From 900daf48eb2a6740b7635fc8ee271df6a8fc7be5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Sep 2014 14:48:44 -0700 Subject: [PATCH 1/7] initial working connection of an xbox gamepad --- examples/xbox.js | 24 +++++++++ interface/CMakeLists.txt | 10 +++- interface/src/devices/JoystickManager.cpp | 33 ++++++------ interface/src/devices/JoystickManager.h | 16 ++---- interface/src/devices/PrioVR.cpp | 2 +- .../ControllerScriptingInterface.cpp | 11 ++++ .../scripting/ControllerScriptingInterface.h | 1 + .../src/JoystickInputController.cpp | 52 +++++++++++++++++++ .../src/JoystickInputController.h | 50 ++++++++++++++++++ libraries/script-engine/src/ScriptEngine.cpp | 16 ++++-- 10 files changed, 183 insertions(+), 32 deletions(-) create mode 100644 examples/xbox.js create mode 100644 libraries/script-engine/src/JoystickInputController.cpp create mode 100644 libraries/script-engine/src/JoystickInputController.h diff --git a/examples/xbox.js b/examples/xbox.js new file mode 100644 index 0000000000..03378995bf --- /dev/null +++ b/examples/xbox.js @@ -0,0 +1,24 @@ +// +// xbox.js +// examples +// +// Created by Stephen Birarda on September 23, 2014 +// +// Copyright 2014 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 +// + +gamepad = Controller.joystick(); +print("THE GAMEPAD NAME is " + gamepad.name); +print("THE GAMEPAD HAS " + gamepad.numAxes + " AXES") + +function printValues() { + controllerAxes = gamepad.axes; + for (i = 0; i < controllerAxes.size; i++) { + // print("The value for axis " + i + " is " + controllerAxes[i]); + } +} + +Script.update.connect(printValues); \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 5653286104..a2a832afe0 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceplus" "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp") +set(OPTIONAL_EXTERNALS "Faceplus" "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp" "SDL") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) @@ -120,6 +120,10 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) add_definitions(-DHAVE_${${EXTERNAL}_UPPERCASE}) # include the library directories (ignoring warnings) + if (NOT ${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS) + set(${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIR}) + endif () + include_directories(SYSTEM ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS}) # perform the system include hack for OS X to ignore warnings @@ -129,6 +133,10 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) endforeach() endif () + if (NOT ${${EXTERNAL}_UPPERCASE}_LIBRARIES) + set(${${EXTERNAL}_UPPERCASE}_LIBRARIES ${${${EXTERNAL}_UPPERCASE}_LIBRARY}) + endif () + target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES}) endif () diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp index 8169c6d06e..afcc2823ac 100644 --- a/interface/src/devices/JoystickManager.cpp +++ b/interface/src/devices/JoystickManager.cpp @@ -25,12 +25,13 @@ JoystickManager::JoystickManager() { SDL_Init(SDL_INIT_JOYSTICK); int joystickCount = SDL_NumJoysticks(); for (int i = 0; i < joystickCount; i++) { - SDL_Joystick* joystick = SDL_JoystickOpen(i); - if (joystick) { - JoystickState state = { SDL_JoystickName(i), QVector(SDL_JoystickNumAxes(joystick)), - QVector(SDL_JoystickNumButtons(joystick)) }; - _joystickStates.append(state); - _joysticks.append(joystick); + SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i); + if (sdlJoystick) { + _sdlJoysticks.append(sdlJoystick); + + JoystickInputController controller(SDL_JoystickName(i), + SDL_JoystickNumAxes(sdlJoystick), SDL_JoystickNumButtons(sdlJoystick)); + _joysticks.append(controller); } } #endif @@ -38,8 +39,8 @@ JoystickManager::JoystickManager() { JoystickManager::~JoystickManager() { #ifdef HAVE_SDL - foreach (SDL_Joystick* joystick, _joysticks) { - SDL_JoystickClose(joystick); + foreach (SDL_Joystick* sdlJoystick, _sdlJoysticks) { + SDL_JoystickClose(sdlJoystick); } SDL_Quit(); #endif @@ -50,16 +51,16 @@ void JoystickManager::update() { PerformanceTimer perfTimer("joystick"); SDL_JoystickUpdate(); - for (int i = 0; i < _joystickStates.size(); i++) { - SDL_Joystick* joystick = _joysticks.at(i); - JoystickState& state = _joystickStates[i]; - for (int j = 0; j < state.axes.size(); j++) { - float value = glm::round(SDL_JoystickGetAxis(joystick, j) + 0.5f) / numeric_limits::max(); + for (int i = 0; i < _joysticks.size(); i++) { + SDL_Joystick* sdlJoystick = _sdlJoysticks.at(i); + JoystickInputController& joystick = _joysticks[i]; + for (int j = 0; j < joystick.getNumAxes(); j++) { + float value = glm::round(SDL_JoystickGetAxis(sdlJoystick, j) + 0.5f) / numeric_limits::max(); const float DEAD_ZONE = 0.1f; - state.axes[j] = glm::abs(value) < DEAD_ZONE ? 0.0f : value; + joystick.updateAxis(j, glm::abs(value) < DEAD_ZONE ? 0.0f : value); } - for (int j = 0; j < state.buttons.size(); j++) { - state.buttons[j] = SDL_JoystickGetButton(joystick, j); + for (int j = 0; j < joystick.getNumButtons(); j++) { + joystick.updateButton(j, SDL_JoystickGetButton(sdlJoystick, j)); } } #endif diff --git a/interface/src/devices/JoystickManager.h b/interface/src/devices/JoystickManager.h index 53a255e129..31c2dc934b 100644 --- a/interface/src/devices/JoystickManager.h +++ b/interface/src/devices/JoystickManager.h @@ -20,6 +20,8 @@ #undef main #endif +#include "JoystickInputController.h" + class JoystickState; /// Handles joystick input through SDL. @@ -27,27 +29,19 @@ class JoystickManager : public QObject { Q_OBJECT public: - JoystickManager(); virtual ~JoystickManager(); - const QVector& getJoystickStates() const { return _joystickStates; } + QVector& getJoysticks() { return _joysticks; } void update(); private: - QVector _joystickStates; + QVector _joysticks; #ifdef HAVE_SDL - QVector _joysticks; + QVector _sdlJoysticks; #endif }; -class JoystickState { -public: - QString name; - QVector axes; - QVector buttons; -}; - #endif // hifi_JoystickManager_h diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index fad80fda6f..30c5d74ce1 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -61,7 +61,7 @@ static void setPalm(float deltaTime, int index) { palm->setActive(true); // Read controller buttons and joystick into the hand - if (!Application::getInstance()->getJoystickManager()->getJoystickStates().isEmpty()) { + if (!Application::getInstance()->getJoystickManager()->getJoysticks().isEmpty()) { const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0); if (state.axes.size() >= 4 && state.buttons.size() >= 4) { if (index == LEFT_HAND_INDEX) { diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index f2e65a6e28..e8047b1ceb 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -297,6 +297,17 @@ AbstractInputController* ControllerScriptingInterface::createInputController(con } } +JoystickInputController* ControllerScriptingInterface::joystick() const { + // stub to just return the first joystick - assume we only have one connected + QVector& activeJoysticks = Application::getInstance()->getJoystickManager()->getJoysticks(); + + if (activeJoysticks.size() > 0) { + return &activeJoysticks[0]; + } else { + return NULL; + } +} + void ControllerScriptingInterface::releaseInputController(AbstractInputController* input) { _inputControllers.erase(input->getKey()); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 62ef2e9b24..ada79e95cd 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -113,6 +113,7 @@ public slots: /// Factory to create an InputController virtual AbstractInputController* createInputController(const QString& deviceName, const QString& tracker); + JoystickInputController* joystick() const; virtual void releaseInputController(AbstractInputController* input); diff --git a/libraries/script-engine/src/JoystickInputController.cpp b/libraries/script-engine/src/JoystickInputController.cpp new file mode 100644 index 0000000000..fedb3a7643 --- /dev/null +++ b/libraries/script-engine/src/JoystickInputController.cpp @@ -0,0 +1,52 @@ +// +// JoystickInputController.cpp +// interface/src/devices +// +// Created by Stephen Birarda on 2014-09-23. +// Copyright 2014 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 + +#include "JoystickInputController.h" + +JoystickInputController::JoystickInputController() : + _name(), + _axes(0), + _buttons(0) +{ + +} + +JoystickInputController::JoystickInputController(const QString& name, int numAxes, int numButtons) : + _name(name), + _axes(numAxes), + _buttons(numButtons) +{ + +} + +JoystickInputController::JoystickInputController(const JoystickInputController& otherJoystickController) : + _name(otherJoystickController._name), + _axes(otherJoystickController._axes), + _buttons(otherJoystickController._buttons) +{ + +} + +JoystickInputController& JoystickInputController::operator=(const JoystickInputController& otherJoystickController) { + JoystickInputController temp(otherJoystickController); + swap(temp); + return *this; +} + +void JoystickInputController::swap(JoystickInputController& otherJoystickController) { + using std::swap; + + swap(_name, otherJoystickController._name); + swap(_axes, otherJoystickController._axes); + swap(_buttons, otherJoystickController._buttons); +} diff --git a/libraries/script-engine/src/JoystickInputController.h b/libraries/script-engine/src/JoystickInputController.h new file mode 100644 index 0000000000..27166c47fd --- /dev/null +++ b/libraries/script-engine/src/JoystickInputController.h @@ -0,0 +1,50 @@ +// +// JoystickInputController.h +// interface/src/devices +// +// Created by Stephen Birarda on 2014-09-23. +// Copyright 2014 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_JoystickInputController_h +#define hifi_JoystickInputController_h + +#include +#include + +class JoystickInputController : public QObject { + Q_OBJECT + + Q_PROPERTY(QString name READ getName) + + Q_PROPERTY(int numAxes READ getNumAxes) + Q_PROPERTY(QVector axes READ getAxes) +public: + JoystickInputController(); + JoystickInputController(const QString& name, int numAxes, int numButtons); + JoystickInputController(const JoystickInputController& otherJoystickController); + JoystickInputController& operator=(const JoystickInputController& otherJoystickController); + + const QString& getName() const { return _name; } + + void updateAxis(int index, float value) { _axes[index] = value; } + void updateButton(int index, bool isActive) { _buttons[index] = isActive; } + + const QVector& getAxes() const { return _axes; } + const QVector& getButtons() const { return _buttons; } + + int getNumAxes() const { return _axes.size(); } + int getNumButtons() const { return _buttons.size(); } + +private: + void swap(JoystickInputController& otherJoystickController); + + QString _name; + QVector _axes; + QVector _buttons; +}; + +#endif // hifi_JoystickTracker_h \ No newline at end of file diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cfea0d6b86..0ab5f37f29 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -35,6 +35,7 @@ #include "AnimationObject.h" #include "ArrayBufferViewClass.h" #include "DataViewClass.h" +#include "JoystickInputController.h" #include "MenuItemProperties.h" #include "MIDIEvent.h" #include "LocalVoxels.h" @@ -72,14 +73,22 @@ void injectorFromScriptValue(const QScriptValue &object, AudioInjector* &out) { out = qobject_cast(object.toQObject()); } -QScriptValue injectorToScriptValueInputController(QScriptEngine *engine, AbstractInputController* const &in) { +QScriptValue inputControllerToScriptValue(QScriptEngine *engine, AbstractInputController* const &in) { return engine->newQObject(in); } -void injectorFromScriptValueInputController(const QScriptValue &object, AbstractInputController* &out) { +void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputController* &out) { out = qobject_cast(object.toQObject()); } +QScriptValue joystickToScriptValue(QScriptEngine *engine, JoystickInputController* const &in) { + return engine->newQObject(in); +} + +void joystickFromScriptValue(const QScriptValue &object, JoystickInputController* &out) { + out = qobject_cast(object.toQObject()); +} + ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, AbstractControllerScriptingInterface* controllerScriptingInterface) : @@ -277,7 +286,8 @@ void ScriptEngine::init() { globalObject().setProperty("LocalVoxels", localVoxelsValue); qScriptRegisterMetaType(this, injectorToScriptValue, injectorFromScriptValue); - qScriptRegisterMetaType( this, injectorToScriptValueInputController, injectorFromScriptValueInputController); + qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); + qScriptRegisterMetaType(this, joystickToScriptValue, joystickFromScriptValue); qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); From 00b0806c4d7dfd0716ae0cd91df2dc6aca7b2119 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Sep 2014 17:09:46 -0700 Subject: [PATCH 2/7] move JoystickManager to JoystickScriptingInterface, add Joystick class for SDL Joystick --- examples/xbox.js | 15 +--- interface/src/Application.cpp | 5 +- interface/src/Application.h | 3 - interface/src/devices/Joystick.cpp | 60 ++++++++++++++ .../src/devices/Joystick.h | 40 +++++---- interface/src/devices/JoystickManager.cpp | 67 --------------- interface/src/devices/JoystickManager.h | 47 ----------- .../ControllerScriptingInterface.cpp | 11 --- .../scripting/ControllerScriptingInterface.h | 1 - .../scripting/JoystickScriptingInterface.cpp | 82 +++++++++++++++++++ .../scripting/JoystickScriptingInterface.h | 43 ++++++++++ .../src/JoystickInputController.cpp | 52 ------------ libraries/script-engine/src/ScriptEngine.cpp | 10 --- 13 files changed, 217 insertions(+), 219 deletions(-) create mode 100644 interface/src/devices/Joystick.cpp rename libraries/script-engine/src/JoystickInputController.h => interface/src/devices/Joystick.h (50%) delete mode 100644 interface/src/devices/JoystickManager.cpp delete mode 100644 interface/src/devices/JoystickManager.h create mode 100644 interface/src/scripting/JoystickScriptingInterface.cpp create mode 100644 interface/src/scripting/JoystickScriptingInterface.h delete mode 100644 libraries/script-engine/src/JoystickInputController.cpp diff --git a/examples/xbox.js b/examples/xbox.js index 03378995bf..9190ee23ac 100644 --- a/examples/xbox.js +++ b/examples/xbox.js @@ -10,15 +10,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -gamepad = Controller.joystick(); -print("THE GAMEPAD NAME is " + gamepad.name); -print("THE GAMEPAD HAS " + gamepad.numAxes + " AXES") +joysticks = Joysticks.availableJoystickNames; -function printValues() { - controllerAxes = gamepad.axes; - for (i = 0; i < controllerAxes.size; i++) { - // print("The value for axis " + i + " is " + controllerAxes[i]); - } -} - -Script.update.connect(printValues); \ No newline at end of file +for (i = 0; i < joysticks.length; i++) { + print("Joystick " + i + " is " + joysticks[i]); +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 105fb6a973..c49a1e234a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -82,6 +82,7 @@ #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" +#include "scripting/JoystickScriptingInterface.h" #include "scripting/GlobalServicesScriptingInterface.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" @@ -2155,7 +2156,7 @@ void Application::update(float deltaTime) { updateFaceshift(); updateVisage(); _sixenseManager.update(deltaTime); - _joystickManager.update(); + JoystickScriptingInterface::getInstance().update(); _prioVR.update(deltaTime); } @@ -3847,6 +3848,8 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AvatarManager", &_avatarManager); + + scriptEngine->registerGlobalObject("Joysticks", &JoystickScriptingInterface::getInstance()); #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); diff --git a/interface/src/Application.h b/interface/src/Application.h index d17bacd413..7c644b61ea 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -59,7 +59,6 @@ #include "avatar/MyAvatar.h" #include "devices/Faceplus.h" #include "devices/Faceshift.h" -#include "devices/JoystickManager.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" #include "devices/Visage.h" @@ -221,7 +220,6 @@ public: FaceTracker* getActiveFaceTracker(); SixenseManager* getSixenseManager() { return &_sixenseManager; } PrioVR* getPrioVR() { return &_prioVR; } - JoystickManager* getJoystickManager() { return &_joystickManager; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QUndoStack* getUndoStack() { return &_undoStack; } QSystemTrayIcon* getTrayIcon() { return _trayIcon; } @@ -511,7 +509,6 @@ private: SixenseManager _sixenseManager; PrioVR _prioVR; - JoystickManager _joystickManager; Camera _myCamera; // My view onto the world Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode diff --git a/interface/src/devices/Joystick.cpp b/interface/src/devices/Joystick.cpp new file mode 100644 index 0000000000..d220a827f1 --- /dev/null +++ b/interface/src/devices/Joystick.cpp @@ -0,0 +1,60 @@ +// +// Joystick.cpp +// interface/src/devices +// +// Created by Stephen Birarda on 2014-09-23. +// Copyright 2014 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 + +#include + +#include "Joystick.h" + +#ifdef HAVE_SDL + +Joystick::Joystick(const QString& name, SDL_Joystick* sdlJoystick) : + _name(name), + _axes(QVector(SDL_JoystickNumAxes(sdlJoystick))), + _buttons(QVector(SDL_JoystickNumButtons(sdlJoystick))), + _sdlJoystick(sdlJoystick) +{ + +} + +#endif + +Joystick::~Joystick() { +#ifdef HAVE_SDL + SDL_JoystickClose(_sdlJoystick); +#endif +} + +void Joystick::update() { +#ifdef HAVE_SDL + // update our current values, emit a signal when there is a change + for (int j = 0; j < getNumAxes(); j++) { + float value = glm::round(SDL_JoystickGetAxis(_sdlJoystick, j) + 0.5f) / std::numeric_limits::max(); + const float DEAD_ZONE = 0.1f; + float cleanValue = glm::abs(value) < DEAD_ZONE ? 0.0f : value; + + if (_axes[j] != cleanValue) { + float oldValue = _axes[j]; + _axes[j] = cleanValue; + emit axisValueChanged(j, cleanValue, oldValue); + } + } + for (int j = 0; j < getNumButtons(); j++) { + bool newValue = SDL_JoystickGetButton(_sdlJoystick, j); + if (_buttons[j] != newValue) { + bool oldValue = _buttons[j]; + _buttons[j] = newValue; + emit buttonStateChanged(j, newValue, oldValue); + } + } +#endif +} \ No newline at end of file diff --git a/libraries/script-engine/src/JoystickInputController.h b/interface/src/devices/Joystick.h similarity index 50% rename from libraries/script-engine/src/JoystickInputController.h rename to interface/src/devices/Joystick.h index 27166c47fd..c1e9acaff0 100644 --- a/libraries/script-engine/src/JoystickInputController.h +++ b/interface/src/devices/Joystick.h @@ -1,5 +1,5 @@ // -// JoystickInputController.h +// Joystick.h // interface/src/devices // // Created by Stephen Birarda on 2014-09-23. @@ -9,13 +9,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_JoystickInputController_h -#define hifi_JoystickInputController_h +#ifndef hifi_Joystick_h +#define hifi_Joystick_h #include #include -class JoystickInputController : public QObject { +#ifdef HAVE_SDL +#include +#undef main +#endif + +class Joystick : public QObject { Q_OBJECT Q_PROPERTY(QString name READ getName) @@ -23,28 +28,31 @@ class JoystickInputController : public QObject { Q_PROPERTY(int numAxes READ getNumAxes) Q_PROPERTY(QVector axes READ getAxes) public: - JoystickInputController(); - JoystickInputController(const QString& name, int numAxes, int numButtons); - JoystickInputController(const JoystickInputController& otherJoystickController); - JoystickInputController& operator=(const JoystickInputController& otherJoystickController); + Joystick(); + ~Joystick(); + +#ifdef HAVE_SDL + Joystick(const QString& name, SDL_Joystick* sdlJoystick); +#endif + + void update(); const QString& getName() const { return _name; } - void updateAxis(int index, float value) { _axes[index] = value; } - void updateButton(int index, bool isActive) { _buttons[index] = isActive; } - - const QVector& getAxes() const { return _axes; } - const QVector& getButtons() const { return _buttons; } - 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: - void swap(JoystickInputController& otherJoystickController); - QString _name; QVector _axes; QVector _buttons; + +#ifdef HAVE_SDL + SDL_Joystick* _sdlJoystick; +#endif }; #endif // hifi_JoystickTracker_h \ No newline at end of file diff --git a/interface/src/devices/JoystickManager.cpp b/interface/src/devices/JoystickManager.cpp deleted file mode 100644 index afcc2823ac..0000000000 --- a/interface/src/devices/JoystickManager.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// JoystickManager.cpp -// interface/src/devices -// -// Created by Andrzej Kapolka on 5/15/14. -// Copyright 2014 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 - -#include -#include - -#include - -#include "JoystickManager.h" - -using namespace std; - -JoystickManager::JoystickManager() { -#ifdef HAVE_SDL - SDL_Init(SDL_INIT_JOYSTICK); - int joystickCount = SDL_NumJoysticks(); - for (int i = 0; i < joystickCount; i++) { - SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i); - if (sdlJoystick) { - _sdlJoysticks.append(sdlJoystick); - - JoystickInputController controller(SDL_JoystickName(i), - SDL_JoystickNumAxes(sdlJoystick), SDL_JoystickNumButtons(sdlJoystick)); - _joysticks.append(controller); - } - } -#endif -} - -JoystickManager::~JoystickManager() { -#ifdef HAVE_SDL - foreach (SDL_Joystick* sdlJoystick, _sdlJoysticks) { - SDL_JoystickClose(sdlJoystick); - } - SDL_Quit(); -#endif -} - -void JoystickManager::update() { -#ifdef HAVE_SDL - PerformanceTimer perfTimer("joystick"); - SDL_JoystickUpdate(); - - for (int i = 0; i < _joysticks.size(); i++) { - SDL_Joystick* sdlJoystick = _sdlJoysticks.at(i); - JoystickInputController& joystick = _joysticks[i]; - for (int j = 0; j < joystick.getNumAxes(); j++) { - float value = glm::round(SDL_JoystickGetAxis(sdlJoystick, j) + 0.5f) / numeric_limits::max(); - const float DEAD_ZONE = 0.1f; - joystick.updateAxis(j, glm::abs(value) < DEAD_ZONE ? 0.0f : value); - } - for (int j = 0; j < joystick.getNumButtons(); j++) { - joystick.updateButton(j, SDL_JoystickGetButton(sdlJoystick, j)); - } - } -#endif -} diff --git a/interface/src/devices/JoystickManager.h b/interface/src/devices/JoystickManager.h deleted file mode 100644 index 31c2dc934b..0000000000 --- a/interface/src/devices/JoystickManager.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// JoystickManager.h -// interface/src/devices -// -// Created by Andrzej Kapolka on 5/15/14. -// Copyright 2014 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_JoystickManager_h -#define hifi_JoystickManager_h - -#include -#include - -#ifdef HAVE_SDL -#include -#undef main -#endif - -#include "JoystickInputController.h" - -class JoystickState; - -/// Handles joystick input through SDL. -class JoystickManager : public QObject { - Q_OBJECT - -public: - JoystickManager(); - virtual ~JoystickManager(); - - QVector& getJoysticks() { return _joysticks; } - - void update(); - -private: - QVector _joysticks; - -#ifdef HAVE_SDL - QVector _sdlJoysticks; -#endif -}; - -#endif // hifi_JoystickManager_h diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index e8047b1ceb..f2e65a6e28 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -297,17 +297,6 @@ AbstractInputController* ControllerScriptingInterface::createInputController(con } } -JoystickInputController* ControllerScriptingInterface::joystick() const { - // stub to just return the first joystick - assume we only have one connected - QVector& activeJoysticks = Application::getInstance()->getJoystickManager()->getJoysticks(); - - if (activeJoysticks.size() > 0) { - return &activeJoysticks[0]; - } else { - return NULL; - } -} - void ControllerScriptingInterface::releaseInputController(AbstractInputController* input) { _inputControllers.erase(input->getKey()); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index ada79e95cd..62ef2e9b24 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -113,7 +113,6 @@ public slots: /// Factory to create an InputController virtual AbstractInputController* createInputController(const QString& deviceName, const QString& tracker); - JoystickInputController* joystick() const; virtual void releaseInputController(AbstractInputController* input); diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp new file mode 100644 index 0000000000..cf370cf0e9 --- /dev/null +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -0,0 +1,82 @@ +// +// JoystickManager.cpp +// interface/src/devices +// +// Created by Andrzej Kapolka on 5/15/14. +// Copyright 2014 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 + +#ifdef HAVE_SDL +#include +#undef main +#endif + +#include + +#include "JoystickScriptingInterface.h" + +JoystickScriptingInterface& JoystickScriptingInterface::getInstance() { + static JoystickScriptingInterface sharedInstance; + return sharedInstance; +} + +JoystickScriptingInterface::JoystickScriptingInterface() : + _openJoysticks(), + _availableDeviceNames() +{ +#ifdef HAVE_SDL + SDL_Init(SDL_INIT_JOYSTICK); + + int joystickCount = SDL_NumJoysticks(); + + for (int i = 0; i < joystickCount; i++) { + _availableDeviceNames << SDL_JoystickName(i); + } +#endif +} + +JoystickScriptingInterface::~JoystickScriptingInterface() { + qDeleteAll(_openJoysticks); + +#ifdef HAVE_SDL + SDL_Quit(); +#endif +} + +void JoystickScriptingInterface::update() { +#ifdef HAVE_SDL + PerformanceTimer perfTimer("JoystickScriptingInterface::update"); + SDL_JoystickUpdate(); + + foreach(Joystick* joystick, _openJoysticks) { + joystick->update(); + } + +#endif +} + +Joystick* JoystickScriptingInterface::joystickWithName(const QString& name) { + Joystick* matchingJoystick = _openJoysticks.value(name); + if (!matchingJoystick) { + // we haven't opened a joystick with this name yet - enumerate our SDL devices and see if it exists + int joystickCount = SDL_NumJoysticks(); + + for (int i = 0; i < joystickCount; i++) { + if (SDL_JoystickName(i) == name) { + matchingJoystick = _openJoysticks.insert(name, new Joystick(name, SDL_JoystickOpen(i))).value(); + break; + } + } + + qDebug() << "No matching joystick found with name" << name << "- returning NULL pointer."; + } + + return matchingJoystick; +} + + diff --git a/interface/src/scripting/JoystickScriptingInterface.h b/interface/src/scripting/JoystickScriptingInterface.h new file mode 100644 index 0000000000..98e38f5698 --- /dev/null +++ b/interface/src/scripting/JoystickScriptingInterface.h @@ -0,0 +1,43 @@ +// +// JoystickScriptingInterface.h +// interface/src/devices +// +// Created by Andrzej Kapolka on 5/15/14. +// Copyright 2014 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 +#include + +#include "devices/Joystick.h" + +/// Handles joystick input through SDL. +class JoystickScriptingInterface : public QObject { + Q_OBJECT + + Q_PROPERTY(QStringList availableJoystickNames READ getAvailableJoystickNames) +public: + static JoystickScriptingInterface& getInstance(); + + const QStringList& getAvailableJoystickNames() const { return _availableDeviceNames; } + + void update(); + +public slots: + Joystick* joystickWithName(const QString& name); + +private: + JoystickScriptingInterface(); + ~JoystickScriptingInterface(); + + QMap _openJoysticks; + QStringList _availableDeviceNames; +}; + +#endif // hifi_JoystickScriptingInterface_h diff --git a/libraries/script-engine/src/JoystickInputController.cpp b/libraries/script-engine/src/JoystickInputController.cpp deleted file mode 100644 index fedb3a7643..0000000000 --- a/libraries/script-engine/src/JoystickInputController.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// JoystickInputController.cpp -// interface/src/devices -// -// Created by Stephen Birarda on 2014-09-23. -// Copyright 2014 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 - -#include "JoystickInputController.h" - -JoystickInputController::JoystickInputController() : - _name(), - _axes(0), - _buttons(0) -{ - -} - -JoystickInputController::JoystickInputController(const QString& name, int numAxes, int numButtons) : - _name(name), - _axes(numAxes), - _buttons(numButtons) -{ - -} - -JoystickInputController::JoystickInputController(const JoystickInputController& otherJoystickController) : - _name(otherJoystickController._name), - _axes(otherJoystickController._axes), - _buttons(otherJoystickController._buttons) -{ - -} - -JoystickInputController& JoystickInputController::operator=(const JoystickInputController& otherJoystickController) { - JoystickInputController temp(otherJoystickController); - swap(temp); - return *this; -} - -void JoystickInputController::swap(JoystickInputController& otherJoystickController) { - using std::swap; - - swap(_name, otherJoystickController._name); - swap(_axes, otherJoystickController._axes); - swap(_buttons, otherJoystickController._buttons); -} diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0ab5f37f29..545e4709f9 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -35,7 +35,6 @@ #include "AnimationObject.h" #include "ArrayBufferViewClass.h" #include "DataViewClass.h" -#include "JoystickInputController.h" #include "MenuItemProperties.h" #include "MIDIEvent.h" #include "LocalVoxels.h" @@ -81,14 +80,6 @@ void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputCon out = qobject_cast(object.toQObject()); } -QScriptValue joystickToScriptValue(QScriptEngine *engine, JoystickInputController* const &in) { - return engine->newQObject(in); -} - -void joystickFromScriptValue(const QScriptValue &object, JoystickInputController* &out) { - out = qobject_cast(object.toQObject()); -} - ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, AbstractControllerScriptingInterface* controllerScriptingInterface) : @@ -287,7 +278,6 @@ void ScriptEngine::init() { qScriptRegisterMetaType(this, injectorToScriptValue, injectorFromScriptValue); qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); - qScriptRegisterMetaType(this, joystickToScriptValue, joystickFromScriptValue); qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); From d50c81e4a1f952cbda71fec369537014734a4332 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Sep 2014 17:10:25 -0700 Subject: [PATCH 3/7] add a property for number of buttons in Joystick --- interface/src/devices/Joystick.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/Joystick.h b/interface/src/devices/Joystick.h index c1e9acaff0..63386db5c5 100644 --- a/interface/src/devices/Joystick.h +++ b/interface/src/devices/Joystick.h @@ -26,7 +26,7 @@ class Joystick : public QObject { Q_PROPERTY(QString name READ getName) Q_PROPERTY(int numAxes READ getNumAxes) - Q_PROPERTY(QVector axes READ getAxes) + Q_PROPERTY(int numButtons READ getNumButtons) public: Joystick(); ~Joystick(); From 13d3eb02e30b47b39c461f3e1f2e00295db0122e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Sep 2014 17:19:57 -0700 Subject: [PATCH 4/7] report the 360 axis values in xbox.js --- examples/xbox.js | 10 ++++++---- interface/src/Application.cpp | 9 +++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/examples/xbox.js b/examples/xbox.js index 9190ee23ac..603e0dbf56 100644 --- a/examples/xbox.js +++ b/examples/xbox.js @@ -10,8 +10,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -joysticks = Joysticks.availableJoystickNames; +gamepad = Joysticks.joystickWithName("Wireless 360 Controller"); -for (i = 0; i < joysticks.length; i++) { - print("Joystick " + i + " is " + joysticks[i]); -} \ No newline at end of file +function reportAxisValue(axis, newValue, oldValue) { + print("The value for axis " + axis + " has changed to " + newValue + ". It was " + oldValue); +} + +gamepad.axisValueChanged.connect(reportAxisValue); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c49a1e234a..25f2bd6817 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3766,6 +3766,14 @@ void Application::saveScripts() { _settings->endArray(); } +QScriptValue joystickToScriptValue(QScriptEngine *engine, Joystick* const &in) { + return engine->newQObject(in); +} + +void joystickFromScriptValue(const QScriptValue &object, Joystick* &out) { + out = qobject_cast(object.toQObject()); +} + ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow) { QUrl scriptUrl(scriptFilename); @@ -3850,6 +3858,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->registerGlobalObject("AvatarManager", &_avatarManager); scriptEngine->registerGlobalObject("Joysticks", &JoystickScriptingInterface::getInstance()); + qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue); #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); From 9348888ae5a2498b5adcced641a73ef99f1cc7e8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Sep 2014 17:42:48 -0700 Subject: [PATCH 5/7] map PrioVR to new JoystickScriptingInterface --- interface/src/devices/Joystick.h | 3 +++ interface/src/devices/PrioVR.cpp | 23 ++++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/interface/src/devices/Joystick.h b/interface/src/devices/Joystick.h index 63386db5c5..228e993204 100644 --- a/interface/src/devices/Joystick.h +++ b/interface/src/devices/Joystick.h @@ -39,6 +39,9 @@ public: const QString& getName() const { return _name; } + const QVector& getAxes() const { return _axes; } + const QVector& getButtons() const { return _buttons; } + int getNumAxes() const { return _axes.size(); } int getNumButtons() const { return _buttons.size(); } diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index 30c5d74ce1..e810f9e370 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -17,6 +17,7 @@ #include "Application.h" #include "PrioVR.h" +#include "scripting/JoystickScriptingInterface.h" #include "ui/TextRenderer.h" #ifdef HAVE_PRIOVR @@ -61,18 +62,22 @@ static void setPalm(float deltaTime, int index) { palm->setActive(true); // Read controller buttons and joystick into the hand - if (!Application::getInstance()->getJoystickManager()->getJoysticks().isEmpty()) { - const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0); - if (state.axes.size() >= 4 && state.buttons.size() >= 4) { + const QString PRIO_JOYSTICK_NAME = "PrioVR"; + Joystick* prioJoystick = JoystickScriptingInterface::getInstance().joystickWithName(PRIO_JOYSTICK_NAME); + if (prioJoystick) { + const QVector axes = prioJoystick->getAxes(); + const QVector buttons = prioJoystick->getButtons(); + + if (axes.size() >= 4 && buttons.size() >= 4) { if (index == LEFT_HAND_INDEX) { - palm->setControllerButtons(state.buttons.at(1) ? BUTTON_FWD : 0); - palm->setTrigger(state.buttons.at(0) ? 1.0f : 0.0f); - palm->setJoystick(state.axes.at(0), -state.axes.at(1)); + palm->setControllerButtons(buttons[1] ? BUTTON_FWD : 0); + palm->setTrigger(buttons[0] ? 1.0f : 0.0f); + palm->setJoystick(axes[0], -axes[1]); } else { - palm->setControllerButtons(state.buttons.at(3) ? BUTTON_FWD : 0); - palm->setTrigger(state.buttons.at(2) ? 1.0f : 0.0f); - palm->setJoystick(state.axes.at(2), -state.axes.at(3)); + palm->setControllerButtons(buttons[3] ? BUTTON_FWD : 0); + palm->setTrigger(buttons[2] ? 1.0f : 0.0f); + palm->setJoystick(axes[2], -axes[3]); } } } From 875c1dba724ae1995240ed85dace255accb18de3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Sep 2014 08:40:39 -0700 Subject: [PATCH 6/7] change name in header comment to match new class name --- interface/src/scripting/JoystickScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index cf370cf0e9..8911f292b5 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -1,5 +1,5 @@ // -// JoystickManager.cpp +// JoystickScriptingInterface.cpp // interface/src/devices // // Created by Andrzej Kapolka on 5/15/14. From 3ab24d6ea56b90ff23fb3c75eab67bbef6401fbb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 Sep 2014 11:59:44 -0700 Subject: [PATCH 7/7] add a missing HAVE_SDL block --- interface/src/scripting/JoystickScriptingInterface.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index 8911f292b5..1e35c11f61 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -62,6 +62,7 @@ void JoystickScriptingInterface::update() { Joystick* JoystickScriptingInterface::joystickWithName(const QString& name) { Joystick* matchingJoystick = _openJoysticks.value(name); +#ifdef HAVE_SDL if (!matchingJoystick) { // we haven't opened a joystick with this name yet - enumerate our SDL devices and see if it exists int joystickCount = SDL_NumJoysticks(); @@ -75,6 +76,7 @@ Joystick* JoystickScriptingInterface::joystickWithName(const QString& name) { qDebug() << "No matching joystick found with name" << name << "- returning NULL pointer."; } +#endif return matchingJoystick; }