Skip to content

Commit

Permalink
rewrite controller inputs using new "input override" system
Browse files Browse the repository at this point in the history
see dolphin-emu#9624 for details on the rewrite.
We now basically get per-button control for all supported input methods for free.
Fixes for documentation and python stubs pending. Breaking changes!
  • Loading branch information
Felk committed Sep 12, 2023
1 parent e65599d commit 17f96f7
Show file tree
Hide file tree
Showing 8 changed files with 832 additions and 332 deletions.
290 changes: 203 additions & 87 deletions Source/Core/Core/API/Controller.cpp

Large diffs are not rendered by default.

185 changes: 114 additions & 71 deletions Source/Core/Core/API/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,108 +4,151 @@

#pragma once

#include "Common/CommonTypes.h"
#include "Core/API/Events.h"
#include "Core/HW/WiimoteCommon/DataReport.h"
#include "InputCommon/GCPadStatus.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "InputCommon/InputConfig.h"

namespace API
{

enum class ClearOn
{
NextPoll = 0,
NextFrame = 1,
NextOverride = 2,
};

template <typename T>
class BaseManip
struct InputKey
{
public:
BaseManip(API::EventHub& event_hub) : m_event_hub(event_hub)
{
m_frame_advanced_listener = m_event_hub.ListenEvent<API::Events::FrameAdvance>(
[&](const API::Events::FrameAdvance&) { NotifyFrameAdvanced(); });
}
~BaseManip() { m_event_hub.UnlistenEvent(m_frame_advanced_listener); }
void Clear() { m_overrides.clear(); }
void NotifyFrameAdvanced()
{
// std::erase_if back-ported to C++17
for (auto i = m_overrides.begin(), last = m_overrides.end(); i != last; )
{
auto kvp = *i;
if (kvp.second.clear_on == ClearOn::NextFrame && kvp.second.used)
i = m_overrides.erase(i);
else
++i;
}
}
static const InputKey GC_A;
static const InputKey GC_B;
static const InputKey GC_X;
static const InputKey GC_Y;
static const InputKey GC_Z;
static const InputKey GC_START;
static const InputKey GC_UP;
static const InputKey GC_DOWN;
static const InputKey GC_LEFT;
static const InputKey GC_RIGHT;
static const InputKey GC_L;
static const InputKey GC_R;
static const InputKey GC_L_ANALOG;
static const InputKey GC_R_ANALOG;
static const InputKey GC_STICK_X;
static const InputKey GC_STICK_Y;
static const InputKey GC_C_STICK_X;
static const InputKey GC_C_STICK_Y;

protected:
std::map<int, T> m_overrides;
static const InputKey WII_A;
static const InputKey WII_B;
static const InputKey WII_ONE;
static const InputKey WII_TWO;
static const InputKey WII_PLUS;
static const InputKey WII_MINUS;
static const InputKey WII_HOME;
static const InputKey WII_UP;
static const InputKey WII_DOWN;
static const InputKey WII_LEFT;
static const InputKey WII_RIGHT;
static const InputKey WII_IR_X;
static const InputKey WII_IR_Y;
static const InputKey WII_ACCELERATION_X;
static const InputKey WII_ACCELERATION_Y;
static const InputKey WII_ACCELERATION_Z;
static const InputKey WII_ANGULAR_VELOCITY_X;
static const InputKey WII_ANGULAR_VELOCITY_Y;
static const InputKey WII_ANGULAR_VELOCITY_Z;

private:
API::EventHub& m_event_hub;
API::ListenerID<API::Events::FrameAdvance> m_frame_advanced_listener;
};
static const InputKey WII_CLASSIC_A;
static const InputKey WII_CLASSIC_B;
static const InputKey WII_CLASSIC_X;
static const InputKey WII_CLASSIC_Y;
static const InputKey WII_CLASSIC_ZL;
static const InputKey WII_CLASSIC_ZR;
static const InputKey WII_CLASSIC_PLUS;
static const InputKey WII_CLASSIC_MINUS;
static const InputKey WII_CLASSIC_HOME;
static const InputKey WII_CLASSIC_UP;
static const InputKey WII_CLASSIC_DOWN;
static const InputKey WII_CLASSIC_LEFT;
static const InputKey WII_CLASSIC_RIGHT;
static const InputKey WII_CLASSIC_L;
static const InputKey WII_CLASSIC_R;
static const InputKey WII_CLASSIC_L_ANALOG;
static const InputKey WII_CLASSIC_R_ANALOG;
static const InputKey WII_CLASSIC_LEFT_STICK_X;
static const InputKey WII_CLASSIC_LEFT_STICK_Y;
static const InputKey WII_CLASSIC_RIGHT_STICK_X;
static const InputKey WII_CLASSIC_RIGHT_STICK_Y;

struct WiiInputButtonsOverride
{
WiimoteCommon::ButtonData button_data;
ClearOn clear_on;
bool used;
};
static const InputKey WII_NUNCHUK_C;
static const InputKey WII_NUNCHUK_Z;
static const InputKey WII_NUNCHUK_STICK_X;
static const InputKey WII_NUNCHUK_STICK_Y;
static const InputKey WII_NUNCHUCK_ACCELERATION_X;
static const InputKey WII_NUNCHUCK_ACCELERATION_Y;
static const InputKey WII_NUNCHUCK_ACCELERATION_Z;

struct IRCameraTransform
{
Common::Vec3 position;
Common::Vec3 pitch_yaw_roll;
};
static const InputKey GBA_A;
static const InputKey GBA_B;
static const InputKey GBA_L;
static const InputKey GBA_R;
static const InputKey GBA_START;
static const InputKey GBA_SELECT;
static const InputKey GBA_UP;
static const InputKey GBA_DOWN;
static const InputKey GBA_LEFT;
static const InputKey GBA_RIGHT;

struct WiiInputIROverride
{
IRCameraTransform ircamera_transform;
ClearOn clear_on;
bool used;
};
std::string_view group_name;
std::string_view control_name;

class WiiButtonsManip : public BaseManip<WiiInputButtonsOverride>
{
public:
using BaseManip::BaseManip;
WiimoteCommon::ButtonData Get(int controller_id);
void Set(WiimoteCommon::ButtonData button_data, int controller_id, ClearOn clear_on);
void PerformInputManip(WiimoteCommon::DataReportBuilder& rpt, int controller_id);
};
bool operator==(const InputKey& o) const
{
return group_name == o.group_name && control_name == o.control_name;
}

class WiiIRManip : public BaseManip<WiiInputIROverride>
{
public:
using BaseManip::BaseManip;
void Set(IRCameraTransform ircamera_transform, int controller_id, ClearOn clear_on);
void PerformInputManip(WiimoteCommon::DataReportBuilder& rpt, int controller_id);
bool operator<(const InputKey& o) const
{
return group_name < o.group_name ||
(group_name == o.group_name && control_name < o.control_name);
}
};

struct GCInputOverride
struct InputOverride
{
GCPadStatus pad_status;
ControlState state;
ClearOn clear_on;
bool used;
};

class GCManip : public BaseManip<GCInputOverride>
class BaseManip
{
public:
using BaseManip::BaseManip;
GCPadStatus Get(int controller_id);
void Set(GCPadStatus pad_status, int controller_id, ClearOn clear_on);
void PerformInputManip(GCPadStatus* pad_status, int controller_id);
BaseManip(API::EventHub& event_hub,
const std::vector<ControllerEmu::EmulatedController*> controllers);
~BaseManip();
ControlState Get(int controller_id, const InputKey& input_key);
void Set(int controller_id, InputKey input_key, ControlState state, ClearOn clear_on);
void Clear() { m_overrides.clear(); }
void NotifyFrameAdvanced();
std::optional<ControlState> PerformInputManip(int controller_id, const InputKey& input_key,
ControlState orig_state);

private:
std::map<std::tuple<int, InputKey>, InputOverride> m_overrides;
std::map<std::tuple<int, InputKey>, ControlState> m_last_seen_input;
EventHub& m_event_hub;
ListenerID<Events::FrameAdvance> m_frame_advanced_listener;
std::vector<ControllerEmu::EmulatedController*> m_controllers;
};

// global instances
GCManip& GetGCManip();
WiiButtonsManip& GetWiiButtonsManip();
WiiIRManip& GetWiiIRManip();
BaseManip& GetGCManip();
BaseManip& GetWiiManip();
BaseManip& GetWiiClassicManip();
BaseManip& GetWiiNunchukManip();
BaseManip& GetGBAManip();

} // namespace API
3 changes: 0 additions & 3 deletions Source/Core/Core/HW/SI/SI_DeviceGCController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/Swap.h"
#include "Core/API/Controller.h"
#include "Core/Config/MainSettings.h"
#include "Core/CoreTiming.h"
#include "Core/HW/GCPad.h"
Expand Down Expand Up @@ -129,8 +128,6 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int request_length)

void CSIDevice_GCController::HandleMoviePadStatus(int device_number, GCPadStatus* pad_status)
{
API::GetGCManip().PerformInputManip(pad_status, device_number);

Movie::SetPolledDevice();
if (NetPlay_GetInput(device_number, pad_status))
{
Expand Down
4 changes: 0 additions & 4 deletions Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "Common/MathUtil.h"
#include "Common/MsgHandler.h"

#include "Core/API/Controller.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigManager.h"
Expand Down Expand Up @@ -631,9 +630,6 @@ void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
std::fill_n(ext_data, ext_size, u8(0xff));
}
}

API::GetWiiButtonsManip().PerformInputManip(rpt_builder, m_index);
API::GetWiiIRManip().PerformInputManip(rpt_builder, m_index);
}

Movie::CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
Expand Down
Loading

0 comments on commit 17f96f7

Please sign in to comment.