This commit is contained in:
Nayla Hanegan 2024-11-04 10:59:00 -05:00
commit 76c08d3a22
119 changed files with 47784 additions and 40258 deletions

View file

@ -693,7 +693,7 @@ private:
negative = new AndroidAxis(source, axis, true);
if (positive && negative)
AddAnalogInputs(positive, negative);
AddFullAnalogSurfaceInputs(positive, negative);
else if (positive || negative)
AddInput(positive ? positive : negative);
}

View file

@ -130,38 +130,50 @@ bool Device::Control::IsHidden() const
return false;
}
ControlState Device::FullAnalogSurface::GetState() const
class FullAnalogSurface final : public Device::Input
{
return (1 + std::max(0.0, m_high.GetState()) - std::max(0.0, m_low.GetState())) / 2;
}
public:
FullAnalogSurface(Input* low, Input* high) : m_low(*low), m_high(*high) {}
std::string Device::FullAnalogSurface::GetName() const
ControlState GetState() const override
{
return (1 + std::max(0.0, m_high.GetState()) - std::max(0.0, m_low.GetState())) / 2;
}
std::string GetName() const override
{
// E.g. "Full Axis X+"
return "Full " + m_high.GetName();
}
bool IsDetectable() const override { return m_low.IsDetectable() && m_high.IsDetectable(); }
bool IsHidden() const override { return m_low.IsHidden() && m_high.IsHidden(); }
bool IsMatchingName(std::string_view name) const override
{
if (Control::IsMatchingName(name))
return true;
// Old naming scheme was "Axis X-+" which is too visually similar to "Axis X+".
// This has caused countless problems for users with mysterious misconfigurations.
// We match this old name to support old configurations.
const auto old_name = m_low.GetName() + *m_high.GetName().rbegin();
return old_name == name;
}
private:
Input& m_low;
Input& m_high;
};
void Device::AddFullAnalogSurfaceInputs(Input* low, Input* high)
{
// E.g. "Full Axis X+"
return "Full " + m_high.GetName();
}
bool Device::FullAnalogSurface::IsDetectable() const
{
return m_low.IsDetectable() && m_high.IsDetectable();
}
bool Device::FullAnalogSurface::IsHidden() const
{
return m_low.IsHidden() && m_high.IsHidden();
}
bool Device::FullAnalogSurface::IsMatchingName(std::string_view name) const
{
if (Control::IsMatchingName(name))
return true;
// Old naming scheme was "Axis X-+" which is too visually similar to "Axis X+".
// This has caused countless problems for users with mysterious misconfigurations.
// We match this old name to support old configurations.
const auto old_name = m_low.GetName() + *m_high.GetName().rbegin();
return old_name == name;
AddInput(low);
AddInput(high);
AddInput(new FullAnalogSurface(low, high));
AddInput(new FullAnalogSurface(high, low));
}
void Device::AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs)

View file

@ -163,28 +163,14 @@ protected:
void AddInput(Input* const i);
void AddOutput(Output* const o);
class FullAnalogSurface final : public Input
{
public:
FullAnalogSurface(Input* low, Input* high) : m_low(*low), m_high(*high) {}
ControlState GetState() const override;
std::string GetName() const override;
bool IsDetectable() const override;
bool IsHidden() const override;
bool IsMatchingName(std::string_view name) const override;
private:
Input& m_low;
Input& m_high;
};
void AddAnalogInputs(Input* low, Input* high)
{
AddInput(low);
AddInput(high);
AddInput(new FullAnalogSurface(low, high));
AddInput(new FullAnalogSurface(high, low));
}
// Pass Inputs for center-neutral (- and +) directions of some axis.
// This function adds those Inputs and also a FullAnalogSurface Input for each direction.
// This is only needed when it's not known if the particular axis is neutral in the center
// or neutral on one of the extremes.
// Some e.g. DInput devices expose a trigger across the full analog surface
// but we have no way of knowing this until the user actually maps the Input,
// so both center-neutral and full-surface Inputs need to be created in that case.
void AddFullAnalogSurfaceInputs(Input* low, Input* high);
void AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs);

View file

@ -167,8 +167,8 @@ Joystick::Joystick(const LPDIRECTINPUTDEVICE8 device) : m_device(device)
const LONG& ax = (&m_state_in.lX)[offset];
// each axis gets a negative and a positive input instance associated with it
AddAnalogInputs(new Axis(offset, ax, base, range.lMin - base),
new Axis(offset, ax, base, range.lMax - base));
AddFullAnalogSurfaceInputs(new Axis(offset, ax, base, range.lMin - base),
new Axis(offset, ax, base, range.lMax - base));
}
}

View file

@ -129,7 +129,7 @@ void PipeDevice::AddAxis(const std::string& name, double value)
ax_lo->SetState(value);
m_axes[name + " +"] = ax_hi;
m_axes[name + " -"] = ax_lo;
AddAnalogInputs(ax_lo, ax_hi);
AddFullAnalogSurfaceInputs(ax_lo, ax_hi);
}
void PipeDevice::SetAxis(const std::string& entry, double value)

View file

@ -263,18 +263,16 @@ private:
};
public:
GameController(SDL_GameController* const gamecontroller, SDL_Joystick* const joystick,
const int sdl_index);
GameController(SDL_GameController* const gamecontroller, SDL_Joystick* const joystick);
~GameController();
std::string GetName() const override;
std::string GetSource() const override;
int GetSDLIndex() const;
int GetSDLInstanceID() const;
private:
SDL_GameController* const m_gamecontroller;
std::string m_name;
int m_sdl_index;
SDL_Joystick* const m_joystick;
SDL_Haptic* m_haptic = nullptr;
};
@ -318,7 +316,7 @@ void InputBackend::OpenAndAddDevice(int index)
// SDL tries parsing these as Joysticks
return;
}
auto gamecontroller = std::make_shared<GameController>(gc, js, index);
auto gamecontroller = std::make_shared<GameController>(gc, js);
if (!gamecontroller->Inputs().empty() || !gamecontroller->Outputs().empty())
GetControllerInterface().AddDevice(std::move(gamecontroller));
}
@ -326,25 +324,20 @@ void InputBackend::OpenAndAddDevice(int index)
bool InputBackend::HandleEventAndContinue(const SDL_Event& e)
{
if (e.type == SDL_CONTROLLERDEVICEADDED || e.type == SDL_JOYDEVICEADDED)
if (e.type == SDL_JOYDEVICEADDED)
{
// Avoid handling the event twice on a GameController
if (e.type == SDL_JOYDEVICEADDED && SDL_IsGameController(e.jdevice.which))
{
return true;
}
// NOTE: SDL_JOYDEVICEADDED's `jdevice.which` is a device index in SDL2.
// It will change to an "instance ID" in SDL3.
// OpenAndAddDevice impl and calls will need refactoring when changing to SDL3.
static_assert(!SDL_VERSION_ATLEAST(3, 0, 0), "Refactoring is needed for SDL3.");
OpenAndAddDevice(e.jdevice.which);
}
else if (e.type == SDL_CONTROLLERDEVICEREMOVED || e.type == SDL_JOYDEVICEREMOVED)
else if (e.type == SDL_JOYDEVICEREMOVED)
{
// Avoid handling the event twice on a GameController
if (e.type == SDL_JOYDEVICEREMOVED && SDL_IsGameController(e.jdevice.which))
{
return true;
}
// NOTE: SDL_JOYDEVICEREMOVED's `jdevice.which` is an "instance ID".
GetControllerInterface().RemoveDevice([&e](const auto* device) {
return device->GetSource() == "SDL" &&
static_cast<const GameController*>(device)->GetSDLIndex() == e.jdevice.which;
static_cast<const GameController*>(device)->GetSDLInstanceID() == e.jdevice.which;
});
}
else if (e.type == m_populate_event_type)
@ -442,6 +435,9 @@ InputBackend::InputBackend(ControllerInterface* controller_interface)
// We want buttons to come in as positions, not labels
SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0");
// Disable DualSense Player LEDs; We already colorize the Primary LED
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "0");
m_hotplug_thread = std::thread([this] {
Common::ScopeGuard quit_guard([] {
// TODO: there seems to be some sort of memory leak with SDL, quit isn't freeing everything up
@ -585,8 +581,8 @@ static constexpr SDLMotionAxisList SDL_AXES_GYRO = {{
// clang-format on
GameController::GameController(SDL_GameController* const gamecontroller,
SDL_Joystick* const joystick, const int sdl_index)
: m_gamecontroller(gamecontroller), m_sdl_index(sdl_index), m_joystick(joystick)
SDL_Joystick* const joystick)
: m_gamecontroller(gamecontroller), m_joystick(joystick)
{
const char* name;
if (gamecontroller)
@ -714,8 +710,8 @@ GameController::GameController(SDL_GameController* const gamecontroller,
const bool is_registered = registered_axes.contains(i);
// each axis gets a negative and a positive input instance associated with it
AddAnalogInputs(new LegacyAxis(m_joystick, i, -32768, is_registered),
new LegacyAxis(m_joystick, i, 32767, is_registered));
AddFullAnalogSurfaceInputs(new LegacyAxis(m_joystick, i, -32768, is_registered),
new LegacyAxis(m_joystick, i, 32767, is_registered));
}
// Hats
@ -809,9 +805,9 @@ std::string GameController::GetSource() const
return "SDL";
}
int GameController::GetSDLIndex() const
int GameController::GetSDLInstanceID() const
{
return m_sdl_index;
return SDL_JoystickInstanceID(m_joystick);
}
std::string GameController::Button::GetName() const

View file

@ -125,9 +125,8 @@ public:
u32 i = 0;
for (auto& axis : m_axes)
{
// AddAnalogInputs adds additional "FullAnalogSurface" Inputs.
AddAnalogInputs(new IndexedAxis(&axis, 0.5, +0.5, i),
new IndexedAxis(&axis, 0.5, -0.5, i));
AddFullAnalogSurfaceInputs(new IndexedAxis(&axis, 0.5, +0.5, i),
new IndexedAxis(&axis, 0.5, -0.5, i));
++i;
}
}

View file

@ -572,7 +572,8 @@ bool evdevDevice::AddNode(std::string devnode, int fd, libevdev* dev)
{
if (libevdev_has_event_code(dev, EV_ABS, axis))
{
AddAnalogInputs(new Axis(num_axis, axis, false, dev), new Axis(num_axis, axis, true, dev));
AddFullAnalogSurfaceInputs(new Axis(num_axis, axis, false, dev),
new Axis(num_axis, axis, true, dev));
++num_axis;
}
}