summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon
diff options
context:
space:
mode:
authoriwubcode <iwubcode@users.noreply.github.com>2020-04-20 23:16:07 -0500
committeriwubcode <iwubcode@users.noreply.github.com>2021-03-17 20:58:33 -0500
commitdb4b4e40cb5c9d00940cdb76478b632804cdf244 (patch)
treeed9ba12bcc60ec1a34a72ada599853115b6c91d8 /Source/Core/InputCommon
parent679d51c2898b99c24ad904e891781a147b2f6667 (diff)
InputCommon / DolphinQt / Core: Add a "RelativeMouse" input which provides the raw delta mouse input
Co-authored-by: Jordan Woyak <jordan.woyak@gmail.com>
Diffstat (limited to 'Source/Core/InputCommon')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp12
-rw-r--r--Source/Core/InputCommon/ControllerInterface/ControllerInterface.h53
-rw-r--r--Source/Core/InputCommon/ControllerInterface/CoreDevice.h6
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp46
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h11
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp20
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h16
7 files changed, 161 insertions, 3 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
index 1d198ca494..fe176ce7f7 100644
--- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
@@ -37,6 +37,8 @@
ControllerInterface g_controller_interface;
+static thread_local ciface::InputChannel tls_input_channel = ciface::InputChannel::Host;
+
void ControllerInterface::Initialize(const WindowSystemInfo& wsi)
{
if (m_is_init)
@@ -274,6 +276,16 @@ void ControllerInterface::UpdateInput()
}
}
+void ControllerInterface::SetCurrentInputChannel(ciface::InputChannel input_channel)
+{
+ tls_input_channel = input_channel;
+}
+
+ciface::InputChannel ControllerInterface::GetCurrentInputChannel()
+{
+ return tls_input_channel;
+}
+
void ControllerInterface::SetAspectRatioAdjustment(float value)
{
m_aspect_ratio_adjustment = value;
diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h
index 254516fb6e..12d17614da 100644
--- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h
+++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h
@@ -32,6 +32,23 @@
#endif
#define CIFACE_USE_DUALSHOCKUDPCLIENT
+namespace ciface
+{
+// A thread local "input channel" is maintained to handle the state of relative inputs.
+// This allows simultaneous use of relative inputs across different input contexts.
+// e.g. binding relative mouse movements to both GameCube controllers and FreeLook.
+// These operate at different rates and processing one would break the other without separate state.
+enum class InputChannel
+{
+ Host,
+ SerialInterface,
+ Bluetooth,
+ FreeLook,
+ Count,
+};
+
+} // namespace ciface
+
//
// ControllerInterface
//
@@ -66,6 +83,9 @@ public:
void UnregisterDevicesChangedCallback(const HotplugCallbackHandle& handle);
void InvokeDevicesChangedCallbacks() const;
+ static void SetCurrentInputChannel(ciface::InputChannel);
+ static ciface::InputChannel GetCurrentInputChannel();
+
private:
std::list<std::function<void()>> m_devices_changed_callbacks;
mutable std::mutex m_callbacks_mutex;
@@ -75,4 +95,37 @@ private:
std::atomic<float> m_aspect_ratio_adjustment = 1;
};
+namespace ciface
+{
+template <typename T>
+class RelativeInputState
+{
+public:
+ void Update()
+ {
+ const auto channel = int(ControllerInterface::GetCurrentInputChannel());
+
+ m_value[channel] = m_delta[channel];
+ m_delta[channel] = {};
+ }
+
+ T GetValue() const
+ {
+ const auto channel = int(ControllerInterface::GetCurrentInputChannel());
+
+ return m_value[channel];
+ }
+
+ void Move(T delta)
+ {
+ for (auto& d : m_delta)
+ d += delta;
+ }
+
+private:
+ std::array<T, int(InputChannel::Count)> m_value;
+ std::array<T, int(InputChannel::Count)> m_delta;
+};
+} // namespace ciface
+
extern ControllerInterface g_controller_interface;
diff --git a/Source/Core/InputCommon/ControllerInterface/CoreDevice.h b/Source/Core/InputCommon/ControllerInterface/CoreDevice.h
index 2612f59627..c368578949 100644
--- a/Source/Core/InputCommon/ControllerInterface/CoreDevice.h
+++ b/Source/Core/InputCommon/ControllerInterface/CoreDevice.h
@@ -93,6 +93,12 @@ public:
virtual bool IsChild(const Input*) const { return false; }
};
+ class RelativeInput : public Input
+ {
+ public:
+ bool IsDetectable() const override { return false; }
+ };
+
//
// Output
//
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp
index e5e10802cc..ebe2e84286 100644
--- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp
@@ -2,11 +2,14 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include "InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h"
+
#include <algorithm>
+#include <fmt/format.h>
+
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/ControllerInterface/DInput/DInput.h"
-#include "InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h"
// (lower would be more sensitive) user can lower sensitivity by setting range
// seems decent here ( at 8 ), I don't think anyone would need more sensitive than this
@@ -19,6 +22,30 @@
namespace ciface::DInput
{
+class RelativeMouseAxis final : public Core::Device::RelativeInput
+{
+public:
+ std::string GetName() const override
+ {
+ return fmt::format("RelativeMouse {}{}", char('X' + m_index), (m_scale > 0) ? '+' : '-');
+ }
+
+ RelativeMouseAxis(u8 index, bool positive, const RelativeMouseState* state)
+ : m_state(*state), m_index(index), m_scale(positive * 2 - 1)
+ {
+ }
+
+ ControlState GetState() const override
+ {
+ return ControlState(m_state.GetValue().data[m_index] * m_scale);
+ }
+
+private:
+ const RelativeMouseState& m_state;
+ const u8 m_index;
+ const s8 m_scale;
+};
+
static const struct
{
const BYTE code;
@@ -108,9 +135,17 @@ KeyboardMouse::KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device,
AddInput(new Axis(i, ax, (2 == i) ? -1 : -MOUSE_AXIS_SENSITIVITY));
AddInput(new Axis(i, ax, -(2 == i) ? 1 : MOUSE_AXIS_SENSITIVITY));
}
+
// cursor, with a hax for-loop
for (unsigned int i = 0; i < 4; ++i)
AddInput(new Cursor(!!(i & 2), (&m_state_in.cursor.x)[i / 2], !!(i & 1)));
+
+ // Raw relative mouse movement.
+ for (unsigned int i = 0; i != mouse_caps.dwAxes; ++i)
+ {
+ AddInput(new RelativeMouseAxis(i, false, &m_state_in.relative_mouse));
+ AddInput(new RelativeMouseAxis(i, true, &m_state_in.relative_mouse));
+ }
}
void KeyboardMouse::UpdateCursorInput()
@@ -147,6 +182,8 @@ void KeyboardMouse::UpdateInput()
{
// set axes to zero
m_state_in.mouse = {};
+ m_state_in.relative_mouse = {};
+
// skip this input state
m_mo_device->GetDeviceState(sizeof(tmp_mouse), &tmp_mouse);
}
@@ -162,14 +199,17 @@ void KeyboardMouse::UpdateInput()
if (DIERR_INPUTLOST == mo_hr || DIERR_NOTACQUIRED == mo_hr)
m_mo_device->Acquire();
- if (SUCCEEDED(kb_hr) && SUCCEEDED(mo_hr))
+ if (SUCCEEDED(mo_hr))
{
+ m_state_in.relative_mouse.Move({tmp_mouse.lX, tmp_mouse.lY, tmp_mouse.lZ});
+ m_state_in.relative_mouse.Update();
+
// need to smooth out the axes, otherwise it doesn't work for shit
for (unsigned int i = 0; i < 3; ++i)
((&m_state_in.mouse.lX)[i] += (&tmp_mouse.lX)[i]) /= 2;
// copy over the buttons
- memcpy(m_state_in.mouse.rgbButtons, tmp_mouse.rgbButtons, sizeof(m_state_in.mouse.rgbButtons));
+ std::copy_n(tmp_mouse.rgbButtons, std::size(tmp_mouse.rgbButtons), m_state_in.mouse.rgbButtons);
UpdateCursorInput();
}
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h
index c3834df528..ceda59d02c 100644
--- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h
@@ -7,6 +7,7 @@
#include <windows.h>
#include "Common/Matrix.h"
+#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"
#include "InputCommon/ControllerInterface/DInput/DInput8.h"
@@ -14,14 +15,23 @@ namespace ciface::DInput
{
void InitKeyboardMouse(IDirectInput8* const idi8, HWND hwnd);
+using RelativeMouseState = RelativeInputState<Common::TVec3<LONG>>;
+
class KeyboardMouse : public Core::Device
{
private:
struct State
{
BYTE keyboard[256];
+
+ // Old smoothed relative mouse movement.
DIMOUSESTATE2 mouse;
+
+ // Normalized mouse cursor position.
Common::TVec2<ControlState> cursor;
+
+ // Raw relative mouse movement.
+ RelativeMouseState relative_mouse;
};
class Key : public Input
@@ -53,6 +63,7 @@ private:
public:
Axis(u8 index, const LONG& axis, LONG range) : m_axis(axis), m_range(range), m_index(index) {}
std::string GetName() const override;
+ bool IsDetectable() const override { return false; }
ControlState GetState() const override;
private:
diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp
index a60edc3282..996673becb 100644
--- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp
@@ -197,6 +197,11 @@ KeyboardMouse::KeyboardMouse(Window window, int opcode, int pointer, int keyboar
// Mouse Axis, X-/+ and Y-/+
for (int i = 0; i != 4; ++i)
AddInput(new Axis(!!(i & 2), !!(i & 1), (i & 2) ? &m_state.axis.y : &m_state.axis.x));
+
+ // Relative Mouse, X-/+ and Y-/+
+ for (int i = 0; i != 4; ++i)
+ AddInput(new RelativeMouse(!!(i & 2), !!(i & 1),
+ (i & 2) ? &m_state.relative_mouse.y : &m_state.relative_mouse.x));
}
KeyboardMouse::~KeyboardMouse()
@@ -302,6 +307,9 @@ void KeyboardMouse::UpdateInput()
XFreeEventData(m_display, &event.xcookie);
}
+ m_state.relative_mouse.x = delta_x;
+ m_state.relative_mouse.y = delta_y;
+
// apply axis smoothing
m_state.axis.x *= MOUSE_AXIS_SMOOTHING;
m_state.axis.x += delta_x;
@@ -391,8 +399,20 @@ KeyboardMouse::Axis::Axis(u8 index, bool positive, const float* axis)
name = fmt::format("Axis {}{}", static_cast<char>('X' + m_index), (m_positive ? '+' : '-'));
}
+KeyboardMouse::RelativeMouse::RelativeMouse(u8 index, bool positive, const float* axis)
+ : m_axis(axis), m_index(index), m_positive(positive)
+{
+ name =
+ fmt::format("RelativeMouse {}{}", static_cast<char>('X' + m_index), (m_positive ? '+' : '-'));
+}
+
ControlState KeyboardMouse::Axis::GetState() const
{
return std::max(0.0f, *m_axis / (m_positive ? MOUSE_AXIS_SENSITIVITY : -MOUSE_AXIS_SENSITIVITY));
}
+
+ControlState KeyboardMouse::RelativeMouse::GetState() const
+{
+ return std::max(0.0f, *m_axis / (m_positive ? MOUSE_AXIS_SENSITIVITY : -MOUSE_AXIS_SENSITIVITY));
+}
} // namespace ciface::XInput2
diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h
index a9442b6332..71681a3e10 100644
--- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h
+++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h
@@ -30,6 +30,7 @@ private:
unsigned int buttons;
Common::Vec2 cursor;
Common::Vec2 axis;
+ Common::Vec2 relative_mouse;
};
class Key : public Input
@@ -91,6 +92,21 @@ private:
std::string name;
};
+ class RelativeMouse : public Input
+ {
+ public:
+ std::string GetName() const override { return name; }
+ bool IsDetectable() const override { return false; }
+ RelativeMouse(u8 index, bool positive, const float* axis);
+ ControlState GetState() const override;
+
+ private:
+ const float* m_axis;
+ const u8 m_index;
+ const bool m_positive;
+ std::string name;
+ };
+
private:
void SelectEventsForDevice(XIEventMask* mask, int deviceid);
void UpdateCursor();