move mouse wakeup from SR to VG
[vg.git] / vg_input.c
1 /* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved */
2
3 #include "vg_input.h"
4 #include "vg_loader.h"
5 #include "vg_engine.h"
6 #include "vg_async.h"
7 #include "vg_string.h"
8
9 f32 controller_deadzone = 0.05f;
10
11 struct vg_input vg_input = {
12 .active_controller_index = -2
13 };
14
15 u8 vg_getkey( SDL_Keycode kc )
16 {
17 SDL_Scancode sc = SDL_GetScancodeFromKey( kc );
18 return vg_input.sdl_keys[sc];
19 }
20
21 /*
22 * takes SDL device index, and tries to open that on any free channel
23 */
24 static int vg_open_gamecontroller( Sint32 index )
25 {
26 struct vg_controller *controller = NULL;
27 int vg_id = 0;
28 const char *name = SDL_GameControllerNameForIndex( index );
29 SDL_JoystickID instance_id = SDL_JoystickGetDeviceInstanceID( index );
30
31 if( instance_id == -1 ){
32 vg_error( ". Invalid device index (vg_open_gamecontroller)\n" );
33 return -1;
34 }
35
36 for( int j=0; j<VG_MAX_CONTROLLERS; j++ ){
37 struct vg_controller *esta = &vg_input.controllers[j];
38
39 if( esta->handle ){
40 if( esta->instance_id == instance_id ){
41 vg_warn( " . SDL_JoystickID[%d] is already in open at index #%d\n",
42 esta->instance_id, j );
43 return -1;
44 }
45 }
46 else{
47 if( !controller ){
48 controller = &vg_input.controllers[j];
49 vg_id = j;
50 }
51 }
52 }
53
54 if( controller ){
55 controller->handle = SDL_GameControllerOpen( index );
56 controller->instance_id = instance_id;
57
58 if( controller->handle ){
59 vg_success(
60 " . opened SDL_JoystickID[%d] as controller '%s' at index #%d\n",
61 instance_id, name, vg_id );
62
63 for( u32 i=0; i< SDL_CONTROLLER_BUTTON_MAX; i++ )
64 controller->buttons[i] = 0;
65
66 for( u32 i=0; i< SDL_CONTROLLER_AXIS_MAX; i++ )
67 controller->axises[i] = 0.0f;
68
69 if( vg_input.active_controller_index == -2 ){
70 vg_input.active_controller_index = vg_id;
71 vg_input.display_input_method = k_input_method_controller;
72 vg_input.display_input_type =
73 SDL_GameControllerGetType( controller->handle );
74 }
75
76 return vg_id;
77 }
78 else{
79 vg_error( ". Failed to attach game controller '%s'. Reason: %s\n",
80 name, SDL_GetError() );
81 return -1;
82 }
83 }
84 else{
85 vg_error( ". Too many controllers open! ignoring '%s'\n", name );
86 return -1;
87 }
88 }
89
90 void vg_input_device_event( SDL_Event *ev )
91 {
92 if( ev->type == SDL_CONTROLLERDEVICEADDED ){
93 int is_controller = SDL_IsGameController( ev->cdevice.which );
94 const char *name = SDL_JoystickNameForIndex( ev->cdevice.which );
95
96 Sint32 index = ev->cdevice.which;
97 SDL_JoystickID instance_id = SDL_JoystickGetDeviceInstanceID( index );
98 vg_info( "SDL_CONTROLLERDEVICEADDED | device index: %d, name: '%s'\n",
99 index, name );
100
101 if( is_controller ){
102 vg_open_gamecontroller( index );
103 }
104 }
105 else if( ev->type == SDL_CONTROLLERDEVICEREMOVED ){
106 vg_info( "SDL_CONTROLLERDEVICEREMOVED | instance_id: %d\n",
107 ev->cdevice.which );
108
109 for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
110 struct vg_controller *controller = &vg_input.controllers[i];
111
112 if( controller->handle ){
113 if( controller->instance_id == ev->cdevice.which ){
114 vg_info( " . closing controller at index #%d\n", i );
115 SDL_GameControllerClose( controller->handle );
116 controller->handle = NULL;
117 controller->instance_id = -1;
118
119 if( vg_input.active_controller_index == i ){
120 vg_input.active_controller_index = -1;
121 vg_input.display_input_method = k_input_method_kbm;
122 vg_info( "display_input: k_input_method_kbm\n" );
123 }
124 break;
125 }
126 }
127 }
128 }
129 }
130
131 void vg_input_controller_event( SDL_Event *ev )
132 {
133 if( ev->type == SDL_CONTROLLERAXISMOTION ){
134 for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
135 struct vg_controller *esta = &vg_input.controllers[i];
136
137 if( ev->caxis.which == esta->instance_id ){
138 float value = (float)ev->caxis.value / 32767.0f;
139
140 if( ev->caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ||
141 ev->caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ||
142 ev->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX ||
143 ev->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY )
144 {
145 float deadz = vg_clampf( controller_deadzone, 0.0f, 0.999f ),
146 high = vg_maxf( 0.0f, fabsf(value) - deadz );
147
148 value = vg_signf(value) * (high / (1.0f-deadz));
149 }
150
151 esta->axises[ ev->caxis.axis ] = value;
152 break;
153 }
154 }
155 }
156 else if( ev->type == SDL_CONTROLLERBUTTONDOWN ){
157 struct vg_controller *active = NULL;
158
159 if( vg_input.active_controller_index >= 0 )
160 active = &vg_input.controllers[vg_input.active_controller_index];
161
162 if( !active || (ev->cbutton.which != active->instance_id) ){
163 active = NULL;
164 vg_input.active_controller_index = -1;
165 vg_input.display_input_method = k_input_method_kbm;
166
167 for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
168 if( vg_input.controllers[i].instance_id == ev->cbutton.which ){
169 active = &vg_input.controllers[i];
170 vg_input.active_controller_index = i;
171 vg_input.display_input_type =
172 SDL_GameControllerGetType(active->handle);
173 break;
174 }
175 }
176
177 if( active ){
178 vg_info( "Switching active controller index to #%d\n",
179 vg_input.active_controller_index );
180 }
181 else{
182 vg_error( "Input out of range (SDL_JoystickID#%d)\n",
183 ev->cbutton.which );
184 }
185 }
186
187 if( active ){
188 if( vg_input.display_input_method != k_input_method_controller ){
189 vg_input.display_input_method = k_input_method_controller;
190 vg_info( "display_input: k_input_method_controller\n" );
191 }
192 active->buttons[ ev->cbutton.button ] = 1;
193 }
194 }
195 else if( ev->type == SDL_CONTROLLERBUTTONUP ){
196 for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
197 struct vg_controller *esta = &vg_input.controllers[i];
198
199 if( ev->cbutton.which == esta->instance_id ){
200 esta->buttons[ ev->cbutton.button ] = 0;
201 break;
202 }
203 }
204 }
205 }
206
207 void vg_process_inputs(void)
208 {
209 int count;
210 vg_input.sdl_keys = SDL_GetKeyboardState( &count );
211 vg_input.sdl_mouse = SDL_GetMouseState(NULL,NULL);
212
213 if( vg_input.display_input_method != k_input_method_kbm )
214 {
215 /* check for giving keyboard priority */
216 for( int i=0; i<count; i++ )
217 {
218 if( vg_input.sdl_keys[i] )
219 {
220 vg_input.display_input_method = k_input_method_kbm;
221 vg_info( "display_input: k_input_method_kbm (keyboard %d)\n", i );
222 break;
223 }
224 }
225
226 /* check for giving mouse priority */
227 if( vg_input.sdl_mouse &
228 (SDL_BUTTON(SDL_BUTTON_LEFT)|SDL_BUTTON(SDL_BUTTON_RIGHT)|
229 SDL_BUTTON(SDL_BUTTON_MIDDLE)) )
230 {
231 vg_input.display_input_method = k_input_method_kbm;
232 vg_info( "display_input: k_input_method_kbm (mouse click)\n" );
233 }
234
235 vg_input.hidden_mouse_travel += v2_length( vg.mouse_delta );
236 if( vg_input.hidden_mouse_travel > 64.0f )
237 {
238 vg_input.display_input_method = k_input_method_kbm;
239 vg_input.hidden_mouse_travel = 0.0f;
240 vg_info( "display_input: k_input_method_kbm (mouse move)\n" );
241 }
242 }
243 else
244 vg_input.hidden_mouse_travel = 0.0f;
245 }
246
247 void async_vg_input_init( void *payload, u32 size )
248 {
249 vg_info( "Checking for controllers\n" );
250 SDL_GameControllerAddMappingsFromFile( "gamecontrollerdb.txt" );
251
252 int joy_count = SDL_NumJoysticks();
253 for( int i=0; i<joy_count; i++ ) {
254 const char *name = SDL_JoystickNameForIndex( i );
255 int is_controller = SDL_IsGameController(i);
256
257 vg_info( "%d: %s [controller: %d]\n", i, name, is_controller );
258
259 if( is_controller ){
260 vg_open_gamecontroller( i );
261 }
262 }
263 }
264
265 void vg_input_init(void)
266 {
267 VG_VAR_F32( controller_deadzone, flags=VG_VAR_PERSISTENT );
268 vg_async_call( async_vg_input_init, NULL, 0 );
269 }
270
271 void vg_input_free(void)
272 {
273 for( int i=0; i<VG_MAX_CONTROLLERS; i++ ){
274 struct vg_controller *controller = &vg_input.controllers[i];
275
276 if( controller->handle ){
277 SDL_GameControllerClose( controller->handle );
278 controller->handle = NULL;
279 }
280 }
281 }
282
283 struct vg_controller *vg_active_controller(void)
284 {
285 if( vg_input.active_controller_index >= 0 )
286 return &vg_input.controllers[vg_input.active_controller_index];
287 else
288 return NULL;
289 }
290
291 u8 vg_controller_button( SDL_GameControllerButton button )
292 {
293 struct vg_controller *c = vg_active_controller();
294 if( c ) return c->buttons[ button ];
295 else return 0;
296 }
297
298 f32 vg_controller_axis( SDL_GameControllerAxis axis )
299 {
300 struct vg_controller *c = vg_active_controller();
301 if( c ) return c->axises[ axis ];
302 else return 0;
303 }
304
305 static void vg_input_apply_to_u8( vg_input_op mode, u8 data, u8 *inout_result ){
306 if ( mode == vg_mode_absmax ) *inout_result |= data;
307 else if( mode == vg_mode_mul ) *inout_result &= data;
308 else vg_fatal_error( "mode not supported for destination type (%d)", mode );
309 }
310
311 static void vg_input_apply_to_f32( vg_input_op mode, f32 data,
312 f32 *inout_result ){
313 if ( mode == vg_mode_absmax ){
314 if( fabsf(data) > fabsf(*inout_result) )
315 *inout_result = data;
316 }
317 else if( mode == vg_mode_max ) *inout_result = vg_maxf(*inout_result,data);
318 else if( mode == vg_mode_mul ) *inout_result *= (f32)data;
319 else if( mode == vg_mode_sub ) *inout_result -= (f32)data;
320 else if( mode == vg_mode_add ) *inout_result += (f32)data;
321 else vg_fatal_error( "mode not supported for destination type (%d)", mode );
322 }
323
324 /*
325 * Run an input program. out_result must point to memory with sufficient
326 * storage respective to the size set by type.
327 */
328 void vg_exec_input_program( enum vg_input_type type, vg_input_op *ops,
329 void *out_result ){
330 u8 *out_button = NULL;
331 f32 *out_joy = NULL;
332
333 if( type == k_vg_input_type_button_u8 ){
334 out_button = out_result;
335 *out_button = 0;
336 }
337 else if( type == k_vg_input_type_axis_f32 ){
338 out_joy = out_result;
339 out_joy[0] = 0.0f;
340 }
341 else if( type == k_vg_input_type_joy_v2f ){
342 out_joy = out_result;
343 out_joy[0] = 0.0f;
344 out_joy[1] = 0.0f;
345 }
346
347 /* computer state */
348 vg_input_op mode = vg_mode_absmax;
349 u32 pc = 0, index = 0;
350
351 next_code:;
352 vg_input_op op = ops[ pc ++ ];
353
354 if( (op >= vg_mode_mul) && (op <= vg_mode_max) )
355 mode = op;
356 else if( (op == vg_keyboard) || (op == vg_mouse) || (op == vg_joy_button) ){
357 u8 state = 0;
358
359 if( op == vg_keyboard )
360 state = vg_getkey(ops[pc ++]);
361 else if( op == vg_mouse )
362 state = (vg_input.sdl_mouse & SDL_BUTTON(ops[pc ++]))?1:0;
363 else
364 state = vg_controller_button(ops[pc ++]);
365
366 if( type == k_vg_input_type_button_u8 )
367 vg_input_apply_to_u8( mode, state, out_button );
368 else
369 vg_input_apply_to_f32( mode, (f32)state, &out_joy[index] );
370 }
371 else if( op == vg_joy_axis ){
372 f32 state = vg_controller_axis( ops[pc ++] );
373 if( type == k_vg_input_type_button_u8 )
374 vg_input_apply_to_u8( mode, state>0.5f?1:0, out_button );
375 else
376 vg_input_apply_to_f32( mode, state, &out_joy[index] );
377 }
378 else if( (op == vg_joy_ls) || (op == vg_joy_rs) ){
379 if( type == k_vg_input_type_joy_v2f ){
380 vg_input_apply_to_f32( mode,
381 vg_controller_axis( op==vg_joy_ls? SDL_CONTROLLER_AXIS_LEFTX:
382 SDL_CONTROLLER_AXIS_RIGHTX),
383 &out_joy[0] );
384 vg_input_apply_to_f32( mode,
385 vg_controller_axis( op==vg_joy_ls? SDL_CONTROLLER_AXIS_LEFTY:
386 SDL_CONTROLLER_AXIS_RIGHTY),
387 &out_joy[1] );
388 }
389 }
390 else if( op == vg_index )
391 index = ops[pc ++];
392 else if( op == vg_end )
393 return;
394 else if( op == vg_normalize )
395 v2_normalize( out_joy );
396 else if( op == vg_gui_visible )
397 pc ++;
398 else
399 vg_fatal_error( "unknown op\n" );
400
401 goto next_code;
402 }
403
404 /*
405 * Get vendor specific button glyphs based on SDL button ID
406 */
407 const char *controller_button_str( SDL_GameControllerButton button )
408 {
409 static const char *controller_glyphs[ SDL_CONTROLLER_BUTTON_MAX ][2] = {
410 /* xbox/generic playstation */
411 [ SDL_CONTROLLER_BUTTON_A ] = { KGRN "\x06\x02\x85",KBLU "\x06\x02\x82" },
412 [ SDL_CONTROLLER_BUTTON_B ] = { KRED "\x06\x02\x86",KRED "\x06\x02\x81" },
413 [ SDL_CONTROLLER_BUTTON_X ] = { KBLU "\x06\x02\x83",KMAG "\x06\x02\x7f" },
414 [ SDL_CONTROLLER_BUTTON_Y ] = { KYEL "\x06\x02\x84",KGRN "\x06\x02\x80" },
415 [ SDL_CONTROLLER_BUTTON_LEFTSTICK ] = { "\x87","\x87" },
416 [ SDL_CONTROLLER_BUTTON_RIGHTSTICK ] = { "\x8b","\x8b" },
417 [ SDL_CONTROLLER_BUTTON_LEFTSHOULDER ] = { "\x91","\x91" },
418 [ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ]= { "\x92","\x92" },
419 [ SDL_CONTROLLER_BUTTON_DPAD_LEFT ] = { "\x93","\x93" },
420 [ SDL_CONTROLLER_BUTTON_DPAD_UP ] = { "\x94","\x94" },
421 [ SDL_CONTROLLER_BUTTON_DPAD_RIGHT ] = { "\x95","\x95" },
422 [ SDL_CONTROLLER_BUTTON_DPAD_DOWN ] = { "\x96","\x96" },
423 [ SDL_CONTROLLER_BUTTON_GUIDE ] = { "\x91","\x91" },
424 };
425
426 if( vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS3 ||
427 vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS4 ||
428 vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS5 )
429 {
430 return controller_glyphs[ button ][ 1 ];
431 }
432 else if( vg_input.display_input_type ==
433 SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO ||
434 vg_input.display_input_type ==
435 SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT ||
436 vg_input.display_input_type ==
437 SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR ||
438 vg_input.display_input_type ==
439 SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT )
440 {
441 return NULL;
442 }
443 else
444 return controller_glyphs[ button ][ 0 ];
445 }
446
447 /*
448 * Cat keyboard key string. special_glyphs include SR glyphs
449 */
450 void vg_keyboard_key_string( vg_str *str, u32 key, int special_glyphs )
451 {
452 if( (key >= SDLK_a) && (key <= SDLK_z) ){
453 key = (key-SDLK_a)+(u32)'A';
454 vg_strcatch( str, key );
455 }
456 else if( (key == SDLK_LSHIFT) || (key == SDLK_RSHIFT) )
457 vg_strcat( str, special_glyphs? "\x9e": "shift" );
458 else if( (key == SDLK_LCTRL) || (key == SDLK_RCTRL) )
459 vg_strcat( str, special_glyphs? "\x9f": "ctrl" );
460 else if( (key == SDLK_LALT) || (key == SDLK_RALT) )
461 vg_strcat( str, special_glyphs? "\xa0": "alt" );
462 else if( key == SDLK_SPACE )
463 vg_strcat( str, special_glyphs? "\xa1": "space" );
464 else if( (key == SDLK_RETURN) || (key == SDLK_RETURN2) )
465 vg_strcat( str, special_glyphs? "\xa2": "return" );
466 else if( key == SDLK_ESCAPE )
467 vg_strcat( str, special_glyphs? "\xa3": "escape" );
468 else if( key == SDLK_RIGHT )
469 vg_strcat( str, special_glyphs? "\x95 ": "right" );
470 else if( key == SDLK_LEFT )
471 vg_strcat( str, special_glyphs? "\x93 ": "left" );
472 else if( key == SDLK_UP )
473 vg_strcat( str, special_glyphs? "\x94 ": "up" );
474 else if( key == SDLK_DOWN )
475 vg_strcat( str, special_glyphs? "\x96 ": "down" );
476 else {
477 vg_strcat( str, "keyboard key #" );
478 vg_strcati32( str, key );
479 }
480 }
481
482 /*
483 * Cat mouse button string. special_glyphs include SR glyphs
484 */
485 void vg_mouse_button_string( vg_str *str, u32 button, int special_glyphs )
486 {
487 if ( button == SDL_BUTTON_LEFT )
488 vg_strcat( str, special_glyphs? "\x99": "left mouse" );
489 else if( button == SDL_BUTTON_RIGHT )
490 vg_strcat( str, special_glyphs? "\x9a": "right mouse" );
491 else if( button == SDL_BUTTON_MIDDLE )
492 vg_strcat( str, special_glyphs? "\x9c": "middle mouse" );
493 else{
494 vg_strcat( str, "mouse button #" );
495 vg_strcati32( str, button );
496 }
497 }
498
499 /*
500 * Cat string represeinting single axis
501 */
502 void vg_joy_axis_string( vg_str *str, SDL_GameControllerAxis axis,
503 int special_glyphs )
504 {
505 if( axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT )
506 vg_strcat( str, special_glyphs?"\x8f":"left trigger" );
507 else if( axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT )
508 vg_strcat( str, special_glyphs?"\x90":"right trigger" );
509 else if( axis == SDL_CONTROLLER_AXIS_LEFTX )
510 vg_strcat( str, special_glyphs?"\x88":"left stick horizontal" );
511 else if( axis == SDL_CONTROLLER_AXIS_LEFTY )
512 vg_strcat( str, special_glyphs?"\x89":"left stick vertical" );
513 else if( axis == SDL_CONTROLLER_AXIS_RIGHTX )
514 vg_strcat( str, special_glyphs?"\x8c":"right stick horizontal" );
515 else if( axis == SDL_CONTROLLER_AXIS_RIGHTY )
516 vg_strcat( str, special_glyphs?"\x8d":"right stick vertical" );
517 else{
518 vg_strcat( str, "axis " );
519 vg_strcati32( str, axis );
520 }
521 }
522
523 /*
524 * Cat string represeinting whole joystick
525 */
526 void vg_joy_string( vg_str *str, vg_input_op op, int special_glyphs )
527 {
528 if( op == vg_joy_ls )
529 vg_strcat( str, special_glyphs? "\x87": "left stick" );
530 else
531 vg_strcat( str, special_glyphs? "\x8b": "right stick" );
532 }
533
534 /*
535 * Convert an input program into a readable string
536 */
537 void vg_input_string( vg_str *str, vg_input_op *ops, int glyphs )
538 {
539 u32 pc = 0;
540 int applicable = 0, visible = 1;
541
542 next_code:;
543 vg_input_op op = ops[ pc ++ ];
544
545 if( (op == vg_keyboard) || (op == vg_mouse) ){
546 if( (vg_input.display_input_method == k_input_method_kbm) && visible ){
547 applicable = 1;
548
549 if( op == vg_keyboard )
550 vg_keyboard_key_string( str, ops[pc], glyphs );
551 else
552 vg_mouse_button_string( str, ops[pc], glyphs );
553 }
554 else applicable = 0;
555 pc ++;
556 }
557 else if( (op == vg_joy_button) || (op == vg_joy_axis) ){
558 if( (vg_input.display_input_method == k_input_method_controller)
559 && visible ){
560 applicable = 1;
561
562 if( op == vg_joy_button )
563 vg_strcat( str, controller_button_str(ops[pc]) );
564 else
565 vg_joy_axis_string( str, ops[pc], glyphs );
566 }
567 else applicable = 0;
568 pc ++;
569 }
570 else if( (op == vg_joy_ls) || (op == vg_joy_rs) ){
571 if( (vg_input.display_input_method == k_input_method_controller)
572 && visible ){
573 applicable = 1;
574 vg_joy_string( str, op, glyphs );
575 }
576 else applicable = 0;
577 }
578 else if( op == vg_mode_mul ){
579 if( applicable && visible )
580 vg_strcat( str, " + " );
581 }
582 else if( op == vg_index )
583 pc ++;
584 else if( op == vg_gui_visible )
585 visible = ops[pc++];
586 else if( op == vg_end )
587 return;
588
589 goto next_code;
590 }