Merge pull request #6040 from german77/toggleKeyboard
Enable toggle buttons for keyboard and mouse
This commit is contained in:
commit
827dcad26e
|
@ -12,20 +12,39 @@ namespace InputCommon {
|
|||
|
||||
class KeyButton final : public Input::ButtonDevice {
|
||||
public:
|
||||
explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_)
|
||||
: key_button_list(std::move(key_button_list_)) {}
|
||||
explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_, bool toggle_)
|
||||
: key_button_list(std::move(key_button_list_)), toggle(toggle_) {}
|
||||
|
||||
~KeyButton() override;
|
||||
|
||||
bool GetStatus() const override {
|
||||
if (toggle) {
|
||||
return toggled_status.load(std::memory_order_relaxed);
|
||||
}
|
||||
return status.load();
|
||||
}
|
||||
|
||||
void ToggleButton() {
|
||||
if (lock) {
|
||||
return;
|
||||
}
|
||||
lock = true;
|
||||
const bool old_toggle_status = toggled_status.load();
|
||||
toggled_status.store(!old_toggle_status);
|
||||
}
|
||||
|
||||
void UnlockButton() {
|
||||
lock = false;
|
||||
}
|
||||
|
||||
friend class KeyButtonList;
|
||||
|
||||
private:
|
||||
std::shared_ptr<KeyButtonList> key_button_list;
|
||||
std::atomic<bool> status{false};
|
||||
std::atomic<bool> toggled_status{false};
|
||||
bool lock{false};
|
||||
const bool toggle;
|
||||
};
|
||||
|
||||
struct KeyButtonPair {
|
||||
|
@ -51,6 +70,11 @@ public:
|
|||
for (const KeyButtonPair& pair : list) {
|
||||
if (pair.key_code == key_code) {
|
||||
pair.key_button->status.store(pressed);
|
||||
if (pressed) {
|
||||
pair.key_button->ToggleButton();
|
||||
} else {
|
||||
pair.key_button->UnlockButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +99,8 @@ KeyButton::~KeyButton() {
|
|||
|
||||
std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
|
||||
const int key_code = params.Get("code", 0);
|
||||
std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list);
|
||||
const bool toggle = params.Get("toggle", false);
|
||||
std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list, toggle);
|
||||
key_button_list->AddKeyButton(key_code, button.get());
|
||||
return button;
|
||||
}
|
||||
|
|
|
@ -162,6 +162,42 @@ void Mouse::EndConfiguration() {
|
|||
configuring = false;
|
||||
}
|
||||
|
||||
bool Mouse::ToggleButton(std::size_t button_) {
|
||||
if (button_ >= mouse_info.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto button = 1U << button_;
|
||||
const bool button_state = (toggle_buttons & button) != 0;
|
||||
const bool button_lock = (lock_buttons & button) != 0;
|
||||
|
||||
if (button_lock) {
|
||||
return button_state;
|
||||
}
|
||||
|
||||
lock_buttons |= static_cast<u16>(button);
|
||||
|
||||
if (button_state) {
|
||||
toggle_buttons &= static_cast<u16>(0xFF - button);
|
||||
} else {
|
||||
toggle_buttons |= static_cast<u16>(button);
|
||||
}
|
||||
|
||||
return !button_state;
|
||||
}
|
||||
|
||||
bool Mouse::UnlockButton(std::size_t button_) {
|
||||
if (button_ >= mouse_info.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto button = 1U << button_;
|
||||
const bool button_state = (toggle_buttons & button) != 0;
|
||||
|
||||
lock_buttons &= static_cast<u16>(0xFF - button);
|
||||
|
||||
return button_state;
|
||||
}
|
||||
|
||||
Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() {
|
||||
return mouse_queue;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,9 @@ public:
|
|||
*/
|
||||
void ReleaseButton(MouseButton button_);
|
||||
|
||||
[[nodiscard]] bool ToggleButton(std::size_t button_);
|
||||
[[nodiscard]] bool UnlockButton(std::size_t button_);
|
||||
|
||||
[[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue();
|
||||
[[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const;
|
||||
|
||||
|
@ -94,6 +97,8 @@ private:
|
|||
};
|
||||
|
||||
u16 buttons{};
|
||||
u16 toggle_buttons{};
|
||||
u16 lock_buttons{};
|
||||
std::thread update_thread;
|
||||
MouseButton last_button{MouseButton::Undefined};
|
||||
std::array<MouseInfo, 7> mouse_info;
|
||||
|
|
|
@ -14,16 +14,25 @@ namespace InputCommon {
|
|||
|
||||
class MouseButton final : public Input::ButtonDevice {
|
||||
public:
|
||||
explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_)
|
||||
: button(button_), mouse_input(mouse_input_) {}
|
||||
explicit MouseButton(u32 button_, bool toggle_, MouseInput::Mouse* mouse_input_)
|
||||
: button(button_), toggle(toggle_), mouse_input(mouse_input_) {}
|
||||
|
||||
bool GetStatus() const override {
|
||||
return mouse_input->GetMouseState(button).pressed;
|
||||
const bool button_state = mouse_input->GetMouseState(button).pressed;
|
||||
if (!toggle) {
|
||||
return button_state;
|
||||
}
|
||||
|
||||
if (button_state) {
|
||||
return mouse_input->ToggleButton(button);
|
||||
}
|
||||
return mouse_input->UnlockButton(button);
|
||||
}
|
||||
|
||||
private:
|
||||
const u32 button;
|
||||
const MouseInput::Mouse* mouse_input;
|
||||
const bool toggle;
|
||||
MouseInput::Mouse* mouse_input;
|
||||
};
|
||||
|
||||
MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
|
||||
|
@ -32,8 +41,9 @@ MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_
|
|||
std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
|
||||
const Common::ParamPackage& params) {
|
||||
const auto button_id = params.Get("button", 0);
|
||||
const auto toggle = params.Get("toggle", false);
|
||||
|
||||
return std::make_unique<MouseButton>(button_id, mouse_input.get());
|
||||
return std::make_unique<MouseButton>(button_id, toggle, mouse_input.get());
|
||||
}
|
||||
|
||||
Common::ParamPackage MouseButtonFactory::GetNextInput() const {
|
||||
|
|
|
@ -376,12 +376,16 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
|
|||
}
|
||||
|
||||
void GRenderWindow::keyPressEvent(QKeyEvent* event) {
|
||||
if (!event->isAutoRepeat()) {
|
||||
input_subsystem->GetKeyboard()->PressKey(event->key());
|
||||
}
|
||||
}
|
||||
|
||||
void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
|
||||
if (!event->isAutoRepeat()) {
|
||||
input_subsystem->GetKeyboard()->ReleaseKey(event->key());
|
||||
}
|
||||
}
|
||||
|
||||
MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
|
||||
switch (button) {
|
||||
|
|
|
@ -105,7 +105,9 @@ QString ButtonToText(const Common::ParamPackage& param) {
|
|||
}
|
||||
|
||||
if (param.Get("engine", "") == "keyboard") {
|
||||
return GetKeyName(param.Get("code", 0));
|
||||
const QString button_str = GetKeyName(param.Get("code", 0));
|
||||
const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
|
||||
return QObject::tr("%1%2").arg(toggle, button_str);
|
||||
}
|
||||
|
||||
if (param.Get("engine", "") == "gcpad") {
|
||||
|
@ -157,7 +159,8 @@ QString ButtonToText(const Common::ParamPackage& param) {
|
|||
if (param.Get("engine", "") == "mouse") {
|
||||
if (param.Has("button")) {
|
||||
const QString button_str = QString::number(int(param.Get("button", 0)));
|
||||
return QObject::tr("Click %1").arg(button_str);
|
||||
const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
|
||||
return QObject::tr("%1Click %2").arg(toggle, button_str);
|
||||
}
|
||||
return GetKeyName(param.Get("code", 0));
|
||||
}
|
||||
|
@ -301,6 +304,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
buttons_param[button_id].Clear();
|
||||
button_map[button_id]->setText(tr("[not set]"));
|
||||
});
|
||||
context_menu.addAction(tr("Toggle button"), [&] {
|
||||
const bool toggle_value = !buttons_param[button_id].Get("toggle", false);
|
||||
buttons_param[button_id].Set("toggle", toggle_value);
|
||||
button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
|
||||
});
|
||||
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
|
||||
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||
});
|
||||
|
@ -413,6 +421,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
analogs_param[analog_id].Set("modifier", "");
|
||||
analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
|
||||
});
|
||||
context_menu.addAction(tr("Toggle button"), [&] {
|
||||
Common::ParamPackage modifier_param =
|
||||
Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")};
|
||||
const bool toggle_value = !modifier_param.Get("toggle", false);
|
||||
modifier_param.Set("toggle", toggle_value);
|
||||
analogs_param[analog_id].Set("modifier", modifier_param.Serialize());
|
||||
analog_map_modifier_button[analog_id]->setText(
|
||||
ButtonToText(modifier_param));
|
||||
});
|
||||
context_menu.exec(
|
||||
analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
|
||||
});
|
||||
|
|
Reference in New Issue