diff options
| author | Admiral H. Curtiss <pikachu025@gmail.com> | 2025-02-02 18:02:58 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-02 18:02:58 +0100 |
| commit | 77056ba7b7836d4aff9524058f7829c387a293bf (patch) | |
| tree | 760136081b48212054ab14561a6ca907c83981ba /Source/Core/InputCommon | |
| parent | 017e0b56584e9b01ac231868a31d8bd9fdb27953 (diff) | |
| parent | fb3a727fcc753f298f0c648c8fffc35ca4ae1bec (diff) | |
Merge pull request #13208 from Dentomologist/wiitasinputwindow_update_on_attachment_change
WiiTASInputWindow: Update controls when attachment changes
Diffstat (limited to 'Source/Core/InputCommon')
3 files changed, 92 insertions, 3 deletions
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 |
