mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-03-10 11:37:43 +01:00
Merge pull request #13208 from Dentomologist/wiitasinputwindow_update_on_attachment_change
WiiTASInputWindow: Update controls when attachment changes
This commit is contained in:
commit
77056ba7b7
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -347,32 +347,6 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow(
|
||||
layout->addWidget(m_settings_box);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
if (Core::IsRunning(Core::System::GetInstance()))
|
||||
{
|
||||
m_active_extension = GetWiimote()->GetActiveExtensionNumber();
|
||||
m_is_motion_plus_attached = GetWiimote()->IsMotionPlusAttached();
|
||||
}
|
||||
else
|
||||
{
|
||||
Common::IniFile ini;
|
||||
ini.Load(File::GetUserPath(D_CONFIG_IDX) + "WiimoteNew.ini");
|
||||
const std::string section_name = "Wiimote" + std::to_string(num + 1);
|
||||
|
||||
std::string extension;
|
||||
ini.GetIfExists(section_name, "Extension", &extension);
|
||||
|
||||
if (extension == "Nunchuk")
|
||||
m_active_extension = WiimoteEmu::ExtensionNumber::NUNCHUK;
|
||||
else if (extension == "Classic")
|
||||
m_active_extension = WiimoteEmu::ExtensionNumber::CLASSIC;
|
||||
else
|
||||
m_active_extension = WiimoteEmu::ExtensionNumber::NONE;
|
||||
|
||||
m_is_motion_plus_attached = true;
|
||||
ini.GetIfExists(section_name, "Extension/Attach MotionPlus", &m_is_motion_plus_attached);
|
||||
}
|
||||
UpdateExt();
|
||||
}
|
||||
|
||||
WiimoteEmu::Wiimote* WiiTASInputWindow::GetWiimote()
|
||||
@ -392,7 +366,71 @@ WiimoteEmu::Extension* WiiTASInputWindow::GetExtension()
|
||||
GetAttachments()->GetAttachmentList()[m_active_extension].get());
|
||||
}
|
||||
|
||||
void WiiTASInputWindow::UpdateExt()
|
||||
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 = 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(m_num + 1);
|
||||
|
||||
std::string extension;
|
||||
ini.GetIfExists(section_name, "Extension", &extension);
|
||||
|
||||
if (extension == "Nunchuk")
|
||||
m_active_extension = WiimoteEmu::ExtensionNumber::NUNCHUK;
|
||||
else if (extension == "Classic")
|
||||
m_active_extension = WiimoteEmu::ExtensionNumber::CLASSIC;
|
||||
else
|
||||
m_active_extension = WiimoteEmu::ExtensionNumber::NONE;
|
||||
|
||||
m_is_motion_plus_attached = true;
|
||||
ini.GetIfExists(section_name, "Extension/Attach MotionPlus", &m_is_motion_plus_attached);
|
||||
}
|
||||
|
||||
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); });
|
||||
});
|
||||
}
|
||||
|
||||
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* event)
|
||||
void WiiTASInputWindow::showEvent(QShowEvent* const event)
|
||||
{
|
||||
WiimoteEmu::Wiimote* wiimote = GetWiimote();
|
||||
LoadExtensionAndMotionPlus();
|
||||
|
||||
TASInputWindow::showEvent(event);
|
||||
}
|
||||
|
||||
void WiiTASInputWindow::UpdateInputOverrideFunction()
|
||||
{
|
||||
WiimoteEmu::Wiimote* const wiimote = GetWiimote();
|
||||
|
||||
if (m_active_extension != WiimoteEmu::ExtensionNumber::CLASSIC)
|
||||
wiimote->SetInputOverrideFunction(m_wiimote_overrider.GetInputOverrideFunction());
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user