Skip to content
Snippets Groups Projects
Commit 854c9337 authored by german77's avatar german77 Committed by Narr the Reg
Browse files

input_common: Create input poller and mapping

parent ea7b1fbc
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,12 @@ add_library(input_common STATIC ...@@ -3,6 +3,12 @@ add_library(input_common STATIC
analog_from_button.h analog_from_button.h
keyboard.cpp keyboard.cpp
keyboard.h keyboard.h
input_engine.cpp
input_engine.h
input_mapping.cpp
input_mapping.h
input_poller.cpp
input_poller.h
main.cpp main.cpp
main.h main.h
motion_from_button.cpp motion_from_button.cpp
......
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#include "common/common_types.h"
#include "input_common/input_engine.h"
#include "input_common/input_mapping.h"
namespace InputCommon {
MappingFactory::MappingFactory() {}
void MappingFactory::BeginMapping(Polling::InputType type) {
is_enabled = true;
input_type = type;
input_queue.Clear();
first_axis = -1;
second_axis = -1;
}
[[nodiscard]] const Common::ParamPackage MappingFactory::GetNextInput() {
Common::ParamPackage input;
input_queue.Pop(input);
return input;
}
void MappingFactory::RegisterInput(const MappingData& data) {
if (!is_enabled) {
return;
}
switch (input_type) {
case Polling::InputType::Button:
RegisterButton(data);
return;
case Polling::InputType::Stick:
RegisterStick(data);
return;
case Polling::InputType::Motion:
RegisterMotion(data);
return;
default:
return;
}
}
void MappingFactory::StopMapping() {
is_enabled = false;
input_type = Polling::InputType::None;
input_queue.Clear();
}
void MappingFactory::RegisterButton(const MappingData& data) {
Common::ParamPackage new_input;
new_input.Set("engine", data.engine);
if (data.pad.guid != Common::UUID{}) {
new_input.Set("guid", data.pad.guid.Format());
}
new_input.Set("port", static_cast<int>(data.pad.port));
new_input.Set("pad", static_cast<int>(data.pad.pad));
switch (data.type) {
case EngineInputType::Button:
// Workaround for old compatibility
if (data.engine == "keyboard") {
new_input.Set("code", data.index);
break;
}
new_input.Set("button", data.index);
break;
case EngineInputType::HatButton:
new_input.Set("hat", data.index);
new_input.Set("direction", data.hat_name);
break;
case EngineInputType::Analog:
new_input.Set("axis", data.index);
new_input.Set("threshold", 0.5f);
break;
default:
return;
}
input_queue.Push(new_input);
}
void MappingFactory::RegisterStick(const MappingData& data) {
Common::ParamPackage new_input;
new_input.Set("engine", data.engine);
if (data.pad.guid != Common::UUID{}) {
new_input.Set("guid", data.pad.guid.Format());
}
new_input.Set("port", static_cast<int>(data.pad.port));
new_input.Set("pad", static_cast<int>(data.pad.pad));
// If engine is mouse map the mouse position as a joystick
if (data.engine == "mouse") {
new_input.Set("axis_x", 0);
new_input.Set("axis_y", 1);
new_input.Set("threshold", 0.5f);
new_input.Set("range", 1.0f);
new_input.Set("deadzone", 0.0f);
input_queue.Push(new_input);
return;
}
switch (data.type) {
case EngineInputType::Button:
case EngineInputType::HatButton:
RegisterButton(data);
return;
case EngineInputType::Analog:
if (first_axis == data.index) {
return;
}
if (first_axis == -1) {
first_axis = data.index;
return;
}
new_input.Set("axis_x", first_axis);
new_input.Set("axis_y", data.index);
new_input.Set("threshold", 0.5f);
new_input.Set("range", 0.95f);
new_input.Set("deadzone", 0.15f);
break;
default:
return;
}
input_queue.Push(new_input);
}
void MappingFactory::RegisterMotion(const MappingData& data) {
Common::ParamPackage new_input;
new_input.Set("engine", data.engine);
if (data.pad.guid != Common::UUID{}) {
new_input.Set("guid", data.pad.guid.Format());
}
new_input.Set("port", static_cast<int>(data.pad.port));
new_input.Set("pad", static_cast<int>(data.pad.pad));
switch (data.type) {
case EngineInputType::Button:
case EngineInputType::HatButton:
RegisterButton(data);
return;
case EngineInputType::Analog:
if (first_axis == data.index) {
return;
}
if (second_axis == data.index) {
return;
}
if (first_axis == -1) {
first_axis = data.index;
return;
}
if (second_axis == -1) {
second_axis = data.index;
return;
}
new_input.Set("axis_x", first_axis);
new_input.Set("axis_y", second_axis);
new_input.Set("axis_z", data.index);
new_input.Set("range", 1.0f);
new_input.Set("deadzone", 0.20f);
break;
case EngineInputType::Motion:
new_input.Set("motion", data.index);
break;
default:
return;
}
input_queue.Push(new_input);
}
} // namespace InputCommon
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#pragma once
#include "common/threadsafe_queue.h"
namespace InputCommon {
class InputEngine;
struct MappingData;
class MappingFactory {
public:
MappingFactory();
/**
* Resets all varables to beggin the mapping process
* @param "type": type of input desired to be returned
*/
void BeginMapping(Polling::InputType type);
/// Returns an input event with mapping information from the input_queue
[[nodiscard]] const Common::ParamPackage GetNextInput();
/**
* Registers mapping input data from the driver
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterInput(const MappingData& data);
/// Stop polling from all backends
void StopMapping();
private:
/**
* If provided data satisfies the requeriments it will push an element to the input_queue
* Supported input:
* - Button: Creates a basic button ParamPackage
* - HatButton: Creates a basic hat button ParamPackage
* - Analog: Creates a basic analog ParamPackage
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterButton(const MappingData& data);
/**
* If provided data satisfies the requeriments it will push an element to the input_queue
* Supported input:
* - Button, HatButton: Pass the data to RegisterButton
* - Analog: Stores the first axis and on the second axis creates a basic stick ParamPackage
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterStick(const MappingData& data);
/**
* If provided data satisfies the requeriments it will push an element to the input_queue
* Supported input:
* - Button, HatButton: Pass the data to RegisterButton
* - Analog: Stores the first two axis and on the third axis creates a basic Motion
* ParamPackage
* - Motion: Creates a basic Motion ParamPackage
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterMotion(const MappingData& data);
Common::SPSCQueue<Common::ParamPackage> input_queue;
Polling::InputType input_type{Polling::InputType::None};
bool is_enabled{};
int first_axis = -1;
int second_axis = -1;
};
} // namespace InputCommon
This diff is collapsed.
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#pragma once
namespace Input {
class InputDevice;
template <typename InputDevice>
class Factory;
}; // namespace Input
namespace InputCommon {
class InputEngine;
/**
* An Input factory. It receives input events and forward them to all input devices it created.
*/
class InputFactory final : public Input::Factory<Input::InputDevice> {
public:
explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
/**
* Creates a input device from the parameters given. Identifies the type of input to be returned
* if it contains the following parameters:
* - button: Contains "button" or "code"
* - hat_button: Contains "hat"
* - analog: Contains "axis"
* - trigger: Contains "button" and "axis"
* - stick: Contains "axis_x" and "axis_y"
* - motion: Contains "axis_x", "axis_y" and "axis_z"
* - motion: Contains "motion"
* - touch: Contains "button", "axis_x" and "axis_y"
* - battery: Contains "battery"
* @param params contains parameters for creating the device:
* @param - "code": the code of the keyboard key to bind with the input
* @param - "button": same as "code" but for controller buttons
* @param - "hat": similar as "button" but it's a group of hat buttons from SDL
* @param - "axis": the axis number of the axis to bind with the input
* @param - "motion": the motion number of the motion to bind with the input
* @param - "axis_x": same as axis but specifing horizontal direction
* @param - "axis_y": same as axis but specifing vertical direction
* @param - "axis_z": same as axis but specifing forward direction
* @param - "battery": Only used as a placeholder to set the input type
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
private:
/**
* Creates a button device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "code": the code of the keyboard key to bind with the input
* @param - "button": same as "code" but for controller buttons
* @param - "toggle": press once to enable, press again to disable
* @param - "inverted": inverts the output of the button
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateButtonDevice(const Common::ParamPackage& params);
/**
* Creates a hat button device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "button": the controller hat id to bind with the input
* @param - "direction": the direction id to be detected
* @param - "toggle": press once to enable, press again to disable
* @param - "inverted": inverts the output of the button
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateHatButtonDevice(const Common::ParamPackage& params);
/**
* Creates a stick device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "axis_x": the controller horizontal axis id to bind with the input
* @param - "axis_y": the controller vertical axis id to bind with the input
* @param - "deadzone": the mimimum required value to be detected
* @param - "range": the maximum value required to reach 100%
* @param - "threshold": the mimimum required value to considered pressed
* @param - "offset_x": the amount of offset in the x axis
* @param - "offset_y": the amount of offset in the y axis
* @param - "invert_x": inverts the sign of the horizontal axis
* @param - "invert_y": inverts the sign of the vertical axis
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateStickDevice(const Common::ParamPackage& params);
/**
* Creates an analog device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "axis": the controller axis id to bind with the input
* @param - "deadzone": the mimimum required value to be detected
* @param - "range": the maximum value required to reach 100%
* @param - "threshold": the mimimum required value to considered pressed
* @param - "offset": the amount of offset in the axis
* @param - "invert": inverts the sign of the axis
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateAnalogDevice(const Common::ParamPackage& params);
/**
* Creates a trigger device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "button": the controller hat id to bind with the input
* @param - "direction": the direction id to be detected
* @param - "toggle": press once to enable, press again to disable
* @param - "inverted": inverts the output of the button
* @param - "axis": the controller axis id to bind with the input
* @param - "deadzone": the mimimum required value to be detected
* @param - "range": the maximum value required to reach 100%
* @param - "threshold": the mimimum required value to considered pressed
* @param - "offset": the amount of offset in the axis
* @param - "invert": inverts the sign of the axis
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateTriggerDevice(const Common::ParamPackage& params);
/**
* Creates a touch device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "button": the controller hat id to bind with the input
* @param - "direction": the direction id to be detected
* @param - "toggle": press once to enable, press again to disable
* @param - "inverted": inverts the output of the button
* @param - "axis_x": the controller horizontal axis id to bind with the input
* @param - "axis_y": the controller vertical axis id to bind with the input
* @param - "deadzone": the mimimum required value to be detected
* @param - "range": the maximum value required to reach 100%
* @param - "threshold": the mimimum required value to considered pressed
* @param - "offset_x": the amount of offset in the x axis
* @param - "offset_y": the amount of offset in the y axis
* @param - "invert_x": inverts the sign of the horizontal axis
* @param - "invert_y": inverts the sign of the vertical axis
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateTouchDevice(const Common::ParamPackage& params);
/**
* Creates a battery device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateBatteryDevice(const Common::ParamPackage& params);
/**
* Creates a motion device from the parameters given.
* @param params contains parameters for creating the device:
* @param - "axis_x": the controller horizontal axis id to bind with the input
* @param - "axis_y": the controller vertical axis id to bind with the input
* @param - "axis_z": the controller fordward axis id to bind with the input
* @param - "deadzone": the mimimum required value to be detected
* @param - "range": the maximum value required to reach 100%
* @param - "offset_x": the amount of offset in the x axis
* @param - "offset_y": the amount of offset in the y axis
* @param - "offset_z": the amount of offset in the z axis
* @param - "invert_x": inverts the sign of the horizontal axis
* @param - "invert_y": inverts the sign of the vertical axis
* @param - "invert_z": inverts the sign of the fordward axis
* @param - "guid": text string for identifing controllers
* @param - "port": port of the connected device
* @param - "pad": slot of the connected controller
* @return an unique input device with the parameters specified
*/
std::unique_ptr<Input::InputDevice> CreateMotionDevice(Common::ParamPackage params);
std::shared_ptr<InputEngine> input_engine;
};
} // namespace InputCommon
...@@ -38,6 +38,9 @@ namespace Polling { ...@@ -38,6 +38,9 @@ namespace Polling {
enum class DeviceType { Button, AnalogPreferred, Motion }; enum class DeviceType { Button, AnalogPreferred, Motion };
/// Type of input desired for mapping purposes
enum class InputType { None, Button, Stick, Motion, Touch };
/** /**
* A class that can be used to get inputs from an input device like controllers without having to * A class that can be used to get inputs from an input device like controllers without having to
* poll the device's status yourself * poll the device's status yourself
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment