Add support for several joysticks at the smae time

This commit is contained in:
Malin E
2021-11-04 13:19:43 +01:00
parent 8bddf38f02
commit 3526e14e66
8 changed files with 359 additions and 166 deletions

View File

@@ -77,43 +77,55 @@ public:
void updateStateFromInput(
const JoystickInputStates& joystickInputStates, double deltaTime);
void setAxisMapping(int axis, AxisType mapping,
void setAxisMapping(const std::string& joystickName, int axis, AxisType mapping,
AxisInvert shouldInvert = AxisInvert::No,
AxisNormalize shouldNormalize = AxisNormalize::No,
bool isSticky = false, double sensitivity = 0.0
);
AxisInformation axisMapping(int axis) const;
AxisInformation axisMapping(const std::string& joystickName, int axis) const;
void setDeadzone(int axis, float deadzone);
float deadzone(int axis) const;
void setDeadzone(const std::string& joystickName, int axis, float deadzone);
float deadzone(const std::string& joystickName, int axis) const;
void bindButtonCommand(int button, std::string command, JoystickAction action,
ButtonCommandRemote remote, std::string documentation);
void clearButtonCommand(int button);
std::vector<std::string> buttonCommand(int button) const;
void bindButtonCommand(const std::string& joystickName, int button,
std::string command, JoystickAction action, ButtonCommandRemote remote,
std::string documentation);
void clearButtonCommand(const std::string& joystickName, int button);
std::vector<std::string> buttonCommand(const std::string& joystickName,
int button) const;
private:
// We use an array for the axes and a map for the buttons since the axis are going to
// be accessed much more often and thus have to be more efficient. And storing a few
// extra AxisInformation that are not used will not matter that much; finding an axis
// location in a potential map each frame, however, would
struct JoystickCameraState {
std::string joystickName;
std::array<AxisInformation, JoystickInputState::MaxAxes> _axisMapping;
// We use an array for the axes and a map for the buttons since the axis are going to
// be accessed much more often and thus have to be more efficient. And storing a few
// extra AxisInformation that are not used will not matter that much; finding an axis
// location in a potential map each frame, however, would
// This array is used to store the old axis values from the previous frame,
// it is used to calculate the difference in the values in the case of a sticky axis
std::array<float, JoystickInputState::MaxAxes> _prevAxisValues;
std::array<AxisInformation, JoystickInputState::MaxAxes> axisMapping;
struct ButtonInformation {
std::string command;
JoystickAction action;
ButtonCommandRemote synchronization;
std::string documentation;
// This array is used to store the old axis values from the previous frame,
// it is used to calculate the difference in the values in the case of a sticky axis
std::array<float, JoystickInputState::MaxAxes> prevAxisValues;
struct ButtonInformation {
std::string command;
JoystickAction action;
ButtonCommandRemote synchronization;
std::string documentation;
};
std::multimap<int, ButtonInformation> buttonMapping;
};
std::multimap<int, ButtonInformation> _buttonMapping;
std::vector<JoystickCameraState> _joystickCameraStates;
// Find the item in _joystickCameraStates that corresponds to the given joystickName
// return a pointer to the item, if not found then return nullptr
JoystickCameraState* getJoystickCameraState(const std::string& joystickName);
const JoystickCameraState* getJoystickCameraState(const std::string& joystickName) const;
};
} // namespace openspace::interaction

View File

@@ -72,11 +72,6 @@ struct JoystickInputState {
/// \c nAxes values are defined values, the rest are undefined
std::array<float, MaxAxes> axes;
/// The axis values can either go back to 0 when the joystick is released or it can
/// stay at the value it was before the joystick was released.
/// The latter is called a sticky axis, when the values don't go back to 0.
bool isSticky = false;
/// The number of buttons that this joystick possesses
int nButtons = 0;
/// The status of each button. Only the first \c nButtons values are defined, the rest
@@ -88,6 +83,10 @@ struct JoystickInputState {
/// derived from the available GLFW constants
constexpr const int MaxJoysticks = 16;
struct JoystickInputStates : public std::array<JoystickInputState, MaxJoysticks> {
/// The maximum number of joysticks that are supported by this system. This number is
/// derived from the available GLFW constants
static constexpr const int MaxNumJoysticks = 16;
/**
* This function adds the contributions of all connected joysticks for the provided
* \p axis. After adding each joysticks contribution, the result is clamped to [-1,1].
@@ -99,7 +98,7 @@ struct JoystickInputStates : public std::array<JoystickInputState, MaxJoysticks>
*
* \pre \p axis must be 0 or positive
*/
float axis(int axis) const;
float axis(const std::string& joystickName, int axis) const;
/**
* This functions checks whether any connected joystick has its \p button in the
@@ -113,7 +112,7 @@ struct JoystickInputStates : public std::array<JoystickInputState, MaxJoysticks>
*
* \pre \p button must be 0 or positive
*/
bool button(int button, JoystickAction action) const;
bool button(const std::string& joystickName, int button, JoystickAction action) const;
};
} // namespace openspace::interaction

View File

@@ -98,7 +98,8 @@ public:
void mousePositionCallback(double x, double y);
void mouseScrollWheelCallback(double pos);
void setJoystickAxisMapping(int axis, JoystickCameraStates::AxisType mapping,
void setJoystickAxisMapping(const std::string& joystickName,
int axis, JoystickCameraStates::AxisType mapping,
JoystickCameraStates::AxisInvert shouldInvert =
JoystickCameraStates::AxisInvert::No,
JoystickCameraStates::AxisNormalize shouldNormalize =
@@ -106,16 +107,20 @@ public:
bool isSticky = false, double sensitivity = 0.0
);
JoystickCameraStates::AxisInformation joystickAxisMapping(int axis) const;
JoystickCameraStates::AxisInformation joystickAxisMapping(
const std::string& joystickName, int axis) const;
void setJoystickAxisDeadzone(int axis, float deadzone);
float joystickAxisDeadzone(int axis) const;
void setJoystickAxisDeadzone(const std::string& joystickName, int axis,
float deadzone);
float joystickAxisDeadzone(const std::string& joystickName, int axis) const;
void bindJoystickButtonCommand(int button, std::string command, JoystickAction action,
void bindJoystickButtonCommand(const std::string& joystickName, int button,
std::string command, JoystickAction action,
JoystickCameraStates::ButtonCommandRemote remote, std::string documentation);
void clearJoystickButtonCommand(int button);
std::vector<std::string> joystickButtonCommand(int button) const;
void clearJoystickButtonCommand(const std::string& joystickName, int button);
std::vector<std::string> joystickButtonCommand(const std::string& joystickName,
int button) const;
// Websockets
void setWebsocketAxisMapping(int axis, WebsocketCameraStates::AxisType mapping,

View File

@@ -26,7 +26,6 @@
#include <modules/imgui/include/imgui_include.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/interaction/joystickinputstate.h>
namespace {
@@ -86,7 +85,7 @@ void GuiJoystickComponent::render() {
ImGui::Text("%s", "Summed contributions");
ImGui::Text("%s", "Axes");
for (int i = 0; i < JoystickInputState::MaxAxes; ++i) {
float f = global::joystickInputStates->axis(i);
float f = global::joystickInputStates->axis("", i);
ImGui::SliderFloat(
std::to_string(i).c_str(),
&f,
@@ -98,8 +97,8 @@ void GuiJoystickComponent::render() {
for (int i = 0; i < JoystickInputState::MaxButtons; ++i) {
ImGui::RadioButton(
std::to_string(i).c_str(),
global::joystickInputStates->button(i, JoystickAction::Press) ||
global::joystickInputStates->button(i, JoystickAction::Repeat)
global::joystickInputStates->button("", i, JoystickAction::Press) ||
global::joystickInputStates->button("", i, JoystickAction::Repeat)
);
}

View File

@@ -26,10 +26,15 @@
#include <openspace/engine/globals.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/exception.h>
#include <cmath>
#include <utility>
namespace {
constexpr const char* _loggerCat = "JoystickCameraStates";
} // namespace
namespace openspace::interaction {
JoystickCameraStates::JoystickCameraStates(double sensitivity, double velocityScaleFactor)
@@ -46,49 +51,61 @@ void JoystickCameraStates::updateStateFromInput(
std::pair<bool, glm::dvec2> globalRoll = { false, glm::dvec2(0.0) };
std::pair<bool, glm::dvec2> localRotation = { false, glm::dvec2(0.0) };
for (int i = 0; i < JoystickInputState::MaxAxes; ++i) {
AxisInformation t = _axisMapping[i];
if (t.type == AxisType::None) {
for (const JoystickInputState& joystickInputState : joystickInputStates) {
if (joystickInputState.name.empty()) {
continue;
}
float rawValue = joystickInputStates.axis(i);
float value = rawValue;
JoystickCameraState* joystickCameraState =
getJoystickCameraState(joystickInputState.name);
if (t.isSticky) {
value = rawValue - _prevAxisValues[i];
_prevAxisValues[i] = rawValue;
}
if (std::fabs(value) <= t.deadzone) {
if (!joystickCameraState) {
continue;
}
if (t.normalize) {
value = (value + 1.f) / 2.f;
}
for (int i = 0; i < JoystickInputState::MaxAxes; ++i) {
AxisInformation t = joystickCameraState->axisMapping[i];
if (t.type == AxisType::None) {
continue;
}
if (t.invert) {
value *= -1.f;
}
float rawValue = joystickInputStates.axis(joystickInputState.name, i);
float value = rawValue;
if (std::abs(t.sensitivity) > std::numeric_limits<double>::epsilon()) {
value = static_cast<float>(value * t.sensitivity * _sensitivity);
}
else {
value = static_cast<float>(value * _sensitivity);
}
if (t.isSticky) {
value = rawValue - joystickCameraState->prevAxisValues[i];
joystickCameraState->prevAxisValues[i] = rawValue;
}
switch (t.type) {
if (std::fabs(value) <= t.deadzone) {
continue;
}
if (t.normalize) {
value = (value + 1.f) / 2.f;
}
if (t.invert) {
value *= -1.f;
}
if (std::abs(t.sensitivity) > std::numeric_limits<double>::epsilon()) {
value = static_cast<float>(value * t.sensitivity * _sensitivity);
}
else {
value = static_cast<float>(value * _sensitivity);
}
switch (t.type) {
case AxisType::None:
break;
case AxisType::OrbitX:
globalRotation.first = true;
globalRotation.second.x = value;
globalRotation.second.x += value;
break;
case AxisType::OrbitY:
globalRotation.first = true;
globalRotation.second.y = value;
globalRotation.second.y += value;
break;
case AxisType::Zoom:
case AxisType::ZoomIn:
@@ -101,28 +118,47 @@ void JoystickCameraStates::updateStateFromInput(
break;
case AxisType::LocalRollX:
localRoll.first = true;
localRoll.second.x = value;
localRoll.second.x += value;
break;
case AxisType::LocalRollY:
localRoll.first = true;
localRoll.second.y = value;
localRoll.second.y += value;
break;
case AxisType::GlobalRollX:
globalRoll.first = true;
globalRoll.second.x = value;
globalRoll.second.x += value;
break;
case AxisType::GlobalRollY:
globalRoll.first = true;
globalRoll.second.y = value;
globalRoll.second.y += value;
break;
case AxisType::PanX:
localRotation.first = true;
localRotation.second.x = value;
localRotation.second.x += value;
break;
case AxisType::PanY:
localRotation.first = true;
localRotation.second.y = value;
localRotation.second.y += value;
break;
}
}
for (int i = 0; i < JoystickInputState::MaxButtons; ++i) {
auto itRange = joystickCameraState->buttonMapping.equal_range(i);
for (auto it = itRange.first; it != itRange.second; ++it) {
bool active =global::joystickInputStates->button(
joystickInputState.name,
i,
it->second.action
);
if (active) {
global::scriptEngine->queueScript(
it->second.command,
scripting::ScriptEngine::RemoteScripting(it->second.synchronization)
);
}
}
}
}
@@ -160,23 +196,10 @@ void JoystickCameraStates::updateStateFromInput(
else {
_localRotationState.velocity.decelerate(deltaTime);
}
for (int i = 0; i < JoystickInputState::MaxButtons; ++i) {
auto itRange = _buttonMapping.equal_range(i);
for (auto it = itRange.first; it != itRange.second; ++it) {
bool active = global::joystickInputStates->button(i, it->second.action);
if (active) {
global::scriptEngine->queueScript(
it->second.command,
scripting::ScriptEngine::RemoteScripting(it->second.synchronization)
);
}
}
}
}
void JoystickCameraStates::setAxisMapping(int axis, AxisType mapping,
void JoystickCameraStates::setAxisMapping(const std::string& joystickName,
int axis, AxisType mapping,
AxisInvert shouldInvert,
AxisNormalize shouldNormalize,
bool isSticky,
@@ -184,48 +207,119 @@ void JoystickCameraStates::setAxisMapping(int axis, AxisType mapping,
{
ghoul_assert(axis < JoystickInputState::MaxAxes, "axis must be < MaxAxes");
_axisMapping[axis].type = mapping;
_axisMapping[axis].invert = shouldInvert;
_axisMapping[axis].normalize = shouldNormalize;
_axisMapping[axis].isSticky = isSticky;
_axisMapping[axis].sensitivity = sensitivity;
if (isSticky) {
global::joystickInputStates->at(axis).isSticky = true;
JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
if (_joystickCameraStates.size() < JoystickInputStates::MaxNumJoysticks) {
_joystickCameraStates.push_back(JoystickCameraState());
joystickCameraState = &_joystickCameraStates.back();
joystickCameraState->joystickName = joystickName;
}
else {
LWARNING(fmt::format("Cannot add more joysticks, only {} joysticks are "
"supported", JoystickInputStates::MaxNumJoysticks));
return;
}
}
_prevAxisValues[axis] = global::joystickInputStates->axis(axis);
joystickCameraState->axisMapping[axis].type = mapping;
joystickCameraState->axisMapping[axis].invert = shouldInvert;
joystickCameraState->axisMapping[axis].normalize = shouldNormalize;
joystickCameraState->axisMapping[axis].isSticky = isSticky;
joystickCameraState->axisMapping[axis].sensitivity = sensitivity;
joystickCameraState->prevAxisValues[axis] =
global::joystickInputStates->axis(joystickName, axis);
}
JoystickCameraStates::AxisInformation JoystickCameraStates::axisMapping(int axis) const {
return _axisMapping[axis];
JoystickCameraStates::AxisInformation JoystickCameraStates::axisMapping(
const std::string& joystickName,
int axis) const
{
const JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
LWARNING(fmt::format("Cannot find JoystickCameraState with name '{}' "
"(axisMapping)", joystickName));
JoystickCameraStates::AxisInformation dummy;
return dummy;
}
return joystickCameraState->axisMapping[axis];
}
void JoystickCameraStates::setDeadzone(int axis, float deadzone) {
_axisMapping[axis].deadzone = deadzone;
void JoystickCameraStates::setDeadzone(const std::string& joystickName, int axis,
float deadzone)
{
JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
if (_joystickCameraStates.size() < JoystickInputStates::MaxNumJoysticks) {
_joystickCameraStates.push_back(JoystickCameraState());
joystickCameraState = &_joystickCameraStates.back();
joystickCameraState->joystickName = joystickName;
}
else {
LWARNING(fmt::format("Cannot add more joysticks, only {} joysticks are "
"supported", JoystickInputStates::MaxNumJoysticks));
return;
}
}
joystickCameraState->axisMapping[axis].deadzone = deadzone;
}
float JoystickCameraStates::deadzone(int axis) const {
return _axisMapping[axis].deadzone;
float JoystickCameraStates::deadzone(const std::string& joystickName, int axis) const {
const JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
LWARNING(fmt::format("Cannot find JoystickCameraState with name '{}' (deadzone)",
joystickName));
return 0.0f;
}
return joystickCameraState->axisMapping[axis].deadzone;
}
void JoystickCameraStates::bindButtonCommand(int button, std::string command,
void JoystickCameraStates::bindButtonCommand(const std::string& joystickName,
int button, std::string command,
JoystickAction action,
ButtonCommandRemote remote,
std::string documentation)
{
_buttonMapping.insert({
JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
if (_joystickCameraStates.size() < JoystickInputStates::MaxNumJoysticks) {
_joystickCameraStates.push_back(JoystickCameraState());
joystickCameraState = &_joystickCameraStates.back();
joystickCameraState->joystickName = joystickName;
}
else {
LWARNING(fmt::format("Cannot add more joysticks, only {} joysticks are "
"supported", JoystickInputStates::MaxNumJoysticks));
return;
}
}
joystickCameraState->buttonMapping.insert({
button,
{ std::move(command), action, remote, std::move(documentation) }
});
}
void JoystickCameraStates::clearButtonCommand(int button) {
for (auto it = _buttonMapping.begin(); it != _buttonMapping.end();) {
void JoystickCameraStates::clearButtonCommand(const std::string& joystickName,
int button)
{
JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
LWARNING(fmt::format("Cannot find JoystickCameraState with name '{}' "
"(clearButtonCommand)", joystickName));
return;
}
for (auto it = joystickCameraState->buttonMapping.begin();
it != joystickCameraState->buttonMapping.end(); )
{
// If the current iterator is the button that we are looking for, delete it
// (std::multimap::erase will return the iterator to the next element for us)
if (it->first == button) {
it = _buttonMapping.erase(it);
it = joystickCameraState->buttonMapping.erase(it);
}
else {
++it;
@@ -233,14 +327,48 @@ void JoystickCameraStates::clearButtonCommand(int button) {
}
}
std::vector<std::string> JoystickCameraStates::buttonCommand(int button) const {
std::vector<std::string> JoystickCameraStates::buttonCommand(
const std::string& joystickName,
int button) const
{
std::vector<std::string> result;
auto itRange = _buttonMapping.equal_range(button);
const JoystickCameraState* joystickCameraState = getJoystickCameraState(joystickName);
if (!joystickCameraState) {
LWARNING(fmt::format("Cannot find JoystickCameraState with name '{}' "
"(buttonCommand)", joystickName));
return result;
}
auto itRange = joystickCameraState->buttonMapping.equal_range(button);
for (auto it = itRange.first; it != itRange.second; ++it) {
result.push_back(it->second.command);
}
return result;
}
JoystickCameraStates::JoystickCameraState* JoystickCameraStates::getJoystickCameraState(
const std::string& joystickName)
{
for (JoystickCameraState& joystickCameraState : _joystickCameraStates) {
if (joystickCameraState.joystickName == joystickName) {
return &joystickCameraState;
}
}
return nullptr;
}
const JoystickCameraStates::JoystickCameraState* JoystickCameraStates::getJoystickCameraState(
const std::string& joystickName) const
{
for (const JoystickCameraState& joystickCameraState : _joystickCameraStates) {
if (joystickCameraState.joystickName == joystickName) {
return &joystickCameraState;
}
}
return nullptr;
}
} // namespace openspace::interaction

View File

@@ -33,38 +33,68 @@
namespace openspace::interaction {
float JoystickInputStates::axis(int axis) const {
float JoystickInputStates::axis(const std::string& joystickName, int axis) const {
ghoul_precondition(axis >= 0, "axis must be 0 or positive");
float res = std::accumulate(
begin(),
end(),
0.f,
[axis](float value, const JoystickInputState& state) {
if (state.isConnected) {
value += state.axes[axis];
if(joystickName.empty()) {
float res = std::accumulate(
begin(),
end(),
0.f,
[axis](float value, const JoystickInputState& state) {
if (state.isConnected) {
value += state.axes[axis];
}
return value;
}
return value;
}
);
);
// If multiple joysticks are connected, we might get values outside the -1,1 range by
// summing them up
glm::clamp(res, -1.f, 1.f);
return res;
// If multiple joysticks are connected, we might get values outside the -1,1 range by
// summing them up
glm::clamp(res, -1.f, 1.f);
return res;
}
const JoystickInputState* state = nullptr;
for (auto it = begin(); it < end(); ++it) {
if (it->name == joystickName) {
state = &(*it);
}
}
if (!state) {
return 0.0f;
}
return state->axes[axis];
}
bool JoystickInputStates::button(int button, JoystickAction action) const {
bool JoystickInputStates::button(const std::string& joystickName, int button, JoystickAction action) const {
ghoul_precondition(button >= 0, "button must be 0 or positive");
bool res = std::any_of(
begin(),
end(),
[button, action](const JoystickInputState& state) {
return state.isConnected ? (state.buttons[button] == action) : false;
if(joystickName.empty()) {
bool res = std::any_of(
begin(),
end(),
[button, action](const JoystickInputState& state) {
return state.isConnected ? (state.buttons[button] == action) : false;
}
);
return res;
}
const JoystickInputState* state = nullptr;
for (auto it = begin(); it < end(); ++it) {
if (it->name == joystickName) {
state = &(*it);
}
);
return res;
}
if (!state) {
return false;
}
return state->isConnected ? (state->buttons[button] == action) : false;
}
} // namespace openspace::interaction

View File

@@ -498,7 +498,7 @@ void NavigationHandler::loadNavigationState(const std::string& filepath) {
}
}
void NavigationHandler::setJoystickAxisMapping(int axis,
void NavigationHandler::setJoystickAxisMapping(const std::string& joystickName, int axis,
JoystickCameraStates::AxisType mapping,
JoystickCameraStates::AxisInvert shouldInvert,
JoystickCameraStates::AxisNormalize shouldNormalize,
@@ -506,6 +506,7 @@ void NavigationHandler::setJoystickAxisMapping(int axis,
double sensitivity)
{
_orbitalNavigator.joystickStates().setAxisMapping(
joystickName,
axis,
mapping,
shouldInvert,
@@ -530,25 +531,31 @@ void NavigationHandler::setWebsocketAxisMapping(int axis,
JoystickCameraStates::AxisInformation
NavigationHandler::joystickAxisMapping(int axis) const
NavigationHandler::joystickAxisMapping(const std::string& joystickName, int axis) const
{
return _orbitalNavigator.joystickStates().axisMapping(axis);
return _orbitalNavigator.joystickStates().axisMapping(joystickName, axis);
}
void NavigationHandler::setJoystickAxisDeadzone(int axis, float deadzone) {
_orbitalNavigator.joystickStates().setDeadzone(axis, deadzone);
void NavigationHandler::setJoystickAxisDeadzone(const std::string& joystickName, int axis,
float deadzone)
{
_orbitalNavigator.joystickStates().setDeadzone(joystickName, axis, deadzone);
}
float NavigationHandler::joystickAxisDeadzone(int axis) const {
return _orbitalNavigator.joystickStates().deadzone(axis);
float NavigationHandler::joystickAxisDeadzone(const std::string& joystickName,
int axis) const
{
return _orbitalNavigator.joystickStates().deadzone(joystickName, axis);
}
void NavigationHandler::bindJoystickButtonCommand(int button, std::string command,
void NavigationHandler::bindJoystickButtonCommand(const std::string& joystickName,
int button, std::string command,
JoystickAction action,
JoystickCameraStates::ButtonCommandRemote remote,
std::string documentation)
{
_orbitalNavigator.joystickStates().bindButtonCommand(
joystickName,
button,
std::move(command),
action,
@@ -557,12 +564,16 @@ void NavigationHandler::bindJoystickButtonCommand(int button, std::string comman
);
}
void NavigationHandler::clearJoystickButtonCommand(int button) {
_orbitalNavigator.joystickStates().clearButtonCommand(button);
void NavigationHandler::clearJoystickButtonCommand(const std::string& joystickName,
int button)
{
_orbitalNavigator.joystickStates().clearButtonCommand(joystickName, button);
}
std::vector<std::string> NavigationHandler::joystickButtonCommand(int button) const {
return _orbitalNavigator.joystickStates().buttonCommand(button);
std::vector<std::string> NavigationHandler::joystickButtonCommand(
const std::string& joystickName, int button) const
{
return _orbitalNavigator.joystickStates().buttonCommand(joystickName, button);
}
scripting::LuaLibrary NavigationHandler::luaLibrary() {

View File

@@ -151,10 +151,11 @@ int retargetAim(lua_State* L) {
}
int bindJoystickAxis(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 6 }, "lua::bindJoystickAxis");
auto [axis, axisType, shouldInvert, shouldNormalize, isSticky, sensitivity] =
ghoul::lua::checkArgumentsAndThrow(L, { 3, 7 }, "lua::bindJoystickAxis");
auto [joystickName, axis, axisType, shouldInvert, shouldNormalize, isSticky,
sensitivity] =
ghoul::lua::values<
int, std::string, std::optional<bool>, std::optional<bool>,
std::string, int, std::string, std::optional<bool>, std::optional<bool>,
std::optional<bool>, std::optional<double>
>(L);
shouldInvert = shouldInvert.value_or(false);
@@ -163,6 +164,7 @@ int bindJoystickAxis(lua_State* L) {
sensitivity = sensitivity.value_or(0.0);
global::navigationHandler->setJoystickAxisMapping(
joystickName,
axis,
ghoul::from_string<interaction::JoystickCameraStates::AxisType>(axisType),
interaction::JoystickCameraStates::AxisInvert(*shouldInvert),
@@ -174,11 +176,11 @@ int bindJoystickAxis(lua_State* L) {
}
int joystickAxis(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickAxis");
const int axis = ghoul::lua::value<int>(L);
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::joystickAxis");
auto [joystickName, axis] = ghoul::lua::values<std::string, int>(L);
using AI = interaction::JoystickCameraStates::AxisInformation;
AI info = global::navigationHandler->joystickAxisMapping(axis);
AI info = global::navigationHandler->joystickAxisMapping(joystickName, axis);
ghoul::lua::push(
L,
@@ -192,27 +194,32 @@ int joystickAxis(lua_State* L) {
}
int setJoystickAxisDeadzone(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setJoystickAxisDeadzone");
auto [axis, deadzone] = ghoul::lua::values<int, float>(L);
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setJoystickAxisDeadzone");
auto [joystickName, axis, deadzone] = ghoul::lua::values<std::string, int, float>(L);
global::navigationHandler->setJoystickAxisDeadzone(axis, deadzone);
global::navigationHandler->setJoystickAxisDeadzone(joystickName, axis, deadzone);
return 0;
}
int joystickAxisDeadzone(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickAxisDeadzone");
const int axis = ghoul::lua::value<int>(L);
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::joystickAxisDeadzone");
auto [joystickName, axis] = ghoul::lua::values<std::string, int>(L);
const float deadzone = global::navigationHandler->joystickAxisDeadzone(axis);
const float deadzone = global::navigationHandler->joystickAxisDeadzone(joystickName, axis);
ghoul::lua::push(L, deadzone);
return 1;
}
int bindJoystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 3, 5 }, "lua::bindJoystickButton");
auto [button, command, documentation, actionStr, isRemote] =
ghoul::lua::checkArgumentsAndThrow(L, { 4, 6 }, "lua::bindJoystickButton");
auto [joystickName, button, command, documentation, actionStr, isRemote] =
ghoul::lua::values<
int, std::string, std::string, std::optional<std::string>, std::optional<bool>
std::string,
int,
std::string,
std::string,
std::optional<std::string>,
std::optional<bool>
>(L);
actionStr = actionStr.value_or("Press");
isRemote = isRemote.value_or(true);
@@ -221,6 +228,7 @@ int bindJoystickButton(lua_State* L) {
ghoul::from_string<interaction::JoystickAction>(*actionStr);
global::navigationHandler->bindJoystickButtonCommand(
joystickName,
button,
command,
action,
@@ -231,18 +239,19 @@ int bindJoystickButton(lua_State* L) {
}
int clearJoystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::clearJoystickButton");
const int button = ghoul::lua::value<int>(L);
global::navigationHandler->clearJoystickButtonCommand(button);
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::clearJoystickButton");
auto [joystickName, button] = ghoul::lua::values<std::string, int>(L);
global::navigationHandler->clearJoystickButtonCommand(joystickName, button);
return 0;
}
int joystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickButton");
const int button = ghoul::lua::value<int>(L);
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::joystickButton");
auto [joystickName, button] = ghoul::lua::values<std::string, int>(L);
const std::vector<std::string>& cmds =
global::navigationHandler->joystickButtonCommand(button);
global::navigationHandler->joystickButtonCommand(joystickName, button);
std::string cmd = std::accumulate(
cmds.cbegin(),