mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Merge pull request #4010 from leoetlino/relative-input
Add relative input for the Wiimote IR
This commit is contained in:
@ -18,6 +18,7 @@
|
|||||||
#include <wx/control.h>
|
#include <wx/control.h>
|
||||||
#include <wx/dcmemory.h>
|
#include <wx/dcmemory.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
|
#include <wx/event.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/listbox.h>
|
#include <wx/listbox.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
@ -110,6 +111,10 @@ PadSettingCheckBox::PadSettingCheckBox(wxWindow* const parent,
|
|||||||
void PadSettingCheckBox::UpdateGUI()
|
void PadSettingCheckBox::UpdateGUI()
|
||||||
{
|
{
|
||||||
((wxCheckBox*)wxcontrol)->SetValue(setting->GetValue());
|
((wxCheckBox*)wxcontrol)->SetValue(setting->GetValue());
|
||||||
|
// Force WX to trigger an event after updating the value
|
||||||
|
wxCommandEvent event(wxEVT_CHECKBOX);
|
||||||
|
event.SetEventObject(wxcontrol);
|
||||||
|
wxPostEvent(wxcontrol, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadSettingCheckBox::UpdateValue()
|
void PadSettingCheckBox::UpdateValue()
|
||||||
@ -162,8 +167,10 @@ ControlDialog::ControlDialog(GamepadPage* const parent, InputConfig& config,
|
|||||||
|
|
||||||
ControlButton::ControlButton(wxWindow* const parent,
|
ControlButton::ControlButton(wxWindow* const parent,
|
||||||
ControllerInterface::ControlReference* const _ref,
|
ControllerInterface::ControlReference* const _ref,
|
||||||
const unsigned int width, const std::string& label)
|
const std::string& name, const unsigned int width,
|
||||||
: wxButton(parent, wxID_ANY, "", wxDefaultPosition, wxSize(width, 20)), control_reference(_ref)
|
const std::string& label)
|
||||||
|
: wxButton(parent, wxID_ANY, "", wxDefaultPosition, wxSize(width, 20)), control_reference(_ref),
|
||||||
|
m_name(name)
|
||||||
{
|
{
|
||||||
if (label.empty())
|
if (label.empty())
|
||||||
SetLabel(StrToWxStr(_ref->expression));
|
SetLabel(StrToWxStr(_ref->expression));
|
||||||
@ -457,15 +464,68 @@ void ControlDialog::AppendControl(wxCommandEvent& event)
|
|||||||
UpdateGUI();
|
UpdateGUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GamepadPage::AdjustSetting(wxCommandEvent& event)
|
void GamepadPage::EnablePadSetting(const std::string& group_name, const std::string& name,
|
||||||
|
const bool enabled)
|
||||||
{
|
{
|
||||||
((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue();
|
const auto box_iterator =
|
||||||
|
std::find_if(control_groups.begin(), control_groups.end(), [&group_name](const auto& box) {
|
||||||
|
return group_name == box->control_group->name;
|
||||||
|
});
|
||||||
|
if (box_iterator == control_groups.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto* box = *box_iterator;
|
||||||
|
const auto it =
|
||||||
|
std::find_if(box->options.begin(), box->options.end(), [&name](const auto& pad_setting) {
|
||||||
|
return pad_setting->wxcontrol->GetLabelText() == name;
|
||||||
|
});
|
||||||
|
if (it == box->options.end())
|
||||||
|
return;
|
||||||
|
(*it)->wxcontrol->Enable(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GamepadPage::AdjustSettingUI(wxCommandEvent& event)
|
void GamepadPage::EnableControlButton(const std::string& group_name, const std::string& name,
|
||||||
|
const bool enabled)
|
||||||
{
|
{
|
||||||
m_iterate = !m_iterate;
|
const auto box_iterator =
|
||||||
((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue();
|
std::find_if(control_groups.begin(), control_groups.end(), [&group_name](const auto& box) {
|
||||||
|
return group_name == box->control_group->name;
|
||||||
|
});
|
||||||
|
if (box_iterator == control_groups.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto* box = *box_iterator;
|
||||||
|
const auto it =
|
||||||
|
std::find_if(box->control_buttons.begin(), box->control_buttons.end(),
|
||||||
|
[&name](const auto& control_button) { return control_button->m_name == name; });
|
||||||
|
if (it == box->control_buttons.end())
|
||||||
|
return;
|
||||||
|
(*it)->Enable(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamepadPage::AdjustSetting(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
const auto* const control = static_cast<wxControl*>(event.GetEventObject());
|
||||||
|
auto* const pad_setting = static_cast<PadSetting*>(control->GetClientData());
|
||||||
|
pad_setting->UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamepadPage::AdjustBooleanSetting(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
const auto* const control = static_cast<wxControl*>(event.GetEventObject());
|
||||||
|
auto* const pad_setting = static_cast<PadSettingCheckBox*>(control->GetClientData());
|
||||||
|
pad_setting->UpdateValue();
|
||||||
|
|
||||||
|
// TODO: find a cleaner way to have actions depending on the setting
|
||||||
|
if (control->GetLabelText() == "Iterative Input")
|
||||||
|
{
|
||||||
|
m_iterate = pad_setting->setting->GetValue();
|
||||||
|
}
|
||||||
|
else if (control->GetLabelText() == "Relative Input")
|
||||||
|
{
|
||||||
|
EnablePadSetting("IR", "Dead Zone", pad_setting->setting->GetValue());
|
||||||
|
EnableControlButton("IR", "Recenter", pad_setting->setting->GetValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GamepadPage::AdjustControlOption(wxCommandEvent&)
|
void GamepadPage::AdjustControlOption(wxCommandEvent&)
|
||||||
@ -766,6 +826,8 @@ void GamepadPage::RefreshDevices(wxCommandEvent&)
|
|||||||
Pad::LoadConfig();
|
Pad::LoadConfig();
|
||||||
HotkeyManagerEmu::LoadConfig();
|
HotkeyManagerEmu::LoadConfig();
|
||||||
|
|
||||||
|
UpdateGUI();
|
||||||
|
|
||||||
Core::PauseAndLock(false, was_unpaused);
|
Core::PauseAndLock(false, was_unpaused);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,7 +852,8 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
|||||||
wxStaticText* const label =
|
wxStaticText* const label =
|
||||||
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(control->name)));
|
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(control->name)));
|
||||||
|
|
||||||
ControlButton* const control_button = new ControlButton(parent, control->control_ref.get(), 80);
|
ControlButton* const control_button =
|
||||||
|
new ControlButton(parent, control->control_ref.get(), control->name, 80);
|
||||||
control_button->SetFont(m_SmallFont);
|
control_button->SetFont(m_SmallFont);
|
||||||
|
|
||||||
control_buttons.push_back(control_button);
|
control_buttons.push_back(control_button);
|
||||||
@ -848,6 +911,13 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
|||||||
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(groupSetting->m_name))));
|
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(groupSetting->m_name))));
|
||||||
szr->Add(setting->wxcontrol, 0, wxLEFT, 0);
|
szr->Add(setting->wxcontrol, 0, wxLEFT, 0);
|
||||||
}
|
}
|
||||||
|
for (auto& groupSetting : group->boolean_settings)
|
||||||
|
{
|
||||||
|
auto* checkbox = new PadSettingCheckBox(parent, groupSetting.get());
|
||||||
|
checkbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustBooleanSetting, eventsink);
|
||||||
|
options.push_back(checkbox);
|
||||||
|
Add(checkbox->wxcontrol, 0, wxALL | wxLEFT, 5);
|
||||||
|
}
|
||||||
|
|
||||||
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||||
h_szr->Add(szr, 1, 0, 5);
|
h_szr->Add(szr, 1, 0, 5);
|
||||||
@ -942,15 +1012,9 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
|||||||
for (auto& groupSetting : group->boolean_settings)
|
for (auto& groupSetting : group->boolean_settings)
|
||||||
{
|
{
|
||||||
PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, groupSetting.get());
|
PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, groupSetting.get());
|
||||||
|
setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustBooleanSetting, eventsink);
|
||||||
if (groupSetting->m_name == "Iterative Input")
|
if (groupSetting->m_name == "Iterative Input")
|
||||||
{
|
|
||||||
setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSettingUI, eventsink);
|
|
||||||
groupSetting->SetValue(false);
|
groupSetting->SetValue(false);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSetting, eventsink);
|
|
||||||
}
|
|
||||||
options.push_back(setting_cbox);
|
options.push_back(setting_cbox);
|
||||||
Add(setting_cbox->wxcontrol, 0, wxALL | wxLEFT, 5);
|
Add(setting_cbox->wxcontrol, 0, wxALL | wxLEFT, 5);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
(int)(_setting->GetValue() * 100))),
|
(int)(_setting->GetValue() * 100))),
|
||||||
setting(_setting)
|
setting(_setting)
|
||||||
{
|
{
|
||||||
|
wxcontrol->SetLabel(setting->m_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateGUI() override;
|
void UpdateGUI() override;
|
||||||
@ -164,9 +165,10 @@ class ControlButton : public wxButton
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ControlButton(wxWindow* const parent, ControllerInterface::ControlReference* const _ref,
|
ControlButton(wxWindow* const parent, ControllerInterface::ControlReference* const _ref,
|
||||||
const unsigned int width, const std::string& label = "");
|
const std::string& name, const unsigned int width, const std::string& label = "");
|
||||||
|
|
||||||
ControllerInterface::ControlReference* const control_reference;
|
ControllerInterface::ControlReference* const control_reference;
|
||||||
|
const std::string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControlGroupBox : public wxBoxSizer
|
class ControlGroupBox : public wxBoxSizer
|
||||||
@ -222,8 +224,10 @@ public:
|
|||||||
void LoadDefaults(wxCommandEvent& event);
|
void LoadDefaults(wxCommandEvent& event);
|
||||||
|
|
||||||
void AdjustControlOption(wxCommandEvent& event);
|
void AdjustControlOption(wxCommandEvent& event);
|
||||||
|
void EnablePadSetting(const std::string& group_name, const std::string& name, bool enabled);
|
||||||
|
void EnableControlButton(const std::string& group_name, const std::string& name, bool enabled);
|
||||||
void AdjustSetting(wxCommandEvent& event);
|
void AdjustSetting(wxCommandEvent& event);
|
||||||
void AdjustSettingUI(wxCommandEvent& event);
|
void AdjustBooleanSetting(wxCommandEvent& event);
|
||||||
|
|
||||||
void GetProfilePath(std::string& path);
|
void GetProfilePath(std::string& path);
|
||||||
|
|
||||||
|
@ -295,10 +295,13 @@ ControllerEmu::Cursor::Cursor(const std::string& _name)
|
|||||||
controls.emplace_back(std::make_unique<Input>("Forward"));
|
controls.emplace_back(std::make_unique<Input>("Forward"));
|
||||||
controls.emplace_back(std::make_unique<Input>("Backward"));
|
controls.emplace_back(std::make_unique<Input>("Backward"));
|
||||||
controls.emplace_back(std::make_unique<Input>(_trans("Hide")));
|
controls.emplace_back(std::make_unique<Input>(_trans("Hide")));
|
||||||
|
controls.emplace_back(std::make_unique<Input>("Recenter"));
|
||||||
|
|
||||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Center"), 0.5));
|
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Center"), 0.5));
|
||||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Width"), 0.5));
|
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Width"), 0.5));
|
||||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Height"), 0.5));
|
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Height"), 0.5));
|
||||||
|
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 20));
|
||||||
|
boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Relative Input"), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerEmu::LoadDefaults(const ControllerInterface& ciface)
|
void ControllerEmu::LoadDefaults(const ControllerInterface& ciface)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
|
#include "Common/MathUtil.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
#include "InputCommon/GCPadStatus.h"
|
#include "InputCommon/GCPadStatus.h"
|
||||||
@ -424,12 +425,43 @@ public:
|
|||||||
yy += (numeric_settings[0]->GetValue() - 0.5);
|
yy += (numeric_settings[0]->GetValue() - 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
*x = xx;
|
// relative input
|
||||||
*y = yy;
|
if (boolean_settings[0]->GetValue())
|
||||||
|
{
|
||||||
|
const ControlState deadzone = numeric_settings[3]->GetValue();
|
||||||
|
// deadzone to avoid the cursor slowly drifting
|
||||||
|
if (std::abs(xx) > deadzone)
|
||||||
|
m_x = MathUtil::Clamp(m_x + xx * SPEED_MULTIPLIER, -1.0, 1.0);
|
||||||
|
if (std::abs(yy) > deadzone)
|
||||||
|
m_y = MathUtil::Clamp(m_y + yy * SPEED_MULTIPLIER, -1.0, 1.0);
|
||||||
|
|
||||||
|
// recenter
|
||||||
|
if (controls[7]->control_ref->State() > 0.5)
|
||||||
|
{
|
||||||
|
m_x = 0.0;
|
||||||
|
m_y = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_x = xx;
|
||||||
|
m_y = yy;
|
||||||
|
}
|
||||||
|
|
||||||
|
*x = m_x;
|
||||||
|
*y = m_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlState m_z;
|
ControlState m_z;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This is used to reduce the cursor speed for relative input
|
||||||
|
// to something that makes sense with the default range.
|
||||||
|
static constexpr double SPEED_MULTIPLIER = 0.04;
|
||||||
|
|
||||||
|
ControlState m_x = 0.0;
|
||||||
|
ControlState m_y = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Extension : public ControlGroup
|
class Extension : public ControlGroup
|
||||||
|
Reference in New Issue
Block a user