From fe8bcac270b99b5b2b7aeb0b14b0faf05be533fe Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 13 Jul 2020 21:45:54 +0200 Subject: [PATCH] Qt/input: add tooltips to pad settings --- rpcs3/rpcs3qt/pad_settings_dialog.cpp | 74 +++++++++++++++++++++------ rpcs3/rpcs3qt/pad_settings_dialog.h | 10 ++++ rpcs3/rpcs3qt/tooltips.h | 17 ++++-- 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index adc4598e8a..06a792deb3 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -217,6 +217,9 @@ pad_settings_dialog::pad_settings_dialog(std::shared_ptr gui_setti // Initialize configurable buttons InitButtons(); + // Initialize tooltips + SubscribeTooltips(); + // Repaint controller image ui->l_controller->setPixmap(gui::utils::get_colorized_pixmap(*ui->l_controller->pixmap(), QColor(), gui::utils::get_label_color("l_controller"), false, true)); @@ -867,6 +870,26 @@ bool pad_settings_dialog::eventFilter(QObject* object, QEvent* event) { mouseMoveEvent(static_cast(event)); } + + if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) + { + if (ui->l_description && m_descriptions.contains(object)) + { + if (event->type() == QEvent::Enter) + { + // Check for visibility when entering a widget (needed in case of overlapping widgets in a QStackedWidget for example) + if (const auto widget = qobject_cast(object); widget && widget->isVisible()) + { + ui->l_description->setText(m_descriptions[object]); + } + } + else if (event->type() == QEvent::Leave) + { + ui->l_description->setText(m_description); + } + } + } + return QDialog::eventFilter(object, event); } @@ -1145,45 +1168,44 @@ void pad_settings_dialog::ChangeInputType() Tooltips tooltips; // Change the description - QString description; switch (m_handler->m_type) { case pad_handler::null: if (is_ldd_pad) - description = tooltips.gamepad_settings.ldd_pad; + m_description = tooltips.gamepad_settings.ldd_pad; else - description = tooltips.gamepad_settings.null; + m_description = tooltips.gamepad_settings.null; break; case pad_handler::keyboard: - description = tooltips.gamepad_settings.keyboard; break; + m_description = tooltips.gamepad_settings.keyboard; break; #ifdef _WIN32 case pad_handler::xinput: - description = tooltips.gamepad_settings.xinput; break; + m_description = tooltips.gamepad_settings.xinput; break; case pad_handler::mm: - description = tooltips.gamepad_settings.mmjoy; break; + m_description = tooltips.gamepad_settings.mmjoy; break; case pad_handler::ds3: - description = tooltips.gamepad_settings.ds3_windows; break; + m_description = tooltips.gamepad_settings.ds3_windows; break; case pad_handler::ds4: - description = tooltips.gamepad_settings.ds4_windows; break; + m_description = tooltips.gamepad_settings.ds4_windows; break; #elif __linux__ case pad_handler::ds3: - description = tooltips.gamepad_settings.ds3_linux; break; + m_description = tooltips.gamepad_settings.ds3_linux; break; case pad_handler::ds4: - description = tooltips.gamepad_settings.ds4_linux; break; + m_description = tooltips.gamepad_settings.ds4_linux; break; #else case pad_handler::ds3: - description = tooltips.gamepad_settings.ds3_other; break; + m_description = tooltips.gamepad_settings.ds3_other; break; case pad_handler::ds4: - description = tooltips.gamepad_settings.ds4_other; break; + m_description = tooltips.gamepad_settings.ds4_other; break; #endif #ifdef HAVE_LIBEVDEV case pad_handler::evdev: - description = tooltips.gamepad_settings.evdev; break; + m_description = tooltips.gamepad_settings.evdev; break; #endif default: - description = ""; + m_description = ""; } - ui->l_description->setText(description); + ui->l_description->setText(m_description); // change our contextual widgets ui->left_stack->setCurrentIndex((m_handler->m_type == pad_handler::keyboard) ? 1 : 0); @@ -1588,3 +1610,25 @@ void pad_settings_dialog::ResizeDialog() resize(tabwidget_size + buttons_size + margin_size + spacing_size); setMaximumSize(size()); } + +void pad_settings_dialog::SubscribeTooltip(QObject* object, const QString& tooltip) +{ + m_descriptions[object] = tooltip; + object->installEventFilter(this); +} + +void pad_settings_dialog::SubscribeTooltips() +{ + // Localized tooltips + Tooltips tooltips; + + SubscribeTooltip(ui->gb_squircle, tooltips.gamepad_settings.squircle_factor); + SubscribeTooltip(ui->gb_stick_multi, tooltips.gamepad_settings.stick_multiplier); + SubscribeTooltip(ui->gb_vibration, tooltips.gamepad_settings.vibration); + SubscribeTooltip(ui->gb_sticks, tooltips.gamepad_settings.stick_deadzones); + SubscribeTooltip(ui->gb_stick_preview, tooltips.gamepad_settings.emulated_preview); + SubscribeTooltip(ui->gb_triggers, tooltips.gamepad_settings.trigger_deadzones); + SubscribeTooltip(ui->gb_stick_lerp, tooltips.gamepad_settings.stick_lerp); + SubscribeTooltip(ui->gb_mouse_accel, tooltips.gamepad_settings.mouse_acceleration); + SubscribeTooltip(ui->gb_mouse_dz, tooltips.gamepad_settings.mouse_deadzones); +} diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.h b/rpcs3/rpcs3qt/pad_settings_dialog.h index 376d52f51e..578c251dd9 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.h +++ b/rpcs3/rpcs3qt/pad_settings_dialog.h @@ -108,6 +108,10 @@ private: std::string m_title_id; std::shared_ptr m_gui_settings; + // Tooltips + QString m_description; + QHash m_descriptions; + // Capabilities bool m_enable_buttons{ false }; bool m_enable_rumble{ false }; @@ -185,6 +189,12 @@ private: /** Resizes the dialog. We need to do this because the main scroll area can't determine the size on its own. */ void ResizeDialog(); + /** Register a widget for tooltips */ + void SubscribeTooltip(QObject* object, const QString& tooltip); + + /** Used to keep all tooltip subscriptions in one place. */ + void SubscribeTooltips(); + protected: /** Handle keyboard handler input */ void keyPressEvent(QKeyEvent *keyEvent) override; diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 8941905f2d..7863c6f90c 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -199,15 +199,26 @@ public: { const QString null = tr("This controller is disabled and will appear as disconnected to software. Choose another handler to enable it."); const QString ldd_pad = tr("This port is currently assigned to a custom controller by the application and can't be changed."); - const QString keyboard = tr("While it is possible to use a keyboard as a pad in RPCS3, the use of an actual controller is strongly recommended.\nTo bind mouse movement to a button or joystick, click on the desired button to activate it, then click and hold while dragging the mouse to a direction."); - const QString ds3_windows = tr("In order to use the DualShock 3 handler, you need to install the official DualShock 3 driver first.\nSee the RPCS3 Wiki for instructions."); + const QString keyboard = tr("While it is possible to use a keyboard as a pad in RPCS3, the use of an actual controller is strongly recommended.
To bind mouse movement to a button or joystick, click on the desired button to activate it, then click and hold while dragging the mouse to a direction."); + const QString ds3_windows = tr("In order to use the DualShock 3 handler, you need to install the official DualShock 3 driver first.
See the RPCS3 Wiki for instructions."); const QString ds3_linux = tr("In order to use the DualShock 3 handler, you might need to add udev rules to let RPCS3 access the controller.\nSee the RPCS3 Wiki for instructions."); const QString ds3_other = tr("The DualShock 3 handler is recommended for official DualShock 3 controllers."); const QString ds4_windows = tr("If you have any issues with the DualShock 4 handler, it might be caused by third-party tools such as DS4Windows. It's recommended that you disable them while using this handler."); const QString ds4_linux = tr("In order to use the DualShock 4 handler, you might need to add udev rules to let RPCS3 access the controller.\nSee the RPCS3 Wiki for instructions."); const QString ds4_other = tr("The DualShock 4 handler is recommended for official DualShock 4 controllers."); const QString xinput = tr("The XInput handler will work with Xbox controllers and many third-party PC-compatible controllers. Pressure sensitive buttons from SCP are supported when SCP's XInput1_3.dll is placed in the main RPCS3 directory. For more details, see the RPCS3 Wiki."); - const QString evdev = tr("The evdev handler should work with any controller that has linux support.\nIf your joystick is not being centered properly, read the RPCS3 Wiki for instructions."); + const QString evdev = tr("The evdev handler should work with any controller that has linux support.
If your joystick is not being centered properly, read the RPCS3 Wiki for instructions."); const QString mmjoy = tr("The MMJoystick handler should work with almost any controller recognized by Windows. However, it is recommended that you use the more specific handlers if you have a controller that supports them."); + + const QString squircle_factor = tr("The actual DualShock 3's stick range is not circular but formed like a rounded square (or squircle) which represents the maximum range of the emulated sticks. You can use the squircle values to modify the stick input if your sticks can't reach the corners of that range. A value of 0 does not apply any so called squircling. A value of 8000 is usually recommended."); + const QString stick_multiplier = tr("The stick multipliers can be used to change the sensitivity of your stick movements.
The default setting is 1 and represents normal input."); + const QString stick_deadzones = tr("A stick's deadzone determines how far the stick has to be moved until it is fully recognized by the game. The resulting range will be projected onto the full input range in order to give you a smooth experience. Movement inside the deadzone is actually simulated as a real DualShock 3's deadzone of ~13%, so don't worry if there is still movement shown in the emulated stick preview."); + const QString vibration = tr("The PS3 activates two motors (large and small) to handle controller vibrations.
You can enable, disable or even switch these signals for the currently selected pad here."); + const QString emulated_preview = tr("The emulated stick values (red dots) in the stick preview represent the actual stick positions as they will be visible to the game. The actual DualShock 3's stick range is not circular but formed like a rounded square (or squircle) which represents the maximum range of the emulated sticks. The blue regular dots represent the raw stick values (including stick multipliers) before they are converted for ingame usage."); + const QString trigger_deadzones = tr("A trigger's deadzone determines how far the trigger has to be moved until it is recognized by the game. The resulting range will be projected onto the full input range in order to give you a smooth experience."); + const QString stick_lerp = tr("With keyboards you are inevitably restricted to 8 stick directions (4 straight + 4 diagonal). Furthermore when a key is pressed the stick will jump to the maximum value of the chosen direction immediately. The stick interpolation can be used to work-around both of these issues by smoothening out these directional changes. The lower the value, the longer you have to press or release a key until the maximum amplitude is reached."); + const QString mouse_deadzones = tr("The mouse deadzones represent the games' own deadzones on the x and y axes. Games usually enforce their own deadzones to filter out small unwanted stick movements. In consequence mouse input feels unintuitive since it relies on immediate responsiveness. You can change these values temporarily during gameplay in order to find out the optimal values for your game (Alt+T and Alt+Y for x, Alt+U and Alt+I for y)."); + const QString mouse_acceleration = tr("The mouse acceleration can be used to amplify your mouse movements on the x and y axes. Increase these values if your mouse movements feel too slow while playing a game. You can change these values temporarily during gameplay in order to find out the optimal values (Alt+G and Alt+H for x, Alt+J and Alt+K for y). Keep in mind that modern mice usually provide different modes and settings that can be used to change mouse movement speeds as well."); + } gamepad_settings; };