mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 11:53:28 +02:00
integrated joysticks with userinputmapper, enabling plug-in-and-play controllers and input mapping with js
This commit is contained in:
parent
24fda9a733
commit
b8b61e7c62
7 changed files with 278 additions and 145 deletions
|
@ -113,6 +113,7 @@
|
|||
#include "devices/Faceshift.h"
|
||||
#include "devices/Leapmotion.h"
|
||||
#include "devices/RealSense.h"
|
||||
#include "devices/SDL2Manager.h"
|
||||
#include "devices/MIDIManager.h"
|
||||
#include "devices/OculusManager.h"
|
||||
#include "devices/TV3DManager.h"
|
||||
|
@ -127,7 +128,6 @@
|
|||
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||
#include "scripting/ClipboardScriptingInterface.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/JoystickScriptingInterface.h"
|
||||
#include "scripting/GlobalServicesScriptingInterface.h"
|
||||
#include "scripting/LocationScriptingInterface.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
|
@ -1455,6 +1455,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
|||
|
||||
void Application::focusOutEvent(QFocusEvent* event) {
|
||||
_keyboardMouseDevice.focusOutEvent(event);
|
||||
SDL2Manager::getInstance()->focusOutEvent();
|
||||
|
||||
// synthesize events for keys currently pressed, since we may not get their release events
|
||||
foreach (int key, _keysPressed) {
|
||||
|
@ -2450,7 +2451,7 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
|
||||
SixenseManager::getInstance().update(deltaTime);
|
||||
JoystickScriptingInterface::getInstance().update();
|
||||
SDL2Manager::getInstance()->update();
|
||||
}
|
||||
|
||||
_userInputMapper.update(deltaTime);
|
||||
|
@ -4045,7 +4046,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
|
||||
scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data());
|
||||
|
||||
scriptEngine->registerGlobalObject("Joysticks", &JoystickScriptingInterface::getInstance());
|
||||
qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue);
|
||||
|
||||
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
|
||||
|
|
|
@ -13,8 +13,11 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "Joystick.h"
|
||||
|
||||
const float CONTROLLER_THRESHOLD = .25f;
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
const float MAX_AXIS = 32768.0f;
|
||||
|
@ -22,10 +25,7 @@ const float MAX_AXIS = 32768.0f;
|
|||
Joystick::Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController) :
|
||||
_sdlGameController(sdlGameController),
|
||||
_sdlJoystick(SDL_GameControllerGetJoystick(_sdlGameController)),
|
||||
_instanceId(instanceId),
|
||||
_name(name),
|
||||
_axes(QVector<float>(SDL_JoystickNumAxes(_sdlJoystick))),
|
||||
_buttons(QVector<bool>(SDL_JoystickNumButtons(_sdlJoystick)))
|
||||
_instanceId(instanceId)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -42,24 +42,171 @@ void Joystick::closeJoystick() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void Joystick::update() {
|
||||
for (auto axisState : _axisStateMap) {
|
||||
if (axisState.second < CONTROLLER_THRESHOLD && axisState.second > -CONTROLLER_THRESHOLD) {
|
||||
_axisStateMap[axisState.first] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Joystick::focusOutEvent() {
|
||||
_axisStateMap.clear();
|
||||
_buttonPressedMap.clear();
|
||||
};
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
void Joystick::handleAxisEvent(const SDL_ControllerAxisEvent& event) {
|
||||
if (_axes.size() <= event.axis) {
|
||||
_axes.resize(event.axis + 1);
|
||||
SDL_GameControllerAxis axis = (SDL_GameControllerAxis) event.axis;
|
||||
|
||||
if (axis == SDL_CONTROLLER_AXIS_LEFTX) {
|
||||
_axisStateMap[makeInput(LEFT_AXIS_X_POS).getChannel()] = (event.value > 0) ? event.value / MAX_AXIS : 0.0f;
|
||||
_axisStateMap[makeInput(LEFT_AXIS_X_NEG).getChannel()] = (event.value < 0) ? -event.value / MAX_AXIS : 0.0f;
|
||||
} else if (axis == SDL_CONTROLLER_AXIS_LEFTY) {
|
||||
_axisStateMap[makeInput(LEFT_AXIS_Y_POS).getChannel()] = (event.value > 0) ? event.value / MAX_AXIS : 0.0f;
|
||||
_axisStateMap[makeInput(LEFT_AXIS_Y_NEG).getChannel()] = (event.value < 0) ? -event.value / MAX_AXIS : 0.0f;
|
||||
} else if (axis == SDL_CONTROLLER_AXIS_RIGHTX) {
|
||||
_axisStateMap[makeInput(RIGHT_AXIS_X_POS).getChannel()] = (event.value > 0) ? event.value / MAX_AXIS : 0.0f;
|
||||
_axisStateMap[makeInput(RIGHT_AXIS_X_NEG).getChannel()] = (event.value < 0) ? -event.value / MAX_AXIS : 0.0f;
|
||||
} else if (axis == SDL_CONTROLLER_AXIS_RIGHTY) {
|
||||
_axisStateMap[makeInput(RIGHT_AXIS_Y_POS).getChannel()] = (event.value > 0) ? event.value / MAX_AXIS : 0.0f;
|
||||
_axisStateMap[makeInput(RIGHT_AXIS_Y_NEG).getChannel()] = (event.value < 0) ? -event.value / MAX_AXIS : 0.0f;
|
||||
}
|
||||
|
||||
float oldValue = _axes[event.axis];
|
||||
float newValue = event.value / MAX_AXIS;
|
||||
_axes[event.axis] = newValue;
|
||||
|
||||
emit axisValueChanged(event.axis, newValue, oldValue);
|
||||
|
||||
}
|
||||
|
||||
void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) {
|
||||
bool oldValue = _buttons[event.button];
|
||||
auto input = makeInput((SDL_GameControllerButton) event.button);
|
||||
bool newValue = event.state == SDL_PRESSED;
|
||||
_buttons[event.button] = newValue;
|
||||
emit buttonStateChanged(event.button, newValue, oldValue);
|
||||
if (newValue) {
|
||||
_buttonPressedMap.insert(input.getChannel());
|
||||
} else {
|
||||
_buttonPressedMap.erase(input.getChannel());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Joystick::registerToUserInputMapper(UserInputMapper& mapper) {
|
||||
// Grab the current free device ID
|
||||
_deviceID = mapper.getFreeDeviceID();
|
||||
|
||||
auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy(_name));
|
||||
proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input._channel); };
|
||||
proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input._channel); };
|
||||
proxy->getAvailabeInputs = [this] () -> QVector<UserInputMapper::InputPair> {
|
||||
QVector<UserInputMapper::InputPair> availableInputs;
|
||||
#ifdef HAVE_SDL2
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_A), "Bottom Button"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_B), "Right Button"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_X), "Left Button"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_Y), "Top Button"));
|
||||
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_DPAD_UP), "DPad Up"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_DPAD_DOWN), "DPad Down"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_DPAD_LEFT), "DPad Left"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_DPAD_RIGHT), "DPad Right"));
|
||||
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_LEFTSHOULDER), "L1"));
|
||||
availableInputs.append(UserInputMapper::InputPair(makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), "R1"));
|
||||
#endif
|
||||
return availableInputs;
|
||||
};
|
||||
proxy->resetDeviceBindings = [this, &mapper] () -> bool {
|
||||
mapper.removeAllInputChannelsForDevice(_deviceID);
|
||||
this->assignDefaultInputMapping(mapper);
|
||||
return true;
|
||||
};
|
||||
mapper.registerDevice(_deviceID, proxy);
|
||||
}
|
||||
|
||||
void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) {
|
||||
#ifdef HAVE_SDL2
|
||||
const float JOYSTICK_MOVE_SPEED = 1.0f;
|
||||
const float DPAD_MOVE_SPEED = .5f;
|
||||
const float JOYSTICK_YAW_SPEED = 0.5f;
|
||||
const float JOYSTICK_PITCH_SPEED = 0.25f;
|
||||
|
||||
// Y axes are flipped (up is negative)
|
||||
// Left Joystick: Movement, strafing
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(LEFT_AXIS_Y_NEG), JOYSTICK_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(LEFT_AXIS_Y_POS), JOYSTICK_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(LEFT_AXIS_X_POS), JOYSTICK_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(LEFT_AXIS_X_NEG), JOYSTICK_MOVE_SPEED);
|
||||
|
||||
// Right Joystick: Camera orientation
|
||||
mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(RIGHT_AXIS_X_POS), JOYSTICK_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(RIGHT_AXIS_X_NEG), JOYSTICK_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(RIGHT_AXIS_Y_NEG), JOYSTICK_PITCH_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(RIGHT_AXIS_Y_POS), JOYSTICK_PITCH_SPEED);
|
||||
|
||||
// Dpad movement
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(SDL_CONTROLLER_BUTTON_DPAD_UP), DPAD_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(SDL_CONTROLLER_BUTTON_DPAD_DOWN), DPAD_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(SDL_CONTROLLER_BUTTON_DPAD_RIGHT), DPAD_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(SDL_CONTROLLER_BUTTON_DPAD_LEFT), DPAD_MOVE_SPEED);
|
||||
|
||||
// Button controls
|
||||
mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(SDL_CONTROLLER_BUTTON_Y), DPAD_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(SDL_CONTROLLER_BUTTON_A), DPAD_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(SDL_CONTROLLER_BUTTON_X), JOYSTICK_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(SDL_CONTROLLER_BUTTON_B), JOYSTICK_YAW_SPEED);
|
||||
|
||||
|
||||
// Hold front right shoulder button for precision controls
|
||||
// Left Joystick: Movement, strafing
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(LEFT_AXIS_Y_NEG), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(LEFT_AXIS_Y_POS), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(LEFT_AXIS_X_POS), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(LEFT_AXIS_X_NEG), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_MOVE_SPEED/2.);
|
||||
|
||||
// Right Joystick: Camera orientation
|
||||
mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(RIGHT_AXIS_X_POS), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_YAW_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(RIGHT_AXIS_X_NEG), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_YAW_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(RIGHT_AXIS_Y_NEG), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_PITCH_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(RIGHT_AXIS_Y_POS), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_PITCH_SPEED/2.);
|
||||
|
||||
// Dpad movement
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(SDL_CONTROLLER_BUTTON_DPAD_UP), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(SDL_CONTROLLER_BUTTON_DPAD_DOWN), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(SDL_CONTROLLER_BUTTON_DPAD_RIGHT), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(SDL_CONTROLLER_BUTTON_DPAD_LEFT), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.);
|
||||
|
||||
// Button controls
|
||||
mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(SDL_CONTROLLER_BUTTON_Y), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(SDL_CONTROLLER_BUTTON_A), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(SDL_CONTROLLER_BUTTON_X), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_YAW_SPEED/2.);
|
||||
mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(SDL_CONTROLLER_BUTTON_B), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_YAW_SPEED/2.);
|
||||
#endif
|
||||
}
|
||||
|
||||
float Joystick::getButton(int channel) const {
|
||||
if (!_buttonPressedMap.empty()) {
|
||||
if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) {
|
||||
return 1.0f;
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float Joystick::getAxis(int channel) const {
|
||||
auto axis = _axisStateMap.find(channel);
|
||||
if (axis != _axisStateMap.end()) {
|
||||
return (*axis).second;
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
UserInputMapper::Input Joystick::makeInput(SDL_GameControllerButton button) {
|
||||
return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON);
|
||||
}
|
||||
#endif
|
||||
|
||||
UserInputMapper::Input Joystick::makeInput(Joystick::JoystickAxisChannel axis) {
|
||||
return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#undef main
|
||||
#endif
|
||||
|
||||
#include "ui/UserInputMapper.h"
|
||||
|
||||
class Joystick : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -29,12 +31,38 @@ class Joystick : public QObject {
|
|||
Q_PROPERTY(int instanceId READ getInstanceId)
|
||||
#endif
|
||||
|
||||
Q_PROPERTY(int numAxes READ getNumAxes)
|
||||
Q_PROPERTY(int numButtons READ getNumButtons)
|
||||
public:
|
||||
enum JoystickAxisChannel {
|
||||
LEFT_AXIS_X_POS = 0,
|
||||
LEFT_AXIS_X_NEG,
|
||||
LEFT_AXIS_Y_POS,
|
||||
LEFT_AXIS_Y_NEG,
|
||||
RIGHT_AXIS_X_POS,
|
||||
RIGHT_AXIS_X_NEG,
|
||||
RIGHT_AXIS_Y_POS,
|
||||
RIGHT_AXIS_Y_NEG,
|
||||
};
|
||||
|
||||
Joystick();
|
||||
~Joystick();
|
||||
|
||||
typedef std::unordered_set<int> ButtonPressedMap;
|
||||
typedef std::map<int, float> AxisStateMap;
|
||||
|
||||
float getButton(int channel) const;
|
||||
float getAxis(int channel) const;
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
UserInputMapper::Input makeInput(SDL_GameControllerButton button);
|
||||
#endif
|
||||
UserInputMapper::Input makeInput(Joystick::JoystickAxisChannel axis);
|
||||
|
||||
void registerToUserInputMapper(UserInputMapper& mapper);
|
||||
void assignDefaultInputMapping(UserInputMapper& mapper);
|
||||
|
||||
void update();
|
||||
void focusOutEvent();
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController);
|
||||
#endif
|
||||
|
@ -51,15 +79,8 @@ public:
|
|||
int getInstanceId() const { return _instanceId; }
|
||||
#endif
|
||||
|
||||
const QVector<float>& getAxes() const { return _axes; }
|
||||
const QVector<bool>& getButtons() const { return _buttons; }
|
||||
int getDeviceID() { return _deviceID; }
|
||||
|
||||
int getNumAxes() const { return _axes.size(); }
|
||||
int getNumButtons() const { return _buttons.size(); }
|
||||
|
||||
signals:
|
||||
void axisValueChanged(int axis, float newValue, float oldValue);
|
||||
void buttonStateChanged(int button, float newValue, float oldValue);
|
||||
private:
|
||||
#ifdef HAVE_SDL2
|
||||
SDL_GameController* _sdlGameController;
|
||||
|
@ -68,8 +89,12 @@ private:
|
|||
#endif
|
||||
|
||||
QString _name;
|
||||
QVector<float> _axes;
|
||||
QVector<bool> _buttons;
|
||||
|
||||
protected:
|
||||
int _deviceID = 0;
|
||||
|
||||
ButtonPressedMap _buttonPressedMap;
|
||||
AxisStateMap _axisStateMap;
|
||||
};
|
||||
|
||||
#endif // hifi_JoystickTracker_h
|
||||
#endif // hifi_Joystick_h
|
||||
|
|
|
@ -1,73 +1,66 @@
|
|||
//
|
||||
// JoystickScriptingInterface.cpp
|
||||
// SDL2Manager.cpp
|
||||
// interface/src/devices
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/15/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Created by Sam Gondelman on 6/5/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <QtDebug>
|
||||
#include <QScriptValue>
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
#include <SDL.h>
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
#include <HFActionEvent.h>
|
||||
#include <HFBackEvent.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Application.h"
|
||||
|
||||
#include "JoystickScriptingInterface.h"
|
||||
#include "SDL2Manager.h"
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
SDL_JoystickID getInstanceId(SDL_GameController* controller) {
|
||||
SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) {
|
||||
SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
|
||||
return SDL_JoystickInstanceID(joystick);
|
||||
}
|
||||
#endif
|
||||
|
||||
JoystickScriptingInterface& JoystickScriptingInterface::getInstance() {
|
||||
static JoystickScriptingInterface sharedInstance;
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
JoystickScriptingInterface::JoystickScriptingInterface() :
|
||||
SDL2Manager::SDL2Manager() :
|
||||
#ifdef HAVE_SDL2
|
||||
_openJoysticks(),
|
||||
_openJoysticks(),
|
||||
#endif
|
||||
_isInitialized(false)
|
||||
_isInitialized(false)
|
||||
{
|
||||
#ifdef HAVE_SDL2
|
||||
bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER) == 0);
|
||||
|
||||
if (initSuccess) {
|
||||
int joystickCount = SDL_NumJoysticks();
|
||||
|
||||
|
||||
for (int i = 0; i < joystickCount; i++) {
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(i);
|
||||
|
||||
if (controller) {
|
||||
SDL_JoystickID id = getInstanceId(controller);
|
||||
Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
if (!_openJoysticks.contains(id)) {
|
||||
Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
joystick->registerToUserInputMapper(*Application::getUserInputMapper());
|
||||
joystick->assignDefaultInputMapping(*Application::getUserInputMapper());
|
||||
emit joystickAdded(joystick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_isInitialized = true;
|
||||
} else {
|
||||
qDebug() << "Error initializing SDL";
|
||||
qDebug() << "Error initializing SDL2 Manager";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JoystickScriptingInterface::~JoystickScriptingInterface() {
|
||||
SDL2Manager::~SDL2Manager() {
|
||||
#ifdef HAVE_SDL2
|
||||
qDeleteAll(_openJoysticks);
|
||||
|
||||
|
@ -75,34 +68,25 @@ JoystickScriptingInterface::~JoystickScriptingInterface() {
|
|||
#endif
|
||||
}
|
||||
|
||||
const QObjectList JoystickScriptingInterface::getAllJoysticks() const {
|
||||
QObjectList objectList;
|
||||
#ifdef HAVE_SDL2
|
||||
const QList<Joystick*> joystickList = _openJoysticks.values();
|
||||
for (int i = 0; i < joystickList.length(); i++) {
|
||||
objectList << joystickList[i];
|
||||
}
|
||||
#endif
|
||||
return objectList;
|
||||
SDL2Manager* SDL2Manager::getInstance() {
|
||||
static SDL2Manager sharedInstance;
|
||||
return &sharedInstance;
|
||||
}
|
||||
|
||||
Joystick* JoystickScriptingInterface::joystickWithName(const QString& name) {
|
||||
#ifdef HAVE_SDL2
|
||||
QMap<SDL_JoystickID, Joystick*>::iterator iter = _openJoysticks.begin();
|
||||
while (iter != _openJoysticks.end()) {
|
||||
if (iter.value()->getName() == name) {
|
||||
return iter.value();
|
||||
}
|
||||
iter++;
|
||||
void SDL2Manager::focusOutEvent() {
|
||||
for (auto joystick : _openJoysticks) {
|
||||
joystick->focusOutEvent();
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void JoystickScriptingInterface::update() {
|
||||
void SDL2Manager::update() {
|
||||
#ifdef HAVE_SDL2
|
||||
if (_isInitialized) {
|
||||
PerformanceTimer perfTimer("JoystickScriptingInterface::update");
|
||||
for (auto joystick : _openJoysticks) {
|
||||
joystick->update();
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("SDL2Manager::update");
|
||||
SDL_GameControllerUpdate();
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
|
@ -120,16 +104,16 @@ void JoystickScriptingInterface::update() {
|
|||
if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) {
|
||||
// this will either start or stop a global back event
|
||||
QEvent::Type backType = (event.type == SDL_CONTROLLERBUTTONDOWN)
|
||||
? HFBackEvent::startType()
|
||||
: HFBackEvent::endType();
|
||||
? HFBackEvent::startType()
|
||||
: HFBackEvent::endType();
|
||||
HFBackEvent backEvent(backType);
|
||||
|
||||
qApp->sendEvent(qApp, &backEvent);
|
||||
} else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_A) {
|
||||
// this will either start or stop a global action event
|
||||
QEvent::Type actionType = (event.type == SDL_CONTROLLERBUTTONDOWN)
|
||||
? HFActionEvent::startType()
|
||||
: HFActionEvent::endType();
|
||||
? HFActionEvent::startType()
|
||||
: HFActionEvent::endType();
|
||||
|
||||
// global action events fire in the center of the screen
|
||||
Application* app = Application::getInstance();
|
||||
|
@ -141,14 +125,19 @@ void JoystickScriptingInterface::update() {
|
|||
|
||||
} else if (event.type == SDL_CONTROLLERDEVICEADDED) {
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which);
|
||||
|
||||
|
||||
SDL_JoystickID id = getInstanceId(controller);
|
||||
Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
emit joystickAdded(joystick);
|
||||
if (!_openJoysticks.contains(id)) {
|
||||
Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
joystick->registerToUserInputMapper(*Application::getUserInputMapper());
|
||||
joystick->assignDefaultInputMapping(*Application::getUserInputMapper());
|
||||
emit joystickAdded(joystick);
|
||||
}
|
||||
} else if (event.type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||
Joystick* joystick = _openJoysticks[event.cdevice.which];
|
||||
_openJoysticks.remove(event.cdevice.which);
|
||||
Application::getUserInputMapper()->removeDevice(joystick->getDeviceID());
|
||||
emit joystickRemoved(joystick);
|
||||
}
|
||||
}
|
|
@ -1,77 +1,46 @@
|
|||
//
|
||||
// JoystickScriptingInterface.h
|
||||
// SDL2Manager.h
|
||||
// interface/src/devices
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/15/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Created by Sam Gondelman on 6/5/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_JoystickScriptingInterface_h
|
||||
#define hifi_JoystickScriptingInterface_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#ifndef hifi__SDL2Manager_h
|
||||
#define hifi__SDL2Manager_h
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#include "ui/UserInputMapper.h"
|
||||
|
||||
#include "devices/Joystick.h"
|
||||
|
||||
/// Handles joystick input through SDL.
|
||||
class JoystickScriptingInterface : public QObject {
|
||||
class SDL2Manager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
Q_PROPERTY(int AXIS_INVALID READ axisInvalid)
|
||||
Q_PROPERTY(int AXIS_LEFT_X READ axisLeftX)
|
||||
Q_PROPERTY(int AXIS_LEFT_Y READ axisLeftY)
|
||||
Q_PROPERTY(int AXIS_RIGHT_X READ axisRightX)
|
||||
Q_PROPERTY(int AXIS_RIGHT_Y READ axisRightY)
|
||||
Q_PROPERTY(int AXIS_TRIGGER_LEFT READ axisTriggerLeft)
|
||||
Q_PROPERTY(int AXIS_TRIGGER_RIGHT READ axisTriggerRight)
|
||||
Q_PROPERTY(int AXIS_MAX READ axisMax)
|
||||
|
||||
Q_PROPERTY(int BUTTON_INVALID READ buttonInvalid)
|
||||
Q_PROPERTY(int BUTTON_FACE_BOTTOM READ buttonFaceBottom)
|
||||
Q_PROPERTY(int BUTTON_FACE_RIGHT READ buttonFaceRight)
|
||||
Q_PROPERTY(int BUTTON_FACE_LEFT READ buttonFaceLeft)
|
||||
Q_PROPERTY(int BUTTON_FACE_TOP READ buttonFaceTop)
|
||||
Q_PROPERTY(int BUTTON_BACK READ buttonBack)
|
||||
Q_PROPERTY(int BUTTON_GUIDE READ buttonGuide)
|
||||
Q_PROPERTY(int BUTTON_START READ buttonStart)
|
||||
Q_PROPERTY(int BUTTON_LEFT_STICK READ buttonLeftStick)
|
||||
Q_PROPERTY(int BUTTON_RIGHT_STICK READ buttonRightStick)
|
||||
Q_PROPERTY(int BUTTON_LEFT_SHOULDER READ buttonLeftShoulder)
|
||||
Q_PROPERTY(int BUTTON_RIGHT_SHOULDER READ buttonRightShoulder)
|
||||
Q_PROPERTY(int BUTTON_DPAD_UP READ buttonDpadUp)
|
||||
Q_PROPERTY(int BUTTON_DPAD_DOWN READ buttonDpadDown)
|
||||
Q_PROPERTY(int BUTTON_DPAD_LEFT READ buttonDpadLeft)
|
||||
Q_PROPERTY(int BUTTON_DPAD_RIGHT READ buttonDpadRight)
|
||||
Q_PROPERTY(int BUTTON_MAX READ buttonMax)
|
||||
|
||||
Q_PROPERTY(int BUTTON_PRESSED READ buttonPressed)
|
||||
Q_PROPERTY(int BUTTON_RELEASED READ buttonRelease)
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
static JoystickScriptingInterface& getInstance();
|
||||
|
||||
SDL2Manager();
|
||||
~SDL2Manager();
|
||||
|
||||
void focusOutEvent();
|
||||
|
||||
void update();
|
||||
|
||||
public slots:
|
||||
Joystick* joystickWithName(const QString& name);
|
||||
const QObjectList getAllJoysticks() const;
|
||||
|
||||
|
||||
static SDL2Manager* getInstance();
|
||||
|
||||
signals:
|
||||
void joystickAdded(Joystick* joystick);
|
||||
void joystickRemoved(Joystick* joystick);
|
||||
|
||||
|
||||
private:
|
||||
#ifdef HAVE_SDL2
|
||||
SDL_JoystickID getInstanceId(SDL_GameController* controller);
|
||||
|
||||
int axisInvalid() const { return SDL_CONTROLLER_AXIS_INVALID; }
|
||||
int axisLeftX() const { return SDL_CONTROLLER_AXIS_LEFTX; }
|
||||
int axisLeftY() const { return SDL_CONTROLLER_AXIS_LEFTY; }
|
||||
|
@ -80,7 +49,7 @@ private:
|
|||
int axisTriggerLeft() const { return SDL_CONTROLLER_AXIS_TRIGGERLEFT; }
|
||||
int axisTriggerRight() const { return SDL_CONTROLLER_AXIS_TRIGGERRIGHT; }
|
||||
int axisMax() const { return SDL_CONTROLLER_AXIS_MAX; }
|
||||
|
||||
|
||||
int buttonInvalid() const { return SDL_CONTROLLER_BUTTON_INVALID; }
|
||||
int buttonFaceBottom() const { return SDL_CONTROLLER_BUTTON_A; }
|
||||
int buttonFaceRight() const { return SDL_CONTROLLER_BUTTON_B; }
|
||||
|
@ -98,18 +67,15 @@ private:
|
|||
int buttonDpadLeft() const { return SDL_CONTROLLER_BUTTON_DPAD_LEFT; }
|
||||
int buttonDpadRight() const { return SDL_CONTROLLER_BUTTON_DPAD_RIGHT; }
|
||||
int buttonMax() const { return SDL_CONTROLLER_BUTTON_MAX; }
|
||||
|
||||
|
||||
int buttonPressed() const { return SDL_PRESSED; }
|
||||
int buttonRelease() const { return SDL_RELEASED; }
|
||||
#endif
|
||||
|
||||
JoystickScriptingInterface();
|
||||
~JoystickScriptingInterface();
|
||||
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
QMap<SDL_JoystickID, Joystick*> _openJoysticks;
|
||||
#endif
|
||||
bool _isInitialized;
|
||||
};
|
||||
|
||||
#endif // hifi_JoystickScriptingInterface_h
|
||||
#endif // hifi__SDL2Manager_h
|
|
@ -106,6 +106,11 @@ void UserInputMapper::removeAllInputChannelsForDevice(uint16 device) {
|
|||
}
|
||||
}
|
||||
|
||||
void UserInputMapper::removeDevice(int device) {
|
||||
removeAllInputChannelsForDevice((uint16) device);
|
||||
_registeredDevices.erase(device);
|
||||
}
|
||||
|
||||
int UserInputMapper::getInputChannels(InputChannels& channels) const {
|
||||
for (auto& channel : _actionToInputsMap) {
|
||||
channels.push_back(channel.second);
|
||||
|
|
|
@ -189,6 +189,7 @@ public:
|
|||
bool removeInputChannel(InputChannel channel);
|
||||
void removeAllInputChannels();
|
||||
void removeAllInputChannelsForDevice(uint16 device);
|
||||
void removeDevice(int device);
|
||||
//Grab all the input channels currently in use, return the number
|
||||
int getInputChannels(InputChannels& channels) const;
|
||||
QVector<InputChannel> getAllInputsForDevice(uint16 device);
|
||||
|
|
Loading…
Reference in a new issue