Input system refactor: Replace 5 callbacks with an interface

This commit is contained in:
Henrik Rydgård
2026-02-12 22:52:16 +01:00
parent dc554e27eb
commit a6ac956884
7 changed files with 71 additions and 72 deletions
+16 -33
View File
@@ -146,19 +146,6 @@ void ConvertAnalogStick(float x, float y, float *outX, float *outY) {
*outY = Clamp(y / norm * mappedNorm, -1.0f, 1.0f);
}
void ControlMapper::SetCallbacks(
std::function<void(VirtKey, bool)> onVKey,
std::function<void(VirtKey, float)> onVKeyAnalog,
std::function<void(uint32_t, uint32_t)> updatePSPButtons,
std::function<void(int, int, float, float)> setPSPAnalog,
std::function<void(int, float, float)> setRawAnalog) {
onVKey_ = onVKey;
onVKeyAnalog_ = onVKeyAnalog;
updatePSPButtons_ = updatePSPButtons;
setPSPAnalog_ = setPSPAnalog;
setRawAnalog_ = setRawAnalog;
}
void ControlMapper::SetPSPAxis(int device, int stick, char axis, float value) {
const int axisId = axis == 'X' ? 0 : 1;
if (stick != 0 && stick != 1) {
@@ -171,12 +158,10 @@ void ControlMapper::SetPSPAxis(int device, int stick, char axis, float value) {
position[axisId] = value;
float x = position[0];
float y = position[1];
const float x = position[0];
const float y = position[1];
if (setRawAnalog_) {
setRawAnalog_(stick, x, y);
}
listener_->SetRawAnalog(stick, x, y);
// NOTE: We need to use single-axis checks, since the other axis might be from another device,
// so we'll add a little leeway.
@@ -208,7 +193,7 @@ void ControlMapper::UpdateAnalogOutput(int stick) {
}
converted_[stick][0] = x;
converted_[stick][1] = y;
setPSPAnalog_(iInternalScreenRotationCached_, stick, x, y);
listener_->SetPSPAnalog(iInternalScreenRotationCached_, stick, x, y);
}
void ControlMapper::ForceReleaseVKey(int vkey) {
@@ -416,7 +401,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no
}
// We only request changing the buttons where the mapped input was involved.
updatePSPButtons_(buttonMask & changedButtonMask, (~buttonMask) & changedButtonMask);
listener_->UpdatePSPButtons(buttonMask & changedButtonMask, (~buttonMask) & changedButtonMask);
bool keyInputUsed = changedButtonMask != 0;
bool updateAnalogSticks = false;
@@ -579,16 +564,16 @@ void ControlMapper::ToggleSwapAxes() {
swapAxes_ = !swapAxes_;
updatePSPButtons_(0, CTRL_LEFT | CTRL_RIGHT | CTRL_UP | CTRL_DOWN);
listener_->UpdatePSPButtons(0, CTRL_LEFT | CTRL_RIGHT | CTRL_UP | CTRL_DOWN);
for (VirtKey vkey = VIRTKEY_FIRST; vkey < VIRTKEY_LAST; vkey = (VirtKey)(vkey + 1)) {
if (IsSwappableVKey(vkey)) {
if (virtKeyOn_[vkey - VIRTKEY_FIRST]) {
onVKey_(vkey, false);
listener_->OnVKey(vkey, false);
virtKeyOn_[vkey - VIRTKEY_FIRST] = false;
}
if (virtKeys_[vkey - VIRTKEY_FIRST] > 0.0f) {
onVKeyAnalog_(vkey, 0.0f);
listener_->OnVKeyAnalog(vkey, 0.0f);
virtKeys_[vkey - VIRTKEY_FIRST] = 0.0f;
}
}
@@ -657,12 +642,12 @@ void ControlMapper::Update(const DisplayLayoutConfig &config, double now) {
float x = std::min(1.0f, std::max(-1.0f, 1.42f * (float)cos(now * -g_Config.fAnalogAutoRotSpeed)));
float y = std::min(1.0f, std::max(-1.0f, 1.42f * (float)sin(now * -g_Config.fAnalogAutoRotSpeed)));
setPSPAnalog_(iInternalScreenRotationCached_, 0, x, y);
listener_->SetPSPAnalog(iInternalScreenRotationCached_, 0, x, y);
} else if (autoRotatingAnalogCCW_) {
float x = std::min(1.0f, std::max(-1.0f, 1.42f * (float)cos(now * g_Config.fAnalogAutoRotSpeed)));
float y = std::min(1.0f, std::max(-1.0f, 1.42f * (float)sin(now * g_Config.fAnalogAutoRotSpeed)));
setPSPAnalog_(iInternalScreenRotationCached_, 0, x, y);
listener_->SetPSPAnalog(iInternalScreenRotationCached_, 0, x, y);
}
}
@@ -683,9 +668,9 @@ void ControlMapper::PSPKey(int deviceId, int pspKeyCode, KeyInputFlags flags) {
} else {
// INFO_LOG(Log::System, "pspKey %d %d", pspKeyCode, flags);
if (flags & KeyInputFlags::DOWN)
updatePSPButtons_(pspKeyCode, 0);
listener_->UpdatePSPButtons(pspKeyCode, 0);
if (flags & KeyInputFlags::UP)
updatePSPButtons_(0, pspKeyCode);
listener_->UpdatePSPButtons(0, pspKeyCode);
}
}
@@ -706,8 +691,7 @@ void ControlMapper::onVKeyAnalog(int deviceId, VirtKey vkey, float value) {
case VIRTKEY_AXIS_RIGHT_Y_MIN: stick = CTRL_STICK_RIGHT; axis = 'Y'; sign = -1.0f; break;
case VIRTKEY_AXIS_RIGHT_Y_MAX: stick = CTRL_STICK_RIGHT; axis = 'Y'; break;
default:
if (onVKeyAnalog_)
onVKeyAnalog_(vkey, value);
listener_->OnVKeyAnalog(vkey, value);
return;
}
if (oppositeVKey != 0) {
@@ -728,7 +712,7 @@ void ControlMapper::onVKey(VirtKey vkey, bool down) {
autoRotatingAnalogCCW_ = false;
} else {
autoRotatingAnalogCW_ = false;
setPSPAnalog_(iInternalScreenRotationCached_, 0, 0.0f, 0.0f);
listener_->SetPSPAnalog(iInternalScreenRotationCached_, 0, 0.0f, 0.0f);
}
break;
case VIRTKEY_ANALOG_ROTATE_CCW:
@@ -737,12 +721,11 @@ void ControlMapper::onVKey(VirtKey vkey, bool down) {
autoRotatingAnalogCCW_ = true;
} else {
autoRotatingAnalogCCW_ = false;
setPSPAnalog_(iInternalScreenRotationCached_, 0, 0.0f, 0.0f);
listener_->SetPSPAnalog(iInternalScreenRotationCached_, 0, 0.0f, 0.0f);
}
break;
default:
if (onVKey_)
onVKey_(vkey, down);
listener_->OnVKey(vkey, down);
break;
}
}
+16 -11
View File
@@ -8,6 +8,18 @@
#include <mutex>
struct DisplayLayoutConfig;
// Pure interface.
class ControlListener {
public:
virtual ~ControlListener() = default;
virtual void OnVKey(VirtKey vkey, bool down) {}
virtual void OnVKeyAnalog(VirtKey vkey, float value) {}
virtual void UpdatePSPButtons(uint32_t buttonMask, uint32_t changedMask) {}
virtual void SetPSPAnalog(int rotation, int stick, float x, float y) {}
virtual void SetRawAnalog(int stick, float x, float y) {}
};
// Utilities for mapping input events to PSP inputs and virtual keys.
// Main use is of course from EmuScreen.cpp, but also useful from control settings etc.
class ControlMapper {
@@ -21,12 +33,9 @@ public:
// Required callbacks.
// TODO: These are so many now that a virtual interface might be more appropriate..
void SetCallbacks(
std::function<void(VirtKey, bool)> onVKey,
std::function<void(VirtKey, float)> onVKeyAnalog,
std::function<void(uint32_t, uint32_t)> updatePSPButtons,
std::function<void(int, int, float, float)> setPSPAnalog,
std::function<void(int, float, float)> setRawAnalog);
void SetListener(ControlListener *listener) {
listener_ = listener;
}
// Inject raw PSP key input directly, such as from touch screen controls.
// Combined with the mapped input. Unlike __Ctrl APIs, this supports
@@ -96,11 +105,7 @@ private:
std::map<InputMapping, InputSample> curInput_;
// Callbacks
std::function<void(VirtKey, bool)> onVKey_;
std::function<void(VirtKey, float)> onVKeyAnalog_;
std::function<void(uint32_t, uint32_t)> updatePSPButtons_;
std::function<void(int, int, float, float)> setPSPAnalog_;
std::function<void(int, float, float)> setRawAnalog_;
ControlListener *listener_ = nullptr;
};
void ConvertAnalogStick(float x, float y, float *outX, float *outY);
+15 -12
View File
@@ -480,18 +480,21 @@ void KeyMappingNewMouseKeyDialog::axis(const AxisInput &axis) {
}
AnalogCalibrationScreen::AnalogCalibrationScreen(const Path &gamePath) : UITwoPaneBaseDialogScreen(gamePath, TwoPaneFlags::SettingsCanScroll) {
mapper_.SetCallbacks(
[](int vkey, bool down) {},
[](int vkey, float analogValue) {},
[&](uint32_t bitsToSet, uint32_t bitsToClear) {},
[&](int iInternalRotation, int stick, float x, float y) {
analogX_[stick] = x;
analogY_[stick] = y;
},
[&](int stick, float x, float y) {
rawX_[stick] = x;
rawY_[stick] = y;
});
mapper_.SetListener(this);
}
AnalogCalibrationScreen::~AnalogCalibrationScreen() {
mapper_.SetListener(nullptr);
}
void AnalogCalibrationScreen::SetPSPAnalog(int rotation, int stick, float x, float y) {
analogX_[stick] = x;
analogY_[stick] = y;
}
void AnalogCalibrationScreen::SetRawAnalog(int stick, float x, float y) {
rawX_[stick] = x;
rawY_[stick] = y;
}
void AnalogCalibrationScreen::update() {
+5 -1
View File
@@ -125,9 +125,10 @@ private:
class JoystickHistoryView;
class AnalogCalibrationScreen : public UITwoPaneBaseDialogScreen {
class AnalogCalibrationScreen : public UITwoPaneBaseDialogScreen, protected ControlListener {
public:
AnalogCalibrationScreen(const Path &gamePath);
~AnalogCalibrationScreen();
bool key(const KeyInput &key) override;
void axis(const AxisInput &axis) override;
@@ -140,6 +141,9 @@ protected:
void CreateSettingsViews(UI::ViewGroup *parent) override;
void CreateContentViews(UI::ViewGroup *parent) override;
void SetPSPAnalog(int rotation, int stick, float x, float y) override;
void SetRawAnalog(int stick, float x, float y) override;
std::string_view GetTitle() const override;
private:
void OnResetToDefaults(UI::EventParams &e);
+10 -11
View File
@@ -126,7 +126,11 @@ static void AssertCancelCallback(const char *message, void *userdata) {
}
// Handles control rotation due to internal screen rotation.
static void SetPSPAnalog(int iInternalScreenRotation, int stick, float x, float y) {
void EmuScreen::UpdatePSPButtons(uint32_t bitsToSet, uint32_t bitsToClear) {
__CtrlUpdateButtons(bitsToSet, bitsToClear);
}
void EmuScreen::SetPSPAnalog(int iInternalScreenRotation, int stick, float x, float y) {
switch (iInternalScreenRotation) {
case ROTATION_LOCKED_HORIZONTAL:
// Standard rotation. No change.
@@ -158,14 +162,7 @@ static void SetPSPAnalog(int iInternalScreenRotation, int stick, float x, float
EmuScreen::EmuScreen(const Path &filename)
: gamePath_(filename) {
saveStateSlot_ = SaveState::GetCurrentSlot();
controlMapper_.SetCallbacks(
std::bind(&EmuScreen::onVKey, this, _1, _2),
std::bind(&EmuScreen::onVKeyAnalog, this, _1, _2),
[](uint32_t bitsToSet, uint32_t bitsToClear) {
__CtrlUpdateButtons(bitsToSet, bitsToClear);
},
&SetPSPAnalog,
nullptr);
controlMapper_.SetListener(this);
_dbg_assert_(coreState == CORE_POWERDOWN);
@@ -449,6 +446,8 @@ void EmuScreen::bootComplete() {
}
EmuScreen::~EmuScreen() {
controlMapper_.SetListener(nullptr);
if (imguiInited_) {
ImGui_ImplThin3d_Shutdown();
ImGui::DestroyContext(ctx_);
@@ -739,7 +738,7 @@ static void ShowFpsLimitNotice() {
g_OSD.SetFlags("altspeed", OSDMessageFlags::Transparent);
}
void EmuScreen::onVKey(VirtKey virtualKeyCode, bool down) {
void EmuScreen::OnVKey(VirtKey virtualKeyCode, bool down) {
auto sc = GetI18NCategory(I18NCat::SCREEN);
auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS);
@@ -1081,7 +1080,7 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) {
}
}
void EmuScreen::onVKeyAnalog(VirtKey virtualKeyCode, float value) {
void EmuScreen::OnVKeyAnalog(VirtKey virtualKeyCode, float value) {
if (virtualKeyCode != VIRTKEY_SPEED_ANALOG) {
return;
}
+8 -3
View File
@@ -36,7 +36,7 @@ struct AxisInput;
class AsyncImageFileView;
class ChatMenu;
class EmuScreen : public UIScreen {
class EmuScreen : public UIScreen, public ControlListener {
public:
EmuScreen(const Path &filename);
~EmuScreen();
@@ -72,6 +72,13 @@ protected:
void focusChanged(ScreenFocusChange focusChange) override;
ScreenRenderFlags PreRender(ScreenRenderMode mode) override;
// ControlListener implementations
void OnVKey(VirtKey virtualKeyCode, bool down);
void OnVKeyAnalog(VirtKey virtualKeyCode, float value);
void UpdatePSPButtons(uint32_t buttonMask, uint32_t changedMask) override;
void SetPSPAnalog(int rotation, int stick, float x, float y);
void SetRawAnalog(int deviceId, float x, float y) {}
private:
void CreateViews() override;
ScreenRenderFlags RunEmulation(bool skipBufferEffects);
@@ -87,8 +94,6 @@ private:
void runImDebugger();
void renderImDebugger();
void onVKey(VirtKey virtualKeyCode, bool down);
void onVKeyAnalog(VirtKey virtualKeyCode, float value);
void AutoLoadSaveState();
bool checkPowerDown();
+1 -1
View File
@@ -1432,7 +1432,7 @@ void MainScreen::CreateViews() {
#if !defined(MOBILE_DEVICE)
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
ImageID icon(g_Config.bFullScreen ? "I_RESTORE" : "I_FULLSCREEN");
fullscreenButton_ = logo->Add(new Button(gr->T("FullScreen", "Full Screen"), icon, new AnchorLayoutParams(48, 48, NONE, 0, 0, NONE, Centering::None)));
fullscreenButton_ = logo->Add(new Button("", icon, new AnchorLayoutParams(48, 48, NONE, 0, 0, NONE, Centering::None)));
fullscreenButton_->SetIgnoreText(true);
fullscreenButton_->OnClick.Add([this](UI::EventParams &e) {
if (fullscreenButton_) {