@@ -95,6 +95,32 @@ static int getControllerButtonArg(VALUE *argv) {
95
95
return btn;
96
96
}
97
97
98
+ const char * prefixButton = " pad_" ;
99
+ const char * prefixAxis = " axis_" ;
100
+
101
+ static VALUE sourceDescToRubyString (SourceDesc input) {
102
+ VALUE inputValue;
103
+ switch (input.type ) {
104
+ case Key:
105
+ inputValue = rb_str_new_cstr (SDL_GetScancodeName (input.d .scan ));
106
+ break ;
107
+ case CButton:
108
+ // Concatenate button prefix to name
109
+ inputValue = rb_str_new_cstr (prefixButton);
110
+ rb_str_concat (inputValue, rb_str_new_cstr (SDL_GameControllerGetStringForButton (input.d .cb )));
111
+ break ;
112
+ case CAxis:
113
+ // Concatenate axis prefix to name
114
+ inputValue = rb_str_new_cstr (prefixAxis);
115
+ rb_str_concat (inputValue, rb_str_new_cstr (SDL_GameControllerGetStringForAxis (input.d .ca .axis )));
116
+ rb_str_concat (inputValue, rb_str_new_cstr (input.d .ca .dir == Negative ? " -" : " +" ));
117
+ break ;
118
+ default :
119
+ inputValue = Qnil;
120
+ }
121
+ return inputValue;
122
+ }
123
+
98
124
RB_METHOD (inputPress) {
99
125
RB_UNUSED_PARAM;
100
126
@@ -358,6 +384,113 @@ RB_METHOD(inputControllerPowerLevel) {
358
384
return ret;
359
385
}
360
386
387
+ RB_METHOD (inputGetBindings) {
388
+ RB_UNUSED_PARAM;
389
+
390
+ rb_check_argc (argc, 1 );
391
+
392
+ VALUE button;
393
+ rb_scan_args (argc, argv, " 1" , &button);
394
+ // Convert Input symbol to the enum used by buttonCodeHash
395
+ int num = getButtonArg (&button);
396
+
397
+ VALUE bindings = rb_ary_new ();
398
+
399
+ BDescVec binds;
400
+ shState->rtData ().bindingUpdateMsg .get (binds);
401
+
402
+ for (size_t i = 0 ; i < binds.size (); ++i)
403
+ {
404
+ if (binds[i].target != num) continue ;
405
+
406
+ VALUE binding = sourceDescToRubyString (binds[i].src );
407
+ rb_ary_push (bindings, binding);
408
+ }
409
+
410
+ return bindings;
411
+ }
412
+
413
+ RB_METHOD (inputApplyBindings) {
414
+ RB_UNUSED_PARAM;
415
+
416
+ rb_check_argc (argc, 2 );
417
+
418
+ VALUE button, inputArray;
419
+ rb_scan_args (argc, argv, " 11" , &button, &inputArray);
420
+
421
+ // Convert Input symbol to the enum used by buttonCodeHash
422
+ Input::ButtonCode num = (Input::ButtonCode) getButtonArg (&button);
423
+
424
+ BDescVec binds;
425
+ shState->rtData ().bindingUpdateMsg .get (binds);
426
+
427
+ // Clear existing bindings for this input
428
+ binds.erase (std::remove_if (binds.begin (), binds.end (), [num](BindingDesc x) { return x.target == num; }), binds.end ());
429
+
430
+ // Add new bindings
431
+ long length = rb_array_len (inputArray);
432
+ for (long i = 0 ; i < length; i++)
433
+ {
434
+ VALUE binding = rb_ary_entry (inputArray, i);
435
+ BindingDesc newBinding;
436
+ newBinding.target = num;
437
+
438
+ char * bindingString = RSTRING_PTR (binding);
439
+ if (strncmp (prefixAxis, bindingString, strlen (prefixAxis)) == 0 ) {
440
+ newBinding.src .type = CAxis;
441
+ // Treat last character as direction
442
+ size_t len = strlen (bindingString);
443
+ newBinding.src .d .ca .dir = (AxisDir) (bindingString[len - 1 ] == ' -' ? Negative : Positive);
444
+ // Cut out the direction character
445
+ bindingString[len - 1 ] = ' \0 ' ;
446
+ // Skip the prefix, leaving behind the SDL-compatible axis name
447
+ newBinding.src .d .ca .axis = SDL_GameControllerGetAxisFromString (bindingString + strlen (prefixAxis));
448
+ // Restore the original direction character in case someone wants to use the information fed into this
449
+ bindingString[len - 1 ] = newBinding.src .d .ca .dir == Negative ? ' -' : ' +' ;
450
+ } else if (strncmp (prefixButton, bindingString, strlen (prefixButton)) == 0 ) {
451
+ // Gamepad Input
452
+ newBinding.src .type = CButton;
453
+ // Skip the prefix, leaving behind the SDL-compatible button name
454
+ newBinding.src .d .cb = SDL_GameControllerGetButtonFromString (bindingString + strlen (prefixButton));
455
+ } else {
456
+ // No prefix, assume regular key
457
+ newBinding.src .type = Key;
458
+ newBinding.src .d .scan = SDL_GetScancodeFromName (bindingString);
459
+ }
460
+ binds.push_back (newBinding);
461
+ }
462
+
463
+ // Update the bindings in memory
464
+ shState->rtData ().bindingUpdateMsg .post (binds);
465
+
466
+ return Qnil;
467
+ }
468
+
469
+ RB_METHOD (inputSaveBindings) {
470
+ BDescVec binds;
471
+ shState->rtData ().bindingUpdateMsg .get (binds);
472
+ storeBindings (binds, shState->config ());
473
+ return Qnil;
474
+ }
475
+
476
+ RB_METHOD (inputResetBindings) {
477
+ BDescVec binds = genDefaultBindings (shState->config ());
478
+ shState->rtData ().bindingUpdateMsg .post (binds);
479
+ return Qnil;
480
+ }
481
+
482
+ RB_METHOD (inputClearLast) {
483
+ shState->eThread ().clearLastInput ();
484
+ return Qnil;
485
+ }
486
+
487
+ RB_METHOD (inputLast) {
488
+ RB_UNUSED_PARAM;
489
+
490
+ SourceDesc lastInput = shState->eThread ().getLastInput ();
491
+ return sourceDescToRubyString (lastInput);
492
+ }
493
+
361
494
#define AXISFUNC (n, ax1, ax2 ) \
362
495
RB_METHOD (inputControllerGet##n##Axis) {\
363
496
RB_UNUSED_PARAM;\
@@ -620,6 +753,13 @@ void inputBindingInit() {
620
753
621
754
_rb_define_module_function (module, " clipboard" , inputGetClipboard);
622
755
_rb_define_module_function (module, " clipboard=" , inputSetClipboard);
756
+
757
+ _rb_define_module_function (module, " last" , inputLast);
758
+ _rb_define_module_function (module, " clear_last" , inputClearLast);
759
+ _rb_define_module_function (module, " bindings" , inputGetBindings);
760
+ _rb_define_module_function (module, " apply_bindings" , inputApplyBindings);
761
+ _rb_define_module_function (module, " save_bindings" , inputSaveBindings);
762
+ _rb_define_module_function (module, " reset_bindings" , inputResetBindings);
623
763
624
764
if (rgssVer >= 3 ) {
625
765
VALUE symHash = rb_hash_new ();
0 commit comments