From 0efce7c8eef89e77349748ef56bc2aa54765f845 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 17 Sep 2014 13:50:57 -0700 Subject: [PATCH 01/15] Add hotkey to reload all scripts --- interface/src/Menu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d7679968ae..2417d156a6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -148,7 +148,8 @@ Menu::Menu() : addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL, Qt::CTRL | Qt::SHIFT | Qt::Key_O, appInstance, SLOT(loadScriptURLDialog())); addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, appInstance, SLOT(stopAllScripts())); - addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, 0, appInstance, SLOT(reloadAllScripts())); + addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::SHIFT | Qt::Key_R, + appInstance, SLOT(reloadAllScripts())); addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J, appInstance, SLOT(toggleRunningScriptsWidget())); From b55a5acdd3cf4553d73884e49290fca465bcaf55 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 17 Sep 2014 14:27:11 -0700 Subject: [PATCH 02/15] Update style of running scripts widget --- interface/ui/runningScriptsWidget.ui | 109 ++++++++++++--------------- 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index ddc6ad6c27..b4d17b1561 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -6,8 +6,8 @@ 0 0 - 324 - 643 + 319 + 481 @@ -29,57 +29,12 @@ 20 - - - - - 6 - - - 0 - - - 6 - - - - - color: #0e7077; -font-size: 20px; - - - Running Scripts - - - 0 - - - -1 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + 0 - 1 + 0 @@ -157,7 +112,7 @@ font: bold 16px; 0 - 8 + 4 @@ -218,6 +173,12 @@ font: bold 16px; + + + 0 + 0 + + 0 @@ -236,6 +197,12 @@ font: bold 16px; + + + 0 + 0 + + Helvetica,Arial,sans-serif @@ -252,11 +219,14 @@ font: bold 16px; 0 - Qt::ScrollBarAsNeeded + Qt::ScrollBarAlwaysOn Qt::ScrollBarAlwaysOff + + QAbstractScrollArea::AdjustToContents + true @@ -268,7 +238,7 @@ font: bold 16px; 0 0 - 284 + 264 16 @@ -278,6 +248,9 @@ font: bold 16px; 0 + + Qt::LeftToRight + font-size: 14px; @@ -303,14 +276,20 @@ font: bold 16px; + + + 0 + 0 + + - font: 14px; + font: 14px; color: #5f5f5f; - There are no scripts currently running. + There are no scripts running. - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -325,15 +304,9 @@ font: bold 16px; 0 - 2 + 0 - - - 0 - 300 - - 0 @@ -352,6 +325,12 @@ font: bold 16px; + + + 0 + 0 + + 0 @@ -432,6 +411,12 @@ font: bold 16px; + + + 0 + 0 + + Qt::ScrollBarAlwaysOn From 145425276d74ac9d480bf70e671602918de445ff Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Sep 2014 14:17:08 -0700 Subject: [PATCH 03/15] Fix script list not being hidden --- interface/src/ui/RunningScriptsWidget.cpp | 1 + interface/ui/runningScriptsWidget.ui | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 6efa2f8fe6..baf3995d0e 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -136,6 +136,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { ui->noRunningScriptsLabel->setVisible(list.isEmpty()); + ui->runningScriptsList->setVisible(!list.isEmpty()); ui->reloadAllButton->setVisible(!list.isEmpty()); ui->stopAllButton->setVisible(!list.isEmpty()); diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index b4d17b1561..a55e949d7a 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -222,7 +222,7 @@ font: bold 16px; Qt::ScrollBarAlwaysOn - Qt::ScrollBarAlwaysOff + Qt::ScrollBarAsNeeded QAbstractScrollArea::AdjustToContents From 21a15cff2a7d59447c2785c66972f259950269fa Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 23 Sep 2014 12:50:47 -0700 Subject: [PATCH 04/15] Avatar can look at corrected position when looking at me --- examples/headMove.js | 2 +- interface/src/Application.cpp | 6 +++--- interface/src/Application.h | 3 ++- interface/src/avatar/Head.cpp | 9 +++++++++ interface/src/avatar/Head.h | 7 +++++++ interface/src/avatar/MyAvatar.cpp | 11 +++++++++++ 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/examples/headMove.js b/examples/headMove.js index 4d432c28b3..894575ead1 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -43,7 +43,7 @@ var noFly = true; var fixedWalkVelocity = true; //var roomLimits = { xMin: 618, xMax: 635.5, zMin: 528, zMax: 552.5 }; -var roomLimits = { xMin: 193.0, xMax: 206.5, zMin: 251.4, zMax: 269.5 }; +var roomLimits = { xMin: 100.0, xMax: 206.5, zMin: 251.4, zMax: 269.5 }; function isInRoom(position) { var BUFFER = 2.0; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e1ee1333ca..d8fa22ec8f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1882,13 +1882,13 @@ void Application::shrinkMirrorView() { } } -const float HEAD_SPHERE_RADIUS = 0.07f; +const float HEAD_SPHERE_RADIUS = 0.1f; bool Application::isLookingAtMyAvatar(Avatar* avatar) { glm::vec3 theirLookat = avatar->getHead()->getLookAtPosition(); - glm::vec3 myHeadPosition = _myAvatar->getHead()->getPosition(); + glm::vec3 myEyePosition = _myAvatar->getHead()->getEyePosition(); - if (pointInSphere(theirLookat, myHeadPosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { + if (pointInSphere(theirLookat, myEyePosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { return true; } return false; diff --git a/interface/src/Application.h b/interface/src/Application.h index d17bacd413..63dce2dbfc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -300,6 +300,8 @@ public: ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } void setCursorVisible(bool visible); + + bool isLookingAtMyAvatar(Avatar* avatar); signals: @@ -414,7 +416,6 @@ private: void updateCursor(float deltaTime); Avatar* findLookatTargetAvatar(glm::vec3& eyePosition, QUuid &nodeUUID); - bool isLookingAtMyAvatar(Avatar* avatar); void renderLookatIndicator(glm::vec3 pointOfInterest); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index a06a060b7d..a1f8495f01 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -47,6 +47,7 @@ Head::Head(Avatar* owningAvatar) : _deltaLeanSideways(0.f), _deltaLeanForward(0.f), _isCameraMoving(false), + _isLookingAtMe(false), _faceModel(this) { @@ -219,6 +220,14 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { return glm::quat(glm::radians(glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); } +glm::vec3 Head::getCorrectedLookAtPosition() { + if (_isLookingAtMe) { + return getLookAtPosition(); + } else { + return _correctedLookAtPosition; + } +} + glm::quat Head::getCameraOrientation () const { if (OculusManager::isConnected()) { return getOrientation(); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 58feeff420..1ff6c5d876 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -63,6 +63,10 @@ public: const glm::vec3& getAngularVelocity() const { return _angularVelocity; } void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; } + void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { _correctedLookAtPosition = correctedLookAtPosition; } + glm::vec3 getCorrectedLookAtPosition(); + void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } + float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } const glm::vec3& getEyePosition() const { return _eyePosition; } @@ -143,8 +147,11 @@ private: float _deltaLeanForward; bool _isCameraMoving; + bool _isLookingAtMe; FaceModel _faceModel; + glm::vec3 _correctedLookAtPosition; + // private methods void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 45ac377dc0..4c75f3482c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -953,6 +953,7 @@ void MyAvatar::updateLookAtTargetAvatar() { _targetAvatarPosition = glm::vec3(0.0f); const float MIN_LOOKAT_ANGLE = PI / 4.0f; // Smallest angle between face and person where we will look at someone float smallestAngleTo = MIN_LOOKAT_ANGLE; + int howManyLookingAtMe = 0; foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { Avatar* avatar = static_cast(avatarPointer.data()); avatar->setIsLookAtTarget(false); @@ -965,11 +966,21 @@ void MyAvatar::updateLookAtTargetAvatar() { _targetAvatarPosition = avatarPointer->getPosition(); smallestAngleTo = angleTo; } + // Check if this avatar is looking at me, and fix their gaze on my camera if so + if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { + howManyLookingAtMe++; + // Have that avatar look directly at my camera + // TODO: correct to look at left/right eye + avatar->getHead()->setLookAtPosition(Application::getInstance()->getCamera()->getPosition()); + } } } if (_lookAtTargetAvatar) { static_cast(_lookAtTargetAvatar.data())->setIsLookAtTarget(true); } + if (howManyLookingAtMe > 0) { + qDebug() << "look @me: " << howManyLookingAtMe; + } } void MyAvatar::clearLookAtTargetAvatar() { From 900daf48eb2a6740b7635fc8ee271df6a8fc7be5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Sep 2014 14:48:44 -0700 Subject: [PATCH 05/15] 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 06/15] 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 07/15] 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 08/15] 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 09/15] 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 10/15] 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 11/15] 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; } From 75e536235c63fbfd8dd8a6153c2b206eda59d970 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 24 Sep 2014 14:38:44 -0700 Subject: [PATCH 12/15] Avatars look at your camera, not your avatar. Improvements to lookAt code --- interface/src/Application.cpp | 15 ++++++------- interface/src/Audio.cpp | 20 ++---------------- interface/src/Audio.h | 2 ++ interface/src/avatar/FaceModel.cpp | 2 +- interface/src/avatar/Head.cpp | 11 +++++++--- interface/src/avatar/Head.h | 3 ++- interface/src/avatar/MyAvatar.cpp | 28 +++++++++++++++---------- interface/src/avatar/MyAvatar.h | 2 +- libraries/avatars/src/AvatarHashMap.cpp | 9 +++----- libraries/avatars/src/AvatarHashMap.h | 2 -- 10 files changed, 44 insertions(+), 50 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9397fa063d..3b46b26468 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1890,10 +1890,9 @@ void Application::shrinkMirrorView() { const float HEAD_SPHERE_RADIUS = 0.1f; bool Application::isLookingAtMyAvatar(Avatar* avatar) { - glm::vec3 theirLookat = avatar->getHead()->getLookAtPosition(); + glm::vec3 theirLookAt = avatar->getHead()->getLookAtPosition(); glm::vec3 myEyePosition = _myAvatar->getHead()->getEyePosition(); - - if (pointInSphere(theirLookat, myEyePosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { + if (pointInSphere(theirLookAt, myEyePosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { return true; } return false; @@ -1999,21 +1998,23 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = _myCamera.getPosition(); } else { - if (_myAvatar->getLookAtTargetAvatar() && _myAvatar != _myAvatar->getLookAtTargetAvatar()) { + AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().toStrongRef(); + if (lookingAt && _myAvatar != lookingAt.data()) { + isLookingAtSomeone = true; // If I am looking at someone else, look directly at one of their eyes if (tracker) { // If tracker active, look at the eye for the side my gaze is biased toward if (tracker->getEstimatedEyeYaw() > _myAvatar->getHead()->getFinalYaw()) { // Look at their right eye - lookAtSpot = static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->getRightEyePosition(); + lookAtSpot = static_cast(lookingAt.data())->getHead()->getRightEyePosition(); } else { // Look at their left eye - lookAtSpot = static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->getLeftEyePosition(); + lookAtSpot = static_cast(lookingAt.data())->getHead()->getLeftEyePosition(); } } else { // Need to add randomly looking back and forth between left and right eye for case with no tracker - lookAtSpot = static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->getEyePosition(); + lookAtSpot = static_cast(lookingAt.data())->getHead()->getEyePosition(); } } else { // I am not looking at anyone else, so just look forward diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index e9cc6f9271..365064e979 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -630,7 +630,7 @@ void Audio::handleAudioInput() { measuredDcOffset += networkAudioSamples[i]; networkAudioSamples[i] -= (int16_t) _dcOffset; thisSample = fabsf(networkAudioSamples[i]); - if (thisSample >= (32767.0f * CLIPPING_THRESHOLD)) { + if (thisSample >= ((float)MAX_16_BIT_AUDIO_SAMPLE * CLIPPING_THRESHOLD)) { _timeSinceLastClip = 0.0f; } loudness += thisSample; @@ -1375,32 +1375,16 @@ int Audio::addBufferToScope(QByteArray* byteArray, int frameOffset, const int16_ return 0; } - // Constant multiplier to map sample value to vertical size of scope - float multiplier = (float)MULTIPLIER_SCOPE_HEIGHT / logf(2.0f); - - // Used to scale each sample. (logf(sample) + fadeOffset) is same as logf(sample * fade). - float fadeOffset = logf(fade); - // Temporary variable receives sample value float sample; - // Temporary variable receives mapping of sample value - int16_t value; - QMutexLocker lock(&_guard); // Short int pointer to mapped samples in byte array int16_t* destination = (int16_t*) byteArray->data(); for (int i = 0; i < sourceSamplesPerChannel; i++) { sample = (float)source[i * sourceNumberOfChannels + sourceChannel]; - if (sample > 1) { - value = (int16_t)(multiplier * (logf(sample) + fadeOffset)); - } else if (sample < -1) { - value = (int16_t)(-multiplier * (logf(-sample) + fadeOffset)); - } else { - value = 0; - } - destination[frameOffset] = value; + destination[frameOffset] = sample / (float) MAX_16_BIT_AUDIO_SAMPLE * (float)SCOPE_HEIGHT / 2.0f; frameOffset = (frameOffset == _samplesPerScope - 1) ? 0 : frameOffset + 1; } return frameOffset; diff --git a/interface/src/Audio.h b/interface/src/Audio.h index f100c04684..e94e5ab16c 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -47,6 +47,8 @@ static const int NUM_AUDIO_CHANNELS = 2; +static const int MAX_16_BIT_AUDIO_SAMPLE = 32767; + class QAudioInput; class QAudioOutput; diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index d51973f88f..70f59f0661 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -64,7 +64,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta glm::translate(state.getDefaultTranslationInConstrainedFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); - glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + + glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getCorrectedLookAtPosition() + _owningHead->getSaccade() - model->getTranslation(), 1.0f)); glm::quat between = rotationBetween(front, lookAt); const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 5e23de1d9c..20f1a59bcc 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -200,7 +200,7 @@ void Head::render(float alpha, Model::RenderMode mode) { } void Head::renderPostLighting() { - renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition); + renderLookatVectors(_leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); } void Head::setScale (float scale) { @@ -220,12 +220,17 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { glm::vec3 Head::getCorrectedLookAtPosition() { if (_isLookingAtMe) { - return getLookAtPosition(); - } else { return _correctedLookAtPosition; + } else { + return getLookAtPosition(); } } +void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { + _isLookingAtMe = true; + _correctedLookAtPosition = correctedLookAtPosition; +} + glm::quat Head::getCameraOrientation () const { if (OculusManager::isConnected()) { return getOrientation(); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 1ff6c5d876..a7186dc045 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -63,9 +63,10 @@ public: const glm::vec3& getAngularVelocity() const { return _angularVelocity; } void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; } - void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { _correctedLookAtPosition = correctedLookAtPosition; } + void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition); glm::vec3 getCorrectedLookAtPosition(); void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } + bool getIsLookingAtMe() { return _isLookingAtMe; } float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b61c28ac1c..a3fa6f525d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -951,16 +951,23 @@ void MyAvatar::updateLookAtTargetAvatar() { // _lookAtTargetAvatar.clear(); _targetAvatarPosition = glm::vec3(0.0f); - const float MIN_LOOKAT_ANGLE = PI / 4.0f; // Smallest angle between face and person where we will look at someone - float smallestAngleTo = MIN_LOOKAT_ANGLE; + + glm::quat faceRotation = Application::getInstance()->getViewFrustum()->getOrientation(); + FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); + if (tracker) { + // If faceshift or other face tracker in use, add on the actual angle of the head + faceRotation *= tracker->getHeadRotation(); + } + glm::vec3 lookForward = faceRotation * IDENTITY_FRONT; + glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); + float smallestAngleTo = glm::radians(Application::getInstance()->getCamera()->getFieldOfView()) / 2.f; + int howManyLookingAtMe = 0; foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { Avatar* avatar = static_cast(avatarPointer.data()); avatar->setIsLookAtTarget(false); - if (!avatar->isMyAvatar()) { - glm::vec3 DEFAULT_GAZE_IN_HEAD_FRAME = glm::vec3(0.0f, 0.0f, -1.0f); - float angleTo = glm::angle(getHead()->getFinalOrientationInWorldFrame() * DEFAULT_GAZE_IN_HEAD_FRAME, - glm::normalize(avatar->getHead()->getEyePosition() - getHead()->getEyePosition())); + if (!avatar->isMyAvatar() && avatar->isInitialized()) { + float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); if (angleTo < smallestAngleTo) { _lookAtTargetAvatar = avatarPointer; _targetAvatarPosition = avatarPointer->getPosition(); @@ -970,17 +977,16 @@ void MyAvatar::updateLookAtTargetAvatar() { if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { howManyLookingAtMe++; // Have that avatar look directly at my camera - // TODO: correct to look at left/right eye - avatar->getHead()->setLookAtPosition(Application::getInstance()->getCamera()->getPosition()); + // Philip TODO: correct to look at left/right eye + avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getCamera()->getPosition()); + } else { + avatar->getHead()->clearCorrectedLookAtPosition(); } } } if (_lookAtTargetAvatar) { static_cast(_lookAtTargetAvatar.data())->setIsLookAtTarget(true); } - if (howManyLookingAtMe > 0) { - qDebug() << "look @me: " << howManyLookingAtMe; - } } void MyAvatar::clearLookAtTargetAvatar() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b5eb7ee1ff..e38f3f4b2b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -119,7 +119,7 @@ public: Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); } Q_INVOKABLE glm::vec3 getTargetAvatarPosition() const { return _targetAvatarPosition; } - AvatarData* getLookAtTargetAvatar() const { return _lookAtTargetAvatar.data(); } + QWeakPointer getLookAtTargetAvatar() const { return _lookAtTargetAvatar; } void updateLookAtTargetAvatar(); void clearLookAtTargetAvatar(); diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 202121bad3..f996fc2bad 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -21,11 +21,6 @@ AvatarHashMap::AvatarHashMap() : connect(NodeList::getInstance(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged); } -void AvatarHashMap::insert(const QUuid& sessionUUID, AvatarSharedPointer avatar) { - _avatarHash.insert(sessionUUID, avatar); - avatar->setSessionUUID(sessionUUID); -} - AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) { qDebug() << "Removing Avatar with UUID" << iterator.key() << "from AvatarHashMap."; return _avatarHash.erase(iterator); @@ -95,9 +90,11 @@ AvatarSharedPointer AvatarHashMap::matchingOrNewAvatar(const QUuid& sessionUUID, matchingAvatar = newSharedAvatar(); qDebug() << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap."; - _avatarHash.insert(sessionUUID, matchingAvatar); + matchingAvatar->setSessionUUID(sessionUUID); matchingAvatar->setOwningAvatarMixer(mixerWeakPointer); + + _avatarHash.insert(sessionUUID, matchingAvatar); } return matchingAvatar; diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index fe9ab3d634..d52c656bc1 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -30,8 +30,6 @@ public: const AvatarHash& getAvatarHash() { return _avatarHash; } int size() const { return _avatarHash.size(); } - - virtual void insert(const QUuid& sessionUUID, AvatarSharedPointer avatar); public slots: void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer); From 11e60c864a5b9e326f018ad8e3fd234dee968be0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 24 Sep 2014 15:17:23 -0700 Subject: [PATCH 13/15] Changed recording file format --- libraries/avatars/src/Recording.cpp | 61 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/libraries/avatars/src/Recording.cpp b/libraries/avatars/src/Recording.cpp index fb3ee2b5e7..b34391d580 100644 --- a/libraries/avatars/src/Recording.cpp +++ b/libraries/avatars/src/Recording.cpp @@ -32,7 +32,7 @@ static const int MAGIC_NUMBER_SIZE = 8; static const char MAGIC_NUMBER[MAGIC_NUMBER_SIZE] = {17, 72, 70, 82, 13, 10, 26, 10}; // Version (Major, Minor) -static const QPair VERSION(0, 1); +static const QPair VERSION(0, 2); int SCALE_RADIX = 10; int BLENDSHAPE_RADIX = 15; @@ -118,12 +118,6 @@ bool readQuat(QDataStream& stream, glm::quat& value) { return true; } -void writeFloat(QDataStream& stream, float value, int radix) { - unsigned char buffer[256]; - int writtenToBuffer = packFloatScalarToSignedTwoByteFixed(buffer, value, radix); - stream.writeRawData(reinterpret_cast(buffer), writtenToBuffer); -} - bool readFloat(QDataStream& stream, float& value, int radix) { int floatByteSize = 2; // 1 floats * 2 bytes int16_t buffer[256]; @@ -185,7 +179,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) { // Orientation writeQuat(fileStream, context.orientation); // Scale - writeFloat(fileStream, context.scale, SCALE_RADIX); + fileStream << context.scale; // Head model fileStream << context.headModel; // Skeleton model @@ -204,7 +198,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) { // Orientation writeQuat(fileStream, data.rotation); // Scale - writeFloat(fileStream, data.scale, SCALE_RADIX); + fileStream << data.scale; } // RECORDING @@ -231,7 +225,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) { for (quint32 j = 0; j < numBlendshapes; ++j) { if (i == 0 || frame._blendshapeCoefficients[j] != previousFrame._blendshapeCoefficients[j]) { - writeFloat(stream, frame.getBlendshapeCoefficients()[j], BLENDSHAPE_RADIX); + stream << frame.getBlendshapeCoefficients()[j]; mask.setBit(maskIndex); } ++maskIndex; @@ -277,7 +271,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) { mask.resize(mask.size() + 1); } if (i == 0 || frame._scale != previousFrame._scale) { - writeFloat(stream, frame._scale, SCALE_RADIX); + stream << frame._scale; mask.setBit(maskIndex); } maskIndex++; @@ -297,7 +291,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) { mask.resize(mask.size() + 1); } if (i == 0 || frame._leanSideways != previousFrame._leanSideways) { - writeFloat(stream, frame._leanSideways, LEAN_RADIX); + stream << frame._leanSideways; mask.setBit(maskIndex); } maskIndex++; @@ -307,7 +301,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) { mask.resize(mask.size() + 1); } if (i == 0 || frame._leanForward != previousFrame._leanForward) { - writeFloat(stream, frame._leanForward, LEAN_RADIX); + stream << frame._leanForward; mask.setBit(maskIndex); } maskIndex++; @@ -438,7 +432,7 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, const QString QPair version; fileStream >> version; // File format version - if (version != VERSION) { + if (version != VERSION && version != QPair(0,1)) { qDebug() << "ERROR: This file format version is not supported."; return recording; } @@ -484,10 +478,10 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, const QString } // Scale - if (!readFloat(fileStream, context.scale, SCALE_RADIX)) { - qDebug() << "Couldn't read file correctly. (Invalid float)"; - recording.clear(); - return recording; + if (version == QPair(0,1)) { + readFloat(fileStream, context.scale, SCALE_RADIX); + } else { + fileStream >> context.scale; } // Head model fileStream >> context.headModel; @@ -519,9 +513,10 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, const QString } // Scale - if (!readFloat(fileStream, data.scale, SCALE_RADIX)) { - qDebug() << "Couldn't read attachment correctly. (Invalid float)"; - continue; + if (version == QPair(0,1)) { + readFloat(fileStream, data.scale, SCALE_RADIX); + } else { + fileStream >> data.scale; } context.attachments << data; } @@ -548,8 +543,12 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, const QString } frame._blendshapeCoefficients.resize(numBlendshapes); for (quint32 j = 0; j < numBlendshapes; ++j) { - if (!mask[maskIndex++] || !readFloat(stream, frame._blendshapeCoefficients[j], BLENDSHAPE_RADIX)) { + if (!mask[maskIndex++]) { frame._blendshapeCoefficients[j] = previousFrame._blendshapeCoefficients[j]; + } else if (version == QPair(0,1)) { + readFloat(stream, frame._blendshapeCoefficients[j], BLENDSHAPE_RADIX); + } else { + stream >> frame._blendshapeCoefficients[j]; } } // Joint Rotations @@ -571,20 +570,32 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, const QString frame._rotation = previousFrame._rotation; } - if (!mask[maskIndex++] || !readFloat(stream, frame._scale, SCALE_RADIX)) { + if (!mask[maskIndex++]) { frame._scale = previousFrame._scale; + } else if (version == QPair(0,1)) { + readFloat(stream, frame._scale, SCALE_RADIX); + } else { + stream >> frame._scale; } if (!mask[maskIndex++] || !readQuat(stream, frame._headRotation)) { frame._headRotation = previousFrame._headRotation; } - if (!mask[maskIndex++] || !readFloat(stream, frame._leanSideways, LEAN_RADIX)) { + if (!mask[maskIndex++]) { frame._leanSideways = previousFrame._leanSideways; + } else if (version == QPair(0,1)) { + readFloat(stream, frame._leanSideways, LEAN_RADIX); + } else { + stream >> frame._leanSideways; } - if (!mask[maskIndex++] || !readFloat(stream, frame._leanForward, LEAN_RADIX)) { + if (!mask[maskIndex++]) { frame._leanForward = previousFrame._leanForward; + } else if (version == QPair(0,1)) { + readFloat(stream, frame._leanForward, LEAN_RADIX); + } else { + stream >> frame._leanForward; } if (!mask[maskIndex++] || !readVec3(stream, frame._lookAtPosition)) { From fcc5eb9d0af9ffa31c1d76af2bcf0d53e7fad282 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 24 Sep 2014 16:37:55 -0700 Subject: [PATCH 14/15] Tuning of audio-driven mouths and brows to look better and not stay open --- interface/src/avatar/Head.cpp | 15 +++++++++++++-- interface/src/avatar/Head.h | 1 + interface/src/avatar/MyAvatar.cpp | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 20f1a59bcc..9c41cf8084 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -34,6 +34,7 @@ Head::Head(Avatar* owningAvatar) : _lastLoudness(0.0f), _longTermAverageLoudness(-1.0f), _audioAttack(0.0f), + _audioJawOpen(0.0f), _angularVelocity(0,0,0), _renderLookatVectors(false), _saccade(0.0f, 0.0f, 0.0f), @@ -157,11 +158,21 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { } // use data to update fake Faceshift blendshape coefficients - const float JAW_OPEN_SCALE = 10.f; + const float JAW_OPEN_SCALE = 0.015f; + const float JAW_OPEN_RATE = 0.9f; + const float JAW_CLOSE_RATE = 0.90f; + float audioDelta = sqrtf(glm::max(_averageLoudness - _longTermAverageLoudness, 0.0f)) * JAW_OPEN_SCALE; + if (audioDelta > _audioJawOpen) { + _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE; + } else { + _audioJawOpen *= JAW_CLOSE_RATE; + } + _audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f); + Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink, _browAudioLift, - glm::clamp(log(_averageLoudness) / JAW_OPEN_SCALE, 0.0f, 1.0f), + _audioJawOpen, _blendshapeCoefficients); } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index a7186dc045..efcee9ed8d 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -130,6 +130,7 @@ private: float _lastLoudness; float _longTermAverageLoudness; float _audioAttack; + float _audioJawOpen; glm::vec3 _angularVelocity; bool _renderLookatVectors; glm::vec3 _saccade; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a3fa6f525d..51f582c4f8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -978,7 +978,7 @@ void MyAvatar::updateLookAtTargetAvatar() { howManyLookingAtMe++; // Have that avatar look directly at my camera // Philip TODO: correct to look at left/right eye - avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getCamera()->getPosition()); + avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); } else { avatar->getHead()->clearCorrectedLookAtPosition(); } From 2766b6a4d7d0da21093837c51d9e3a2632d9fc55 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 24 Sep 2014 17:12:49 -0700 Subject: [PATCH 15/15] Make radio show up in front of you --- examples/radio.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/examples/radio.js b/examples/radio.js index 6ffc7deb84..83e81e7e02 100644 --- a/examples/radio.js +++ b/examples/radio.js @@ -9,18 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var position = { x:1, y: 1, z: 10 }; -var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); -var scale = 1.0; var modelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/entities/radio/Speakers2Finished.fbx"; var soundURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/FamilyStereo.raw"; var AudioRotationOffset = Quat.fromPitchYawRollDegrees(0, -90, 0); var audioOptions = new AudioInjectionOptions(); -audioOptions.volume = 0.7; -audioOptions.position = position; -audioOptions.orientation = Quat.multiply(AudioRotationOffset, rotation); +audioOptions.volume = 0.5; audioOptions.loop = true; audioOptions.isStereo = true; var injector = null; @@ -34,15 +29,22 @@ function update() { if (entity === null) { if (sound.downloaded) { print("Sound file downloaded"); + var position = Vec3.sum(MyAvatar.position, + Vec3.multiplyQbyV(MyAvatar.orientation, + { x: 0, y: 0.3, z: -1 })); + var rotation = Quat.multiply(MyAvatar.orientation, + Quat.fromPitchYawRollDegrees(0, -90, 0)); entity = Entities.addEntity({ - type: "Model", - position: position, - rotation: rotation, - radius: scale / 2.0, - modelURL: modelURL + type: "Model", + position: position, + rotation: rotation, + dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + modelURL: modelURL }); properties = Entities.getEntityProperties(entity); + audioOptions.position = position; + audioOptions.orientation = rotation; injector = Audio.playSound(sound, audioOptions); } } else { @@ -61,6 +63,7 @@ function update() { Script.update.disconnect(update); Script.scriptEnding.connect(scriptEnding); scriptEnding(); + Script.stop(); } } }