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;
|
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
|
} // namespace WiimoteEmu
|
||||||
|
@ -173,7 +173,7 @@ public:
|
|||||||
|
|
||||||
// Active extension number is exposed for TAS.
|
// Active extension number is exposed for TAS.
|
||||||
ExtensionNumber GetActiveExtensionNumber() const;
|
ExtensionNumber GetActiveExtensionNumber() const;
|
||||||
bool IsMotionPlusAttached() const;
|
ControllerEmu::SubscribableSettingValue<bool>& GetMotionPlusSetting();
|
||||||
|
|
||||||
static Common::Vec3
|
static Common::Vec3
|
||||||
OverrideVec3(const ControllerEmu::ControlGroup* control_group, Common::Vec3 vec,
|
OverrideVec3(const ControllerEmu::ControlGroup* control_group, Common::Vec3 vec,
|
||||||
@ -308,7 +308,7 @@ private:
|
|||||||
ControllerEmu::SettingValue<bool> m_sideways_setting;
|
ControllerEmu::SettingValue<bool> m_sideways_setting;
|
||||||
ControllerEmu::SettingValue<bool> m_upright_setting;
|
ControllerEmu::SettingValue<bool> m_upright_setting;
|
||||||
ControllerEmu::SettingValue<double> m_battery_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_x_setting;
|
||||||
ControllerEmu::SettingValue<double> m_fov_y_setting;
|
ControllerEmu::SettingValue<double> m_fov_y_setting;
|
||||||
|
|
||||||
|
@ -347,32 +347,6 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow(
|
|||||||
layout->addWidget(m_settings_box);
|
layout->addWidget(m_settings_box);
|
||||||
|
|
||||||
setLayout(layout);
|
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()
|
WiimoteEmu::Wiimote* WiiTASInputWindow::GetWiimote()
|
||||||
@ -392,7 +366,71 @@ WiimoteEmu::Extension* WiiTASInputWindow::GetExtension()
|
|||||||
GetAttachments()->GetAttachmentList()[m_active_extension].get());
|
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)
|
if (m_active_extension == WiimoteEmu::ExtensionNumber::NUNCHUK)
|
||||||
{
|
{
|
||||||
@ -451,17 +489,36 @@ void WiiTASInputWindow::UpdateExt()
|
|||||||
m_nunchuk_buttons_box->hide();
|
m_nunchuk_buttons_box->hide();
|
||||||
m_classic_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();
|
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)
|
if (m_active_extension != WiimoteEmu::ExtensionNumber::CLASSIC)
|
||||||
wiimote->SetInputOverrideFunction(m_wiimote_overrider.GetInputOverrideFunction());
|
wiimote->SetInputOverrideFunction(m_wiimote_overrider.GetInputOverrideFunction());
|
||||||
|
@ -34,15 +34,22 @@ public:
|
|||||||
void hideEvent(QHideEvent* event) override;
|
void hideEvent(QHideEvent* event) override;
|
||||||
void showEvent(QShowEvent* event) override;
|
void showEvent(QShowEvent* event) override;
|
||||||
|
|
||||||
|
void UpdateExtension(int extension);
|
||||||
|
void UpdateMotionPlus(bool attached);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WiimoteEmu::Wiimote* GetWiimote();
|
WiimoteEmu::Wiimote* GetWiimote();
|
||||||
ControllerEmu::Attachments* GetAttachments();
|
ControllerEmu::Attachments* GetAttachments();
|
||||||
WiimoteEmu::Extension* GetExtension();
|
WiimoteEmu::Extension* GetExtension();
|
||||||
|
|
||||||
void UpdateExt();
|
void LoadExtensionAndMotionPlus();
|
||||||
|
void UpdateControlVisibility();
|
||||||
|
void UpdateInputOverrideFunction();
|
||||||
|
|
||||||
WiimoteEmu::ExtensionNumber m_active_extension;
|
WiimoteEmu::ExtensionNumber m_active_extension;
|
||||||
|
int m_attachment_callback_id = -1;
|
||||||
bool m_is_motion_plus_attached;
|
bool m_is_motion_plus_attached;
|
||||||
|
int m_motion_plus_callback_id = -1;
|
||||||
int m_num;
|
int m_num;
|
||||||
|
|
||||||
InputOverrider m_wiimote_overrider;
|
InputOverrider m_wiimote_overrider;
|
||||||
|
@ -35,6 +35,11 @@ NumericSetting<int>& Attachments::GetSelectionSetting()
|
|||||||
return m_selection_setting;
|
return m_selection_setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubscribableSettingValue<int>& Attachments::GetAttachmentSetting()
|
||||||
|
{
|
||||||
|
return m_selection_value;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::unique_ptr<EmulatedController>>& Attachments::GetAttachmentList() const
|
const std::vector<std::unique_ptr<EmulatedController>>& Attachments::GetAttachmentList() const
|
||||||
{
|
{
|
||||||
return m_attachments;
|
return m_attachments;
|
||||||
|
@ -29,11 +29,12 @@ public:
|
|||||||
void SetSelectedAttachment(u32 val);
|
void SetSelectedAttachment(u32 val);
|
||||||
|
|
||||||
NumericSetting<int>& GetSelectionSetting();
|
NumericSetting<int>& GetSelectionSetting();
|
||||||
|
SubscribableSettingValue<int>& GetAttachmentSetting();
|
||||||
|
|
||||||
const std::vector<std::unique_ptr<EmulatedController>>& GetAttachmentList() const;
|
const std::vector<std::unique_ptr<EmulatedController>>& GetAttachmentList() const;
|
||||||
|
|
||||||
private:
|
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,
|
// 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.
|
// 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.
|
// For the rest, it's treated similarly to other numeric_settings in the group.
|
||||||
|
@ -3,8 +3,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
@ -173,7 +178,9 @@ class SettingValue
|
|||||||
friend class NumericSetting<T>;
|
friend class NumericSetting<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ValueType GetValue() const
|
virtual ~SettingValue() = default;
|
||||||
|
|
||||||
|
virtual ValueType GetValue() const
|
||||||
{
|
{
|
||||||
// Only update dynamic values when the input gate is enabled.
|
// Only update dynamic values when the input gate is enabled.
|
||||||
// Otherwise settings will all change to 0 when window focus is lost.
|
// Otherwise settings will all change to 0 when window focus is lost.
|
||||||
@ -184,9 +191,11 @@ public:
|
|||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueType GetCachedValue() const { return m_value; }
|
||||||
|
|
||||||
bool IsSimpleValue() const { return m_input.GetExpression().empty(); }
|
bool IsSimpleValue() const { return m_input.GetExpression().empty(); }
|
||||||
|
|
||||||
void SetValue(ValueType value)
|
virtual void SetValue(const ValueType value)
|
||||||
{
|
{
|
||||||
m_value = value;
|
m_value = value;
|
||||||
|
|
||||||
@ -202,4 +211,78 @@ private:
|
|||||||
mutable InputReference m_input;
|
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
|
} // namespace ControllerEmu
|
||||||
|
Loading…
x
Reference in New Issue
Block a user