Merge pull request #5233 from german77/inverted
InputCommon: Allow to invert analog axis with right click
This commit is contained in:
		| @@ -139,10 +139,10 @@ void GCButtonFactory::EndConfiguration() { | ||||
|  | ||||
| class GCAnalog final : public Input::AnalogDevice { | ||||
| public: | ||||
|     explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_, | ||||
|                       const GCAdapter::Adapter* adapter, float range_) | ||||
|         : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter), | ||||
|           range(range_) {} | ||||
|     explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_, | ||||
|                       float deadzone_, float range_, const GCAdapter::Adapter* adapter) | ||||
|         : port(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_), | ||||
|           deadzone(deadzone_), range(range_), gcadapter(adapter) {} | ||||
|  | ||||
|     float GetAxis(u32 axis) const { | ||||
|         if (gcadapter->DeviceConnected(port)) { | ||||
| @@ -157,7 +157,12 @@ public: | ||||
|     std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { | ||||
|         float x = GetAxis(analog_axis_x); | ||||
|         float y = GetAxis(analog_axis_y); | ||||
|  | ||||
|         if (invert_x) { | ||||
|             x = -x; | ||||
|         } | ||||
|         if (invert_y) { | ||||
|             y = -y; | ||||
|         } | ||||
|         // Make sure the coordinates are in the unit circle, | ||||
|         // otherwise normalize it. | ||||
|         float r = x * x + y * y; | ||||
| @@ -200,9 +205,11 @@ private: | ||||
|     const u32 port; | ||||
|     const u32 axis_x; | ||||
|     const u32 axis_y; | ||||
|     const bool invert_x; | ||||
|     const bool invert_y; | ||||
|     const float deadzone; | ||||
|     const GCAdapter::Adapter* gcadapter; | ||||
|     const float range; | ||||
|     const GCAdapter::Adapter* gcadapter; | ||||
|     mutable std::mutex mutex; | ||||
| }; | ||||
|  | ||||
| @@ -223,8 +230,13 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param | ||||
|     const auto axis_y = static_cast<u32>(params.Get("axis_y", 1)); | ||||
|     const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); | ||||
|     const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | ||||
|     const std::string invert_x_value = params.Get("invert_x", "+"); | ||||
|     const std::string invert_y_value = params.Get("invert_y", "+"); | ||||
|     const bool invert_x = invert_x_value == "-"; | ||||
|     const bool invert_y = invert_y_value == "-"; | ||||
|  | ||||
|     return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); | ||||
|     return std::make_unique<GCAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range, | ||||
|                                       adapter.get()); | ||||
| } | ||||
|  | ||||
| void GCAnalogFactory::BeginConfiguration() { | ||||
| @@ -282,6 +294,8 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() { | ||||
|         params.Set("port", controller_number); | ||||
|         params.Set("axis_x", analog_x_axis); | ||||
|         params.Set("axis_y", analog_y_axis); | ||||
|         params.Set("invert_x", "+"); | ||||
|         params.Set("invert_y", "+"); | ||||
|         analog_x_axis = -1; | ||||
|         analog_y_axis = -1; | ||||
|         controller_number = -1; | ||||
|   | ||||
| @@ -62,10 +62,10 @@ void MouseButtonFactory::EndConfiguration() { | ||||
|  | ||||
| class MouseAnalog final : public Input::AnalogDevice { | ||||
| public: | ||||
|     explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_, float range_, | ||||
|                          const MouseInput::Mouse* mouse_input_) | ||||
|         : button(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), range(range_), | ||||
|           mouse_input(mouse_input_) {} | ||||
|     explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_, | ||||
|                          float deadzone_, float range_, const MouseInput::Mouse* mouse_input_) | ||||
|         : button(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_), | ||||
|           deadzone(deadzone_), range(range_), mouse_input(mouse_input_) {} | ||||
|  | ||||
|     float GetAxis(u32 axis) const { | ||||
|         std::lock_guard lock{mutex}; | ||||
| @@ -77,6 +77,12 @@ public: | ||||
|     std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { | ||||
|         float x = GetAxis(analog_axis_x); | ||||
|         float y = GetAxis(analog_axis_y); | ||||
|         if (invert_x) { | ||||
|             x = -x; | ||||
|         } | ||||
|         if (invert_y) { | ||||
|             y = -y; | ||||
|         } | ||||
|  | ||||
|         // Make sure the coordinates are in the unit circle, | ||||
|         // otherwise normalize it. | ||||
| @@ -104,6 +110,8 @@ private: | ||||
|     const u32 button; | ||||
|     const u32 axis_x; | ||||
|     const u32 axis_y; | ||||
|     const bool invert_x; | ||||
|     const bool invert_y; | ||||
|     const float deadzone; | ||||
|     const float range; | ||||
|     const MouseInput::Mouse* mouse_input; | ||||
| @@ -128,8 +136,13 @@ std::unique_ptr<Input::AnalogDevice> MouseAnalogFactory::Create( | ||||
|     const auto axis_y = static_cast<u32>(params.Get("axis_y", 1)); | ||||
|     const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); | ||||
|     const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | ||||
|     const std::string invert_x_value = params.Get("invert_x", "+"); | ||||
|     const std::string invert_y_value = params.Get("invert_y", "+"); | ||||
|     const bool invert_x = invert_x_value == "-"; | ||||
|     const bool invert_y = invert_y_value == "-"; | ||||
|  | ||||
|     return std::make_unique<MouseAnalog>(port, axis_x, axis_y, deadzone, range, mouse_input.get()); | ||||
|     return std::make_unique<MouseAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range, | ||||
|                                          mouse_input.get()); | ||||
| } | ||||
|  | ||||
| void MouseAnalogFactory::BeginConfiguration() { | ||||
| @@ -153,6 +166,8 @@ Common::ParamPackage MouseAnalogFactory::GetNextInput() const { | ||||
|             params.Set("port", static_cast<u16>(pad.button)); | ||||
|             params.Set("axis_x", 0); | ||||
|             params.Set("axis_y", 1); | ||||
|             params.Set("invert_x", "+"); | ||||
|             params.Set("invert_y", "+"); | ||||
|             return params; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -352,13 +352,20 @@ private: | ||||
| class SDLAnalog final : public Input::AnalogDevice { | ||||
| public: | ||||
|     explicit SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, | ||||
|                        float deadzone_, float range_) | ||||
|         : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), | ||||
|           range(range_) {} | ||||
|                        bool invert_x_, bool invert_y_, float deadzone_, float range_) | ||||
|         : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), | ||||
|           invert_y(invert_y_), deadzone(deadzone_), range(range_) {} | ||||
|  | ||||
|     std::tuple<float, float> GetStatus() const override { | ||||
|         const auto [x, y] = joystick->GetAnalog(axis_x, axis_y, range); | ||||
|         auto [x, y] = joystick->GetAnalog(axis_x, axis_y, range); | ||||
|         const float r = std::sqrt((x * x) + (y * y)); | ||||
|         if (invert_x) { | ||||
|             x = -x; | ||||
|         } | ||||
|         if (invert_y) { | ||||
|             y = -y; | ||||
|         } | ||||
|  | ||||
|         if (r > deadzone) { | ||||
|             return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), | ||||
|                                    y / r * (r - deadzone) / (1 - deadzone)); | ||||
| @@ -386,6 +393,8 @@ private: | ||||
|     std::shared_ptr<SDLJoystick> joystick; | ||||
|     const int axis_x; | ||||
|     const int axis_y; | ||||
|     const bool invert_x; | ||||
|     const bool invert_y; | ||||
|     const float deadzone; | ||||
|     const float range; | ||||
| }; | ||||
| @@ -572,12 +581,17 @@ public: | ||||
|         const int axis_y = params.Get("axis_y", 1); | ||||
|         const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); | ||||
|         const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | ||||
|         const std::string invert_x_value = params.Get("invert_x", "+"); | ||||
|         const std::string invert_y_value = params.Get("invert_y", "+"); | ||||
|         const bool invert_x = invert_x_value == "-"; | ||||
|         const bool invert_y = invert_y_value == "-"; | ||||
|         auto joystick = state.GetSDLJoystickByGUID(guid, port); | ||||
|  | ||||
|         // This is necessary so accessing GetAxis with axis_x and axis_y won't crash | ||||
|         joystick->SetAxis(axis_x, 0); | ||||
|         joystick->SetAxis(axis_y, 0); | ||||
|         return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone, range); | ||||
|         return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, invert_x, invert_y, deadzone, | ||||
|                                            range); | ||||
|     } | ||||
|  | ||||
| private: | ||||
| @@ -886,6 +900,8 @@ Common::ParamPackage BuildParamPackageForAnalog(int port, const std::string& gui | ||||
|     params.Set("guid", guid); | ||||
|     params.Set("axis_x", axis_x); | ||||
|     params.Set("axis_y", axis_y); | ||||
|     params.Set("invert_x", "+"); | ||||
|     params.Set("invert_y", "+"); | ||||
|     return params; | ||||
| } | ||||
| } // Anonymous namespace | ||||
|   | ||||
| @@ -173,61 +173,31 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) | ||||
|         return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); | ||||
|     } | ||||
|  | ||||
|     if (param.Get("engine", "") == "sdl") { | ||||
|     const auto engine_str = param.Get("engine", ""); | ||||
|     const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); | ||||
|     const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); | ||||
|     const bool invert_x = param.Get("invert_x", "+") == "-"; | ||||
|     const bool invert_y = param.Get("invert_y", "+") == "-"; | ||||
|     if (engine_str == "sdl" || engine_str == "gcpad" || engine_str == "mouse") { | ||||
|         if (dir == "modifier") { | ||||
|             return QObject::tr("[unused]"); | ||||
|         } | ||||
|  | ||||
|         if (dir == "left" || dir == "right") { | ||||
|             const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); | ||||
|  | ||||
|             return QObject::tr("Axis %1").arg(axis_x_str); | ||||
|         if (dir == "left") { | ||||
|             const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-"); | ||||
|             return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); | ||||
|         } | ||||
|  | ||||
|         if (dir == "up" || dir == "down") { | ||||
|             const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); | ||||
|  | ||||
|             return QObject::tr("Axis %1").arg(axis_y_str); | ||||
|         if (dir == "right") { | ||||
|             const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+"); | ||||
|             return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); | ||||
|         } | ||||
|  | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     if (param.Get("engine", "") == "gcpad") { | ||||
|         if (dir == "modifier") { | ||||
|             return QObject::tr("[unused]"); | ||||
|         if (dir == "up") { | ||||
|             const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+"); | ||||
|             return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); | ||||
|         } | ||||
|  | ||||
|         if (dir == "left" || dir == "right") { | ||||
|             const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); | ||||
|  | ||||
|             return QObject::tr("GC Axis %1").arg(axis_x_str); | ||||
|         } | ||||
|  | ||||
|         if (dir == "up" || dir == "down") { | ||||
|             const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); | ||||
|  | ||||
|             return QObject::tr("GC Axis %1").arg(axis_y_str); | ||||
|         } | ||||
|  | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     if (param.Get("engine", "") == "mouse") { | ||||
|         if (dir == "modifier") { | ||||
|             return QObject::tr("[unused]"); | ||||
|         } | ||||
|  | ||||
|         if (dir == "left" || dir == "right") { | ||||
|             const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); | ||||
|  | ||||
|             return QObject::tr("Mouse %1").arg(axis_x_str); | ||||
|         } | ||||
|  | ||||
|         if (dir == "up" || dir == "down") { | ||||
|             const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); | ||||
|  | ||||
|             return QObject::tr("Mouse %1").arg(axis_y_str); | ||||
|         if (dir == "down") { | ||||
|             const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-"); | ||||
|             return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); | ||||
|         } | ||||
|  | ||||
|         return {}; | ||||
| @@ -396,6 +366,25 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|                             analogs_param[analog_id].Clear(); | ||||
|                             analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); | ||||
|                         }); | ||||
|                         context_menu.addAction(tr("Invert axis"), [&] { | ||||
|                             if (sub_button_id == 2 || sub_button_id == 3) { | ||||
|                                 const bool invert_value = | ||||
|                                     analogs_param[analog_id].Get("invert_x", "+") == "-"; | ||||
|                                 const std::string invert_str = invert_value ? "+" : "-"; | ||||
|                                 analogs_param[analog_id].Set("invert_x", invert_str); | ||||
|                             } | ||||
|                             if (sub_button_id == 0 || sub_button_id == 1) { | ||||
|                                 const bool invert_value = | ||||
|                                     analogs_param[analog_id].Get("invert_y", "+") == "-"; | ||||
|                                 const std::string invert_str = invert_value ? "+" : "-"; | ||||
|                                 analogs_param[analog_id].Set("invert_y", invert_str); | ||||
|                             } | ||||
|                             for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; | ||||
|                                  ++sub_button_id) { | ||||
|                                 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( | ||||
|                                     analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | ||||
|                             } | ||||
|                         }); | ||||
|                         context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( | ||||
|                             menu_location)); | ||||
|                     }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei