diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 43a766053..29e02d9ce 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -22,6 +22,7 @@ set(SRCS configure_debug.cpp configure_dialog.cpp configure_general.cpp + configure_input.cpp game_list.cpp hotkeys.cpp main.cpp @@ -52,6 +53,7 @@ set(HEADERS configure_debug.h configure_dialog.h configure_general.h + configure_input.h game_list.h game_list_p.h hotkeys.h @@ -69,6 +71,7 @@ set(UIS configure_audio.ui configure_debug.ui configure_general.ui + configure_input.ui hotkeys.ui main.ui ) diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index ba7edaff9..aa6c120e3 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -2,15 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include -#include -#include + #include "citra_qt/config.h" #include "citra_qt/ui_settings.h" #include "common/file_util.h" -#include "core/settings.h" Config::Config() { // TODO: Don't hardcode the path; let the frontend decide where to put the config files. @@ -21,7 +18,7 @@ Config::Config() { Reload(); } -static const std::array defaults = { +const std::array defaults = { // directly mapped keys Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h index dd0b2ef0b..2f5724d4d 100644 --- a/src/citra_qt/config.h +++ b/src/citra_qt/config.h @@ -5,6 +5,10 @@ #pragma once #include +#include "core/settings.h" +#include +#include +#include class QSettings; @@ -21,3 +25,4 @@ public: void Reload(); void Save(); }; +extern const std::array defaults; diff --git a/src/citra_qt/configure.ui b/src/citra_qt/configure.ui index e1624bbef..09c2026de 100644 --- a/src/citra_qt/configure.ui +++ b/src/citra_qt/configure.ui @@ -24,7 +24,7 @@ General - + Input @@ -69,6 +69,12 @@
configure_debug.h
1 + + ConfigureInput + QWidget +
configure_input.h
+ 1 +
diff --git a/src/citra_qt/configure_dialog.cpp b/src/citra_qt/configure_dialog.cpp index 2f0317fe0..e6b6d45e0 100644 --- a/src/citra_qt/configure_dialog.cpp +++ b/src/citra_qt/configure_dialog.cpp @@ -27,4 +27,5 @@ void ConfigureDialog::applyConfiguration() { ui->generalTab->applyConfiguration(); ui->audioTab->applyConfiguration(); ui->debugTab->applyConfiguration(); + ui->inputTab->applyConfiguration(); } diff --git a/src/citra_qt/configure_input.cpp b/src/citra_qt/configure_input.cpp new file mode 100644 index 000000000..76b0ee45e --- /dev/null +++ b/src/citra_qt/configure_input.cpp @@ -0,0 +1,178 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. +#include "configure_input.h" + +ConfigureInput::ConfigureInput(QWidget *parent) : + QWidget(parent), + ui(new Ui::ConfigureInput) +{ + ui->setupUi(this); + + //Initialize mapping of input enum to UI button. + input_mapping = { + { std::make_pair(Settings::NativeInput::Values::A, ui->btnFaceA) }, + { std::make_pair(Settings::NativeInput::Values::B, ui->btnFaceB) }, + { std::make_pair(Settings::NativeInput::Values::X, ui->btnFaceX) }, + { std::make_pair(Settings::NativeInput::Values::Y, ui->btnFaceY) }, + { std::make_pair(Settings::NativeInput::Values::L, ui->btnShdrL) }, + { std::make_pair(Settings::NativeInput::Values::R, ui->btnShdrR) }, + { std::make_pair(Settings::NativeInput::Values::ZL, ui->btnShdrZL) }, + { std::make_pair(Settings::NativeInput::Values::ZR, ui->btnShdrZR) }, + { std::make_pair(Settings::NativeInput::Values::START, ui->btnStart) }, + { std::make_pair(Settings::NativeInput::Values::SELECT, ui->btnSelect) }, + { std::make_pair(Settings::NativeInput::Values::HOME, ui->btnHome) }, + { std::make_pair(Settings::NativeInput::Values::DUP, ui->btnDirUp) }, + { std::make_pair(Settings::NativeInput::Values::DDOWN, ui->btnDirDown) }, + { std::make_pair(Settings::NativeInput::Values::DLEFT, ui->btnDirLeft) }, + { std::make_pair(Settings::NativeInput::Values::DRIGHT, ui->btnDirRight) }, + { std::make_pair(Settings::NativeInput::Values::CUP, ui->btnStickUp) }, + { std::make_pair(Settings::NativeInput::Values::CDOWN, ui->btnStickDown) }, + { std::make_pair(Settings::NativeInput::Values::CLEFT, ui->btnStickLeft) }, + { std::make_pair(Settings::NativeInput::Values::CRIGHT, ui->btnStickRight) }, + { std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->btnCircleUp) }, + { std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->btnCircleDown) }, + { std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->btnCircleLeft) }, + { std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->btnCircleRight) }, + }; + + //Attach handle click method to each button click. + for (auto &ent1 : input_mapping) { + connect(ent1.second, &QPushButton::released, this, &ConfigureInput::HandleClick); + } + connect(ui->btnRestoreDefaults, &QPushButton::released, this, &ConfigureInput::RestoreDefaults); + setFocusPolicy(Qt::ClickFocus); + this->setConfiguration(); +} + +ConfigureInput::~ConfigureInput() +{ +} + +///Event handler for all button released() event. +void ConfigureInput::HandleClick() +{ + QPushButton* sender = qobject_cast(QObject::sender()); + sender->setText("[waiting]"); + sender->setFocus(); + grabKeyboard(); + grabMouse(); + changingButton = sender; +} + +///Save all button configurations to settings file +void ConfigureInput::applyConfiguration() +{ + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS - 1; ++i) { + int value = GetKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text()); + Settings::values.input_mappings[Settings::NativeInput::All[i]] = value; + } + Settings::Apply(); +} + +///Load configuration settings into button text +void ConfigureInput::setConfiguration() +{ + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS - 1; ++i) { + QString keyValue = GetKeyName(Settings::values.input_mappings[i]); + input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue); + } +} + +///Handle key press event for input tab when a button is 'waiting'. +void ConfigureInput::keyPressEvent(QKeyEvent *event) +{ + if (changingButton != nullptr && event->key() > 0) + { + keysPressed.push_back(event->key()); + + //Can't save Modifier + Keys yet as input. Will re-enable after settings refactor + /*if (event->key() == Qt::Key_Shift) + return; + + else if (event->key() == Qt::Key_Control) + return; + + else if (event->key() == Qt::Key_Alt) + return; + + else if (event->key() == Qt::Key_Meta) + return; + else*/ + SetKey(); + } +} + +///Set button text to name of key pressed. +void ConfigureInput::SetKey() +{ + QString keyValue = ""; + for (int i : keysPressed) // Will only contain one key until settings refactor + { + keyValue += GetKeyName(i); + } + //RemoveDuplicates(keyValue); + changingButton->setText(keyValue); + + keysPressed.clear(); + releaseKeyboard(); + releaseMouse(); + changingButton = nullptr; +} + +///Convert key ASCII value to its' letter/name +QString ConfigureInput::GetKeyName(int key_code) +{ + if (key_code == Qt::Key_Shift) + return tr("Shift"); + + else if (key_code == Qt::Key_Control) + return tr("Ctrl"); + + else if (key_code == Qt::Key_Alt) + return tr("Alt"); + + else if (key_code == Qt::Key_Meta) + return ""; + else if (key_code == -1) + return ""; + + return QKeySequence(key_code).toString(); +} + +///Convert letter/name of key to its ASCII value. +int ConfigureInput::GetKeyValue(QString text) +{ + if (text == "Shift") + return Qt::Key_Shift; + else if (text == "Ctrl") + return Qt::Key_Control; + else if (text == "Alt") + return Qt::Key_Alt; + else if (text == "Meta") + return -1; + else if (text == "") + return -1; + return QKeySequence(text)[0]; +} + +///Check all inputs for duplicate keys. Clears out any other button with same key as new button. +void ConfigureInput::RemoveDuplicates(QString newValue) +{ + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS - 1; ++i) { + if (changingButton != input_mapping[Settings::NativeInput::Values(i)]) { + QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text(); + if (newValue == oldValue) + input_mapping[Settings::NativeInput::Values(i)]->setText(""); + } + } +} + +///Restore all buttons to their default values. +void ConfigureInput::RestoreDefaults() { + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS - 1; ++i) + { + QString keyValue = GetKeyName(defaults[i].toInt()); + input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue); + } +} \ No newline at end of file diff --git a/src/citra_qt/configure_input.h b/src/citra_qt/configure_input.h new file mode 100644 index 000000000..5e66b04d9 --- /dev/null +++ b/src/citra_qt/configure_input.h @@ -0,0 +1,45 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. +#pragma once +#include + +#include +#include +#include +#include +#include +#include + +#include "citra_qt/config.h" +#include "core/settings.h" +#include "ui_configure_input.h" + +namespace Ui { + class ConfigureInput; +} + +class ConfigureInput : public QWidget +{ + Q_OBJECT + +public: + explicit ConfigureInput(QWidget *parent = 0); + ~ConfigureInput(); + void applyConfiguration(); + +private: + std::unique_ptr ui; + std::map input_mapping; + std::vector keysPressed; + QPushButton* changingButton = nullptr; /// button currently waiting for key press. + + void HandleClick(); + void setConfiguration(); + void SetKey(); + void RemoveDuplicates(QString newValue); + void RestoreDefaults(); + virtual void keyPressEvent(QKeyEvent *event); + QString GetKeyName(int key_code); + int GetKeyValue(QString text); +}; diff --git a/src/citra_qt/configure_input.ui b/src/citra_qt/configure_input.ui new file mode 100644 index 000000000..0324f9396 --- /dev/null +++ b/src/citra_qt/configure_input.ui @@ -0,0 +1,975 @@ + + + ConfigureInput + + + + 0 + 0 + 390 + 457 + + + + ConfigureInput + + + + + 10 + 0 + 181 + 130 + + + + Face Buttons + + + false + + + false + + + + + 10 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + A: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + B: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 10 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + X: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Y: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + + 200 + 0 + 181 + 130 + + + + Directional Pad + + + false + + + false + + + + + 10 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Up: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 10 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Left: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Right: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Down: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + + 10 + 140 + 181 + 130 + + + + Shoulder Buttons + + + false + + + false + + + + + 10 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + L: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + ZR: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + R: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 10 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + ZL: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + + 200 + 140 + 181 + 130 + + + + Circle Pad + + + false + + + false + + + + + 10 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Left: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Down: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Right: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 10 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Up: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + + 10 + 280 + 181 + 130 + + + + C-Stick + + + false + + + false + + + + + 10 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Left: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Down: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Right: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 10 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Up: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + + 200 + 280 + 181 + 130 + + + + System Buttons + + + false + + + false + + + + + 10 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Start: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 100 + 20 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Select: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + 10 + 70 + 71 + 50 + + + + + + 0 + 0 + 51 + 16 + + + + Home: + + + + + + 0 + 20 + 71 + 26 + + + + + + + + + + + + 270 + 420 + 110 + 28 + + + + Restore Defaults + + + + + + + \ No newline at end of file diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 0ed1ffa5a..0398989d0 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -513,6 +513,7 @@ void GMainWindow::OnConfigure() { if (result == QDialog::Accepted) { configureDialog.applyConfiguration(); + render_window->ReloadSetKeymaps(); config->Save(); } }