#include #include #include bool QueryDevices(void *userdata, SDL_Event *event); bool PollGamepad(void *userdata, SDL_Event *event); InputSettings::InputSettings(nlohmann::json &settings) : settings(settings) { int i = 0; for(auto& kb : kbButtons) { auto field = JSONGetField(settings, "input", kb.getName()); kb.setLabel(field != "" ? field : "##unsetButton" + std::to_string(i++)); } devices.addItem({"Keyboard/Mouse"}); SDL_InitSubSystem(SDL_INIT_GAMEPAD); SDL_AddEventWatch(QueryDevices, this); SDL_AddEventWatch(PollGamepad, this); } bool InputSettings::render() { if(devices.render()) { auto currentlySelectedDevice = devices.getCurrentlySelected(); JSONSetField(settings, "input", "Device", currentlySelectedDevice); selectedDeviceIsNotKeyboard = currentlySelectedDevice == "Keyboard/Mouse"; modified = true; } int i = 0; for(auto& kb : kbButtons) { if(kb.render()) { devices.setEnabled(false); for (auto &otherKb : kbButtons) { otherKb.setEnabled(false); } whichGrabbing = i; } if((i % 2 == 0) || i == 0) // only go down every 2 buttons... just... i like it this way ImGui::SameLine(); i++; } return modified; } std::array InputSettings::GetMappedKeys() { std::array ret{}; int i = 0; for (auto& kb : kbButtons) { ret[i++] = SDL_GetKeyFromName(kb.getLabel().c_str()); } return ret; } bool QueryDevices(void *userdata, SDL_Event *event) { auto _this = (InputSettings*)userdata; if (!_this->devices.isEnabled()) return false; switch (event->type) { case SDL_EVENT_GAMEPAD_ADDED: { const auto index = event->gdevice.which; const auto gamepad = SDL_OpenGamepad(index); Util::info("Found controller!"); const auto serial = SDL_GetGamepadSerial(gamepad); const auto name = SDL_GetGamepadName(gamepad); const auto path = SDL_GetGamepadPath(gamepad); if (name) { if (!_this->gamepadIndexes.contains(index)) { _this->gamepadIndexes[index] = name; } _this->devices.addItem({name}); } else if (serial) { if (!_this->gamepadIndexes.contains(index)) { _this->gamepadIndexes[index] = serial; } _this->devices.addItem({serial}); } else if (path) { if (!_this->gamepadIndexes.contains(index)) { _this->gamepadIndexes[index] = path; } _this->devices.addItem({path}); } SDL_CloseGamepad(gamepad); } return true; case SDL_EVENT_GAMEPAD_REMOVED: { const auto index = event->gdevice.which; if (_this->gamepadIndexes.contains(index)) _this->devices.removeItem(_this->gamepadIndexes[index]); } return true; default: return false; } } bool PollGamepad(void *userdata, SDL_Event *event) { auto _this = (InputSettings*)userdata; switch (event->type) { case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { if (!_this->selectedDeviceIsNotKeyboard) return false; const auto k = SDL_GetGamepadStringForButton(static_cast(event->gbutton.button)); JSONSetField(_this->settings, "input", _this->kbButtons[_this->whichGrabbing].getName(), k); _this->kbButtons[_this->whichGrabbing].setLabel(k); _this->devices.setEnabled(true); for (auto &kbButton : _this->kbButtons) { kbButton.setEnabled(true); } _this->grabbing = false; _this->whichGrabbing = -1; _this->modified = true; } return true; case SDL_EVENT_KEY_DOWN: { if (_this->selectedDeviceIsNotKeyboard) return false; const auto k = SDL_GetKeyName(event->key.key); JSONSetField(_this->settings, "input", _this->kbButtons[_this->whichGrabbing].getName(), k); _this->kbButtons[_this->whichGrabbing].setLabel(k); _this->devices.setEnabled(true); for (auto &kbButton : _this->kbButtons) { kbButton.setEnabled(true); } _this->grabbing = false; _this->whichGrabbing = -1; _this->modified = true; } return true; default: return false; } }