This commit is contained in:
Eblo 2025-03-20 00:32:23 -03:00 committed by GitHub
commit 7e4d1bbc44
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 163 additions and 2 deletions

View file

@ -95,6 +95,32 @@ static int getControllerButtonArg(VALUE *argv) {
return btn;
}
const char* prefixButton = "pad_";
const char* prefixAxis = "axis_";
static VALUE sourceDescToRubyString(SourceDesc input) {
VALUE inputValue;
switch(input.type) {
case Key:
inputValue = rb_str_new_cstr(SDL_GetScancodeName(input.d.scan));
break;
case CButton:
// Concatenate button prefix to name
inputValue = rb_str_new_cstr(prefixButton);
rb_str_concat(inputValue, rb_str_new_cstr(SDL_GameControllerGetStringForButton(input.d.cb)));
break;
case CAxis:
// Concatenate axis prefix to name
inputValue = rb_str_new_cstr(prefixAxis);
rb_str_concat(inputValue, rb_str_new_cstr(SDL_GameControllerGetStringForAxis(input.d.ca.axis)));
rb_str_concat(inputValue, rb_str_new_cstr(input.d.ca.dir == Negative ? "-" : "+"));
break;
default:
inputValue = Qnil;
}
return inputValue;
}
RB_METHOD(inputPress) {
RB_UNUSED_PARAM;
@ -358,6 +384,113 @@ RB_METHOD(inputControllerPowerLevel) {
return ret;
}
RB_METHOD(inputGetBindings) {
RB_UNUSED_PARAM;
rb_check_argc(argc, 1);
VALUE button;
rb_scan_args(argc, argv, "1", &button);
// Convert Input symbol to the enum used by buttonCodeHash
int num = getButtonArg(&button);
VALUE bindings = rb_ary_new();
BDescVec binds;
shState->rtData().bindingUpdateMsg.get(binds);
for (size_t i = 0; i < binds.size(); ++i)
{
if(binds[i].target != num) continue;
VALUE binding = sourceDescToRubyString(binds[i].src);
rb_ary_push(bindings, binding);
}
return bindings;
}
RB_METHOD(inputApplyBindings) {
RB_UNUSED_PARAM;
rb_check_argc(argc, 2);
VALUE button, inputArray;
rb_scan_args(argc, argv, "11", &button, &inputArray);
// Convert Input symbol to the enum used by buttonCodeHash
Input::ButtonCode num = (Input::ButtonCode) getButtonArg(&button);
BDescVec binds;
shState->rtData().bindingUpdateMsg.get(binds);
// Clear existing bindings for this input
binds.erase(std::remove_if(binds.begin(), binds.end(), [num](BindingDesc x) { return x.target == num; }), binds.end());
// Add new bindings
long length = rb_array_len(inputArray);
for(long i = 0; i < length; i++)
{
VALUE binding = rb_ary_entry(inputArray, i);
BindingDesc newBinding;
newBinding.target = num;
char* bindingString = RSTRING_PTR(binding);
if(strncmp(prefixAxis, bindingString, strlen(prefixAxis)) == 0) {
newBinding.src.type = CAxis;
// Treat last character as direction
size_t len = strlen(bindingString);
newBinding.src.d.ca.dir = (AxisDir) (bindingString[len - 1] == '-' ? Negative : Positive);
// Cut out the direction character
bindingString[len - 1] = '\0';
// Skip the prefix, leaving behind the SDL-compatible axis name
newBinding.src.d.ca.axis = SDL_GameControllerGetAxisFromString(bindingString + strlen(prefixAxis));
// Restore the original direction character in case someone wants to use the information fed into this
bindingString[len - 1] = newBinding.src.d.ca.dir == Negative ? '-' : '+';
} else if(strncmp(prefixButton, bindingString, strlen(prefixButton)) == 0) {
// Gamepad Input
newBinding.src.type = CButton;
// Skip the prefix, leaving behind the SDL-compatible button name
newBinding.src.d.cb = SDL_GameControllerGetButtonFromString(bindingString + strlen(prefixButton));
} else {
// No prefix, assume regular key
newBinding.src.type = Key;
newBinding.src.d.scan = SDL_GetScancodeFromName(bindingString);
}
binds.push_back(newBinding);
}
// Update the bindings in memory
shState->rtData().bindingUpdateMsg.post(binds);
return Qnil;
}
RB_METHOD(inputSaveBindings) {
BDescVec binds;
shState->rtData().bindingUpdateMsg.get(binds);
storeBindings(binds, shState->config());
return Qnil;
}
RB_METHOD(inputResetBindings) {
BDescVec binds = genDefaultBindings(shState->config());
shState->rtData().bindingUpdateMsg.post(binds);
return Qnil;
}
RB_METHOD(inputClearLast) {
shState->eThread().clearLastInput();
return Qnil;
}
RB_METHOD(inputLast) {
RB_UNUSED_PARAM;
SourceDesc lastInput = shState->eThread().getLastInput();
return sourceDescToRubyString(lastInput);
}
#define AXISFUNC(n, ax1, ax2) \
RB_METHOD(inputControllerGet##n##Axis) {\
RB_UNUSED_PARAM;\
@ -621,6 +754,13 @@ void inputBindingInit() {
_rb_define_module_function(module, "clipboard", inputGetClipboard);
_rb_define_module_function(module, "clipboard=", inputSetClipboard);
_rb_define_module_function(module, "last", inputLast);
_rb_define_module_function(module, "clear_last", inputClearLast);
_rb_define_module_function(module, "bindings", inputGetBindings);
_rb_define_module_function(module, "apply_bindings", inputApplyBindings);
_rb_define_module_function(module, "save_bindings", inputSaveBindings);
_rb_define_module_function(module, "reset_bindings", inputResetBindings);
if (rgssVer >= 3) {
VALUE symHash = rb_hash_new();

View file

@ -88,6 +88,7 @@ EventThread::ControllerState EventThread::controllerState;
EventThread::MouseState EventThread::mouseState;
EventThread::TouchState EventThread::touchState;
SDL_atomic_t EventThread::verticalScrollDistance;
SourceDesc lastInputDesc;
/* User event codes */
enum
@ -408,6 +409,8 @@ void EventThread::process(RGSSThreadData &rtData)
}
keyStates[event.key.keysym.scancode] = true;
lastInputDesc.type = Key;
lastInputDesc.d.scan = event.key.keysym.scancode;
break;
case SDL_KEYUP :
@ -426,6 +429,8 @@ void EventThread::process(RGSSThreadData &rtData)
case SDL_CONTROLLERBUTTONDOWN:
controllerState.buttons[event.cbutton.button] = true;
lastInputDesc.type = CButton;
lastInputDesc.d.cb = (SDL_GameControllerButton) event.cbutton.button;
break;
case SDL_CONTROLLERBUTTONUP:
@ -434,6 +439,9 @@ void EventThread::process(RGSSThreadData &rtData)
case SDL_CONTROLLERAXISMOTION:
controllerState.axes[event.caxis.axis] = event.caxis.value;
lastInputDesc.type = CAxis;
lastInputDesc.d.ca.axis = (SDL_GameControllerAxis) event.caxis.axis;
lastInputDesc.d.ca.dir = event.caxis.value < 0 ? Negative : Positive;
break;
case SDL_CONTROLLERDEVICEADDED:
@ -864,6 +872,16 @@ void EventThread::lockText(bool lock)
lock ? SDL_LockMutex(textInputLock) : SDL_UnlockMutex(textInputLock);
}
const SourceDesc EventThread::getLastInput()
{
return lastInputDesc;
}
void EventThread::clearLastInput()
{
lastInputDesc.type = Invalid;
}
void SyncPoint::haltThreads()
{
if (mainSync.locked)

View file

@ -117,6 +117,9 @@ public:
/* Called on game screen (size / offset) changes */
void notifyGameScreenChange(const SDL_Rect &screen);
const SourceDesc getLastInput();
void clearLastInput();
private:
static int eventFilter(void *, SDL_Event*);

View file

@ -28,7 +28,6 @@
#include "util/util.h"
#include <SDL_scancode.h>
#include <SDL_keyboard.h>
#include <SDL_mouse.h>
#include <SDL_clipboard.h>

View file

@ -24,6 +24,7 @@
#include <unordered_map>
#include <SDL_gamecontroller.h>
#include <SDL_keyboard.h>
#include <string>
#include <vector>