diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index c34db23c1e..cd933da17a 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -292,9 +292,6 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1 m_extension->attachments.emplace_back(new WiimoteEmu::Drums(m_reg_ext)); m_extension->attachments.emplace_back(new WiimoteEmu::Turntable(m_reg_ext)); - m_extension->boolean_settings.emplace_back( - m_motion_plus_setting = new ControllerEmu::BooleanSetting(_trans("Motion Plus"), false)); - // rumble groups.emplace_back(m_rumble = new ControllerEmu::ControlGroup(_trans("Rumble"))); m_rumble->controls.emplace_back(m_motor = new ControllerEmu::Output(_trans("Motor"))); diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index 7c8841784d..6fc1ebdf0f 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -65,6 +65,7 @@ set(SRCS Config/Mapping/MappingBool.cpp Config/Mapping/MappingButton.cpp Config/Mapping/MappingCommon.cpp + Config/Mapping/MappingIndicator.cpp Config/Mapping/MappingNumeric.cpp Config/Mapping/MappingWidget.cpp Config/Mapping/MappingWindow.cpp diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp index 3e147f33af..4c41a90057 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp @@ -35,6 +35,8 @@ MappingButton::MappingButton(MappingWidget* widget, ControlReference* ref, bool m_reference(ref) { Connect(); + setToolTip( + tr("Left-click to detect input.\nMiddle-click to clear.\nRight-click for more options.")); if (!m_reference->IsInput() || !indicator) return; @@ -116,6 +118,7 @@ void MappingButton::Clear() { m_reference->SetExpression(""); m_parent->SaveSettings(); + Update(); } void MappingButton::Update() @@ -136,7 +139,7 @@ void MappingButton::mouseReleaseEvent(QMouseEvent* event) else emit AdvancedPressed(); return; - case Qt::MouseButton::MiddleButton: + case Qt::MouseButton::MidButton: Clear(); return; case Qt::MouseButton::RightButton: diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingIndicator.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingIndicator.cpp new file mode 100644 index 0000000000..c10a6d9f5c --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingIndicator.cpp @@ -0,0 +1,287 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/MappingIndicator.h" + +#include +#include + +#include +#include + +#include + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" +#include "InputCommon/ControllerEmu/Setting/NumericSetting.h" +#include "InputCommon/ControllerInterface/Device.h" + +#include "DolphinQt2/Settings.h" + +MappingIndicator::MappingIndicator(ControllerEmu::ControlGroup* group) : m_group(group) +{ + setMinimumHeight(128); + + switch (m_group->type) + { + case ControllerEmu::GroupType::Cursor: + BindCursorControls(false); + break; + case ControllerEmu::GroupType::Stick: + BindStickControls(); + break; + case ControllerEmu::GroupType::Tilt: + BindCursorControls(true); + break; + case ControllerEmu::GroupType::MixedTriggers: + BindMixedTriggersControls(); + break; + default: + break; + } + + m_timer = new QTimer(this); + connect(m_timer, &QTimer::timeout, this, [this] { repaint(); }); + m_timer->start(1000 / 30); +} + +void MappingIndicator::BindCursorControls(bool tilt) +{ + m_cursor_up = m_group->controls[0]->control_ref.get(); + m_cursor_down = m_group->controls[1]->control_ref.get(); + m_cursor_left = m_group->controls[2]->control_ref.get(); + m_cursor_right = m_group->controls[3]->control_ref.get(); + + if (!tilt) + { + m_cursor_forward = m_group->controls[4]->control_ref.get(); + m_cursor_backward = m_group->controls[5]->control_ref.get(); + + m_cursor_center = m_group->numeric_settings[0].get(); + m_cursor_width = m_group->numeric_settings[1].get(); + m_cursor_height = m_group->numeric_settings[2].get(); + m_cursor_deadzone = m_group->numeric_settings[3].get(); + } + else + { + m_cursor_deadzone = m_group->numeric_settings[0].get(); + } +} + +void MappingIndicator::BindStickControls() +{ + m_stick_up = m_group->controls[0]->control_ref.get(); + m_stick_down = m_group->controls[1]->control_ref.get(); + m_stick_left = m_group->controls[2]->control_ref.get(); + m_stick_right = m_group->controls[3]->control_ref.get(); + m_stick_modifier = m_group->controls[4]->control_ref.get(); + + m_stick_radius = m_group->numeric_settings[0].get(); + m_stick_deadzone = m_group->numeric_settings[1].get(); +} + +void MappingIndicator::BindMixedTriggersControls() +{ + m_mixed_triggers_l_button = m_group->controls[0]->control_ref.get(); + m_mixed_triggers_r_button = m_group->controls[1]->control_ref.get(); + m_mixed_triggers_l_analog = m_group->controls[2]->control_ref.get(); + m_mixed_triggers_r_analog = m_group->controls[3]->control_ref.get(); + + m_mixed_triggers_threshold = m_group->numeric_settings[0].get(); +} + +static ControlState PollControlState(ControlReference* ref) +{ + Settings::Instance().SetControllerStateNeeded(true); + + auto state = ref->State(); + + Settings::Instance().SetControllerStateNeeded(false); + + if (state != 0) + return state; + else + return 0; +} + +void MappingIndicator::DrawCursor(bool tilt) +{ + float centerx = width() / 2., centery = height() / 2.; + + QPainter p(this); + + float width = 64, height = 64; + float deadzone = m_cursor_deadzone->GetValue() * 48; + + if (!tilt) + { + float depth = centery - PollControlState(m_cursor_forward) * this->height() / 2.5 + + PollControlState(m_cursor_backward) * this->height() / 2.5; + + p.fillRect(0, depth, this->width(), 4, Qt::gray); + + width *= m_cursor_width->GetValue(); + height *= m_cursor_height->GetValue(); + } + + float curx = centerx - 4 - std::min(PollControlState(m_cursor_left), 0.5) * width + + std::min(PollControlState(m_cursor_right), 0.5) * width, + cury = centery - 4 - std::min(PollControlState(m_cursor_up), 0.5) * height + + std::min(PollControlState(m_cursor_down), 0.5) * height; + + // Draw background + p.setBrush(Qt::white); + p.setPen(Qt::black); + p.drawRect(centerx - (width / 2), centery - (height / 2), width, height); + + // Draw deadzone + p.setBrush(Qt::lightGray); + p.drawEllipse(centerx - (deadzone / 2), centery - (deadzone / 2), deadzone, deadzone); + + // Draw cursor + p.fillRect(curx, cury, 8, 8, Qt::red); +} + +void MappingIndicator::DrawStick() +{ + float centerx = width() / 2., centery = height() / 2.; + + bool c_stick = m_group->name == "C-Stick"; + bool classic_controller = m_group->name == "Left Stick" || m_group->name == "Right Stick"; + + float ratio = 1; + + if (c_stick) + ratio = 1.; + else if (classic_controller) + ratio = 0.9f; + + // Polled values + float mod = PollControlState(m_stick_modifier) ? 0.5 : 1; + float radius = m_stick_radius->GetValue(); + float curx = -PollControlState(m_stick_left) + PollControlState(m_stick_right), + cury = -PollControlState(m_stick_up) + PollControlState(m_stick_down); + // The maximum deadzone value covers 50% of the stick area + float deadzone = m_stick_deadzone->GetValue() / 2.; + + // Size parameters + float max_size = (height() / 2.5) / ratio; + float stick_size = (height() / 3.) / ratio; + + // Emulated cursor position + float virt_curx, virt_cury; + + if (abs(curx) < deadzone && abs(cury) < deadzone) + { + virt_curx = virt_cury = 0; + } + else + { + virt_curx = curx * mod; + virt_cury = cury * mod; + } + + // Coordinates for an octagon + std::array radius_octagon = { + QPointF(centerx, centery + stick_size), // Bottom + QPointF(centerx + stick_size / sqrt(2), centery + stick_size / sqrt(2)), // Bottom Right + QPointF(centerx + stick_size, centery), // Right + QPointF(centerx + stick_size / sqrt(2), centery - stick_size / sqrt(2)), // Top Right + QPointF(centerx, centery - stick_size), // Top + QPointF(centerx - stick_size / sqrt(2), centery - stick_size / sqrt(2)), // Top Left + QPointF(centerx - stick_size, centery), // Left + QPointF(centerx - stick_size / sqrt(2), centery + stick_size / sqrt(2)) // Bottom Left + }; + + QPainter p(this); + + // Draw maximum values + p.setBrush(Qt::white); + p.setPen(Qt::black); + p.drawRect(centerx - max_size, centery - max_size, max_size * 2, max_size * 2); + + // Draw radius + p.setBrush(c_stick ? Qt::yellow : Qt::darkGray); + p.drawPolygon(radius_octagon.data(), static_cast(radius_octagon.size())); + + // Draw deadzone + p.setBrush(c_stick ? Qt::darkYellow : Qt::lightGray); + p.drawEllipse(centerx - deadzone * stick_size, centery - deadzone * stick_size, + deadzone * stick_size * 2, deadzone * stick_size * 2); + + // Draw stick + p.setBrush(Qt::black); + p.drawEllipse(centerx - 4 + curx * max_size, centery - 4 + cury * max_size, 8, 8); + + // Draw virtual stick + p.setBrush(Qt::red); + p.drawEllipse(centerx - 4 + virt_curx * max_size * radius, + centery - 4 + virt_cury * max_size * radius, 8, 8); +} + +void MappingIndicator::DrawMixedTriggers() +{ + QPainter p(this); + + // Polled values + double r_analog = PollControlState(m_mixed_triggers_r_analog); + double r_button = PollControlState(m_mixed_triggers_r_button); + double l_analog = PollControlState(m_mixed_triggers_l_analog); + double l_button = PollControlState(m_mixed_triggers_l_button); + double threshold = m_mixed_triggers_threshold->GetValue(); + + double r_bar_percent = r_analog; + double l_bar_percent = l_analog; + + if (r_button && (r_button != r_analog) || (r_button == r_analog) && (r_analog > threshold)) + r_bar_percent = 1; + else + r_bar_percent *= 0.8; + + if (l_button && (l_button != l_analog) || (l_button == l_analog) && (l_analog > threshold)) + l_bar_percent = 1; + else + l_bar_percent *= 0.8; + + p.fillRect(0, 0, width(), 64, Qt::black); + + p.fillRect(0, 0, l_bar_percent * width(), 32, Qt::red); + p.fillRect(0, 32, r_bar_percent * width(), 32, Qt::red); + + p.setPen(Qt::white); + p.drawLine(width() * 0.8, 0, width() * 0.8, 63); + p.drawLine(0, 32, width(), 32); + + p.setPen(Qt::green); + p.drawLine(width() * 0.8 * threshold, 0, width() * 0.8 * threshold, 63); + + p.setBrush(Qt::black); + p.setPen(Qt::white); + p.drawText(width() * 0.225, 16, tr("L-Analog")); + p.drawText(width() * 0.8 + 16, 16, tr("L")); + p.drawText(width() * 0.225, 48, tr("R-Analog")); + p.drawText(width() * 0.8 + 16, 48, tr("R")); +} + +void MappingIndicator::paintEvent(QPaintEvent*) +{ + switch (m_group->type) + { + case ControllerEmu::GroupType::Cursor: + DrawCursor(false); + break; + case ControllerEmu::GroupType::Tilt: + DrawCursor(true); + break; + case ControllerEmu::GroupType::Stick: + DrawStick(); + break; + case ControllerEmu::GroupType::MixedTriggers: + DrawMixedTriggers(); + break; + default: + break; + } +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingIndicator.h b/Source/Core/DolphinQt2/Config/Mapping/MappingIndicator.h new file mode 100644 index 0000000000..c563fb2880 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingIndicator.h @@ -0,0 +1,68 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +namespace ControllerEmu +{ +class Control; +class ControlGroup; +class NumericSetting; +} + +class QPaintEvent; +class QTimer; + +class ControlReference; + +class MappingIndicator : public QWidget +{ +public: + explicit MappingIndicator(ControllerEmu::ControlGroup* group); + +private: + void BindCursorControls(bool tilt); + void BindStickControls(); + void BindMixedTriggersControls(); + + void DrawCursor(bool tilt); + void DrawStick(); + void DrawMixedTriggers(); + + void paintEvent(QPaintEvent*) override; + ControllerEmu::ControlGroup* m_group; + + // Stick settings + ControlReference* m_stick_up; + ControlReference* m_stick_down; + ControlReference* m_stick_left; + ControlReference* m_stick_right; + ControlReference* m_stick_modifier; + + ControllerEmu::NumericSetting* m_stick_radius; + ControllerEmu::NumericSetting* m_stick_deadzone; + + // Cursor settings + ControlReference* m_cursor_up; + ControlReference* m_cursor_down; + ControlReference* m_cursor_left; + ControlReference* m_cursor_right; + ControlReference* m_cursor_forward; + ControlReference* m_cursor_backward; + + ControllerEmu::NumericSetting* m_cursor_center; + ControllerEmu::NumericSetting* m_cursor_width; + ControllerEmu::NumericSetting* m_cursor_height; + ControllerEmu::NumericSetting* m_cursor_deadzone; + + // Triggers settings + ControlReference* m_mixed_triggers_r_analog; + ControlReference* m_mixed_triggers_r_button; + ControlReference* m_mixed_triggers_l_analog; + ControlReference* m_mixed_triggers_l_button; + + ControllerEmu::NumericSetting* m_mixed_triggers_threshold; + + QTimer* m_timer; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWidget.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingWidget.cpp index 5e66b033b0..5c2261de06 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWidget.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWidget.cpp @@ -11,6 +11,7 @@ #include "DolphinQt2/Config/Mapping/IOWindow.h" #include "DolphinQt2/Config/Mapping/MappingBool.h" #include "DolphinQt2/Config/Mapping/MappingButton.h" +#include "DolphinQt2/Config/Mapping/MappingIndicator.h" #include "DolphinQt2/Config/Mapping/MappingNumeric.h" #include "DolphinQt2/Config/Mapping/MappingWindow.h" #include "InputCommon/ControlReference/ControlReference.h" @@ -49,7 +50,8 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con bool need_indicator = group->type == ControllerEmu::GroupType::Cursor || group->type == ControllerEmu::GroupType::Stick || - group->type == ControllerEmu::GroupType::Tilt; + group->type == ControllerEmu::GroupType::Tilt || + group->type == ControllerEmu::GroupType::MixedTriggers; for (auto& control : group->controls) { diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index f708808611..6208321ab6 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -205,6 +205,7 @@ + @@ -272,6 +273,7 @@ +