summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp4
-rw-r--r--Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h4
-rw-r--r--Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp107
-rw-r--r--Source/Core/DolphinQt/TAS/WiiTASInputWindow.h9
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.cpp5
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h3
-rw-r--r--Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h87
7 files changed, 186 insertions, 33 deletions
diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
index 2c510fb394..9d354a4b8e 100644
--- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
@@ -602,9 +602,9 @@ ExtensionNumber Wiimote::GetActiveExtensionNumber() const
return m_active_extension;
}
-bool Wiimote::IsMotionPlusAttached() const
+ControllerEmu::SubscribableSettingValue<bool>& Wiimote::GetMotionPlusSetting()
{
- return m_is_motion_plus_attached;
+ return m_motion_plus_setting;
}
} // namespace WiimoteEmu
diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
index e364ccdb6c..e50a6efbc9 100644
--- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
+++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
@@ -173,7 +173,7 @@ public:
// Active extension number is exposed for TAS.
ExtensionNumber GetActiveExtensionNumber() const;
- bool IsMotionPlusAttached() const;
+ ControllerEmu::SubscribableSettingValue<bool>& GetMotionPlusSetting();
static Common::Vec3
OverrideVec3(const ControllerEmu::ControlGroup* control_group, Common::Vec3 vec,
@@ -308,7 +308,7 @@ private:
ControllerEmu::SettingValue<bool> m_sideways_setting;
ControllerEmu::SettingValue<bool> m_upright_setting;
ControllerEmu::SettingValue<double> m_battery_setting;
- ControllerEmu::SettingValue<bool> m_motion_plus_setting;
+ ControllerEmu::SubscribableSettingValue<bool> m_motion_plus_setting;
ControllerEmu::SettingValue<double> m_fov_x_setting;
ControllerEmu::SettingValue<double> m_fov_y_setting;
diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp
index 08c3431fd8..5afe374608 100644
--- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp
+++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp
@@ -347,17 +347,61 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow(
layout->addWidget(m_settings_box);
setLayout(layout);
+}
+
+WiimoteEmu::Wiimote* WiiTASInputWindow::GetWiimote()
+{
+ return static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(m_num));
+}
+
+ControllerEmu::Attachments* WiiTASInputWindow::GetAttachments()
+{
+ return static_cast<ControllerEmu::Attachments*>(
+ GetWiimote()->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments));
+}
+
+WiimoteEmu::Extension* WiiTASInputWindow::GetExtension()
+{
+ return static_cast<WiimoteEmu::Extension*>(
+ GetAttachments()->GetAttachmentList()[m_active_extension].get());
+}
+
+void WiiTASInputWindow::UpdateExtension(const int extension)
+{
+ const auto new_extension = static_cast<WiimoteEmu::ExtensionNumber>(extension);
+ if (new_extension == m_active_extension)
+ return;
+
+ m_active_extension = new_extension;
+
+ UpdateControlVisibility();
+ UpdateInputOverrideFunction();
+}
+
+void WiiTASInputWindow::UpdateMotionPlus(const bool attached)
+{
+ if (attached == m_is_motion_plus_attached)
+ return;
+
+ m_is_motion_plus_attached = attached;
+
+ UpdateControlVisibility();
+}
+
+void WiiTASInputWindow::LoadExtensionAndMotionPlus()
+{
+ WiimoteEmu::Wiimote* const wiimote = GetWiimote();
if (Core::IsRunning(Core::System::GetInstance()))
{
- m_active_extension = GetWiimote()->GetActiveExtensionNumber();
- m_is_motion_plus_attached = GetWiimote()->IsMotionPlusAttached();
+ m_active_extension = wiimote->GetActiveExtensionNumber();
+ m_is_motion_plus_attached = wiimote->GetMotionPlusSetting().GetValue();
}
else
{
Common::IniFile ini;
ini.Load(File::GetUserPath(D_CONFIG_IDX) + "WiimoteNew.ini");
- const std::string section_name = "Wiimote" + std::to_string(num + 1);
+ const std::string section_name = "Wiimote" + std::to_string(m_num + 1);
std::string extension;
ini.GetIfExists(section_name, "Extension", &extension);
@@ -372,27 +416,21 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow(
m_is_motion_plus_attached = true;
ini.GetIfExists(section_name, "Extension/Attach MotionPlus", &m_is_motion_plus_attached);
}
- UpdateExt();
-}
-
-WiimoteEmu::Wiimote* WiiTASInputWindow::GetWiimote()
-{
- return static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(m_num));
-}
-ControllerEmu::Attachments* WiiTASInputWindow::GetAttachments()
-{
- return static_cast<ControllerEmu::Attachments*>(
- GetWiimote()->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments));
+ UpdateControlVisibility();
+ UpdateInputOverrideFunction();
+
+ m_motion_plus_callback_id =
+ wiimote->GetMotionPlusSetting().AddCallback([this](const bool attached) {
+ QueueOnObject(this, [this, attached] { UpdateMotionPlus(attached); });
+ });
+ m_attachment_callback_id =
+ GetAttachments()->GetAttachmentSetting().AddCallback([this](const int extension_index) {
+ QueueOnObject(this, [this, extension_index] { UpdateExtension(extension_index); });
+ });
}
-WiimoteEmu::Extension* WiiTASInputWindow::GetExtension()
-{
- return static_cast<WiimoteEmu::Extension*>(
- GetAttachments()->GetAttachmentList()[m_active_extension].get());
-}
-
-void WiiTASInputWindow::UpdateExt()
+void WiiTASInputWindow::UpdateControlVisibility()
{
if (m_active_extension == WiimoteEmu::ExtensionNumber::NUNCHUK)
{
@@ -451,17 +489,36 @@ void WiiTASInputWindow::UpdateExt()
m_nunchuk_buttons_box->hide();
m_classic_buttons_box->hide();
}
+
+ // Without these calls, switching between attachments can result in the Stick/IRWidgets being
+ // surrounded by large amounts of empty space in one dimension.
+ adjustSize();
+ resize(sizeHint());
}
-void WiiTASInputWindow::hideEvent(QHideEvent* event)
+void WiiTASInputWindow::hideEvent(QHideEvent* const event)
{
- GetWiimote()->ClearInputOverrideFunction();
+ WiimoteEmu::Wiimote* const wiimote = GetWiimote();
+
+ wiimote->ClearInputOverrideFunction();
+ wiimote->GetMotionPlusSetting().RemoveCallback(m_motion_plus_callback_id);
+
GetExtension()->ClearInputOverrideFunction();
+ GetAttachments()->GetAttachmentSetting().RemoveCallback(m_attachment_callback_id);
+
+ TASInputWindow::hideEvent(event);
+}
+
+void WiiTASInputWindow::showEvent(QShowEvent* const event)
+{
+ LoadExtensionAndMotionPlus();
+
+ TASInputWindow::showEvent(event);
}
-void WiiTASInputWindow::showEvent(QShowEvent* event)
+void WiiTASInputWindow::UpdateInputOverrideFunction()
{
- WiimoteEmu::Wiimote* wiimote = GetWiimote();
+ WiimoteEmu::Wiimote* const wiimote = GetWiimote();
if (m_active_extension != WiimoteEmu::ExtensionNumber::CLASSIC)
wiimote->SetInputOverrideFunction(m_wiimote_overrider.GetInputOverrideFunction());
diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h
index a77c38bb4c..a7a413e864 100644
--- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h
+++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h
@@ -34,15 +34,22 @@ public:
void hideEvent(QHideEvent* event) override;
void showEvent(QShowEvent* event) override;
+ void UpdateExtension(int extension);
+ void UpdateMotionPlus(bool attached);
+
private:
WiimoteEmu::Wiimote* GetWiimote();
ControllerEmu::Attachments* GetAttachments();
WiimoteEmu::Extension* GetExtension();
- void UpdateExt();
+ void LoadExtensionAndMotionPlus();
+ void UpdateControlVisibility();
+ void UpdateInputOverrideFunction();
WiimoteEmu::ExtensionNumber m_active_extension;
+ int m_attachment_callback_id = -1;
bool m_is_motion_plus_attached;
+ int m_motion_plus_callback_id = -1;
int m_num;
InputOverrider m_wiimote_overrider;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.cpp
index 42e1acff5b..b4bb1699c0 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.cpp
@@ -35,6 +35,11 @@ NumericSetting<int>& Attachments::GetSelectionSetting()
return m_selection_setting;
}
+SubscribableSettingValue<int>& Attachments::GetAttachmentSetting()
+{
+ return m_selection_value;
+}
+
const std::vector<std::unique_ptr<EmulatedController>>& Attachments::GetAttachmentList() const
{
return m_attachments;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h
index 7553639396..887231196b 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h
@@ -29,11 +29,12 @@ public:
void SetSelectedAttachment(u32 val);
NumericSetting<int>& GetSelectionSetting();
+ SubscribableSettingValue<int>& GetAttachmentSetting();
const std::vector<std::unique_ptr<EmulatedController>>& GetAttachmentList() const;
private:
- SettingValue<int> m_selection_value;
+ SubscribableSettingValue<int> m_selection_value;
// This is here and not added to the list of numeric_settings because it's serialized differently,
// by string (to be independent from the enum), and visualized differently in the UI.
// For the rest, it's treated similarly to other numeric_settings in the group.
diff --git a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h
index 863e211cae..dbe52576e4 100644
--- a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h
+++ b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h
@@ -3,8 +3,13 @@
#pragma once
+#include <algorithm>
#include <atomic>
+#include <functional>
+#include <mutex>
#include <string>
+#include <utility>
+#include <vector>
#include "Common/CommonTypes.h"
#include "Common/IniFile.h"
@@ -173,7 +178,9 @@ class SettingValue
friend class NumericSetting<T>;
public:
- ValueType GetValue() const
+ virtual ~SettingValue() = default;
+
+ virtual ValueType GetValue() const
{
// Only update dynamic values when the input gate is enabled.
// Otherwise settings will all change to 0 when window focus is lost.
@@ -184,9 +191,11 @@ public:
return m_value;
}
+ ValueType GetCachedValue() const { return m_value; }
+
bool IsSimpleValue() const { return m_input.GetExpression().empty(); }
- void SetValue(ValueType value)
+ virtual void SetValue(const ValueType value)
{
m_value = value;
@@ -202,4 +211,78 @@ private:
mutable InputReference m_input;
};
+template <typename ValueType>
+class SubscribableSettingValue final : public SettingValue<ValueType>
+{
+public:
+ using Base = SettingValue<ValueType>;
+
+ ValueType GetValue() const override
+ {
+ const ValueType cached_value = GetCachedValue();
+ if (IsSimpleValue())
+ return cached_value;
+
+ const ValueType updated_value = Base::GetValue();
+ if (updated_value != cached_value)
+ TriggerCallbacks();
+
+ return updated_value;
+ }
+
+ void SetValue(const ValueType value) override
+ {
+ if (value != GetCachedValue())
+ {
+ Base::SetValue(value);
+ TriggerCallbacks();
+ }
+ else if (!IsSimpleValue())
+ {
+ // The setting has an expression with a cached value equal to the one currently being set.
+ // Don't trigger the callbacks (since the value didn't change), but clear the expression and
+ // make the setting a simple value instead.
+ Base::SetValue(value);
+ }
+ }
+
+ ValueType GetCachedValue() const { return Base::GetCachedValue(); }
+ bool IsSimpleValue() const { return Base::IsSimpleValue(); }
+
+ using SettingChangedCallback = std::function<void(ValueType)>;
+
+ int AddCallback(const SettingChangedCallback& callback)
+ {
+ std::lock_guard lock(m_mutex);
+ const int callback_id = m_next_callback_id;
+ ++m_next_callback_id;
+ m_callback_pairs.emplace_back(callback_id, callback);
+
+ return callback_id;
+ }
+
+ void RemoveCallback(const int id)
+ {
+ std::lock_guard lock(m_mutex);
+ const auto iter = std::ranges::find(m_callback_pairs, id, &IDCallbackPair::first);
+ if (iter != m_callback_pairs.end())
+ m_callback_pairs.erase(iter);
+ }
+
+private:
+ void TriggerCallbacks() const
+ {
+ std::lock_guard lock(m_mutex);
+ const ValueType value = Base::GetValue();
+ for (const auto& pair : m_callback_pairs)
+ pair.second(value);
+ }
+
+ using IDCallbackPair = std::pair<int, SettingChangedCallback>;
+ std::vector<IDCallbackPair> m_callback_pairs;
+ int m_next_callback_id = 0;
+
+ mutable std::mutex m_mutex;
+};
+
} // namespace ControllerEmu