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);