From 90b77030d5c7da0e88454b503de783bb7e85a080 Mon Sep 17 00:00:00 2001 From: Thijs Wenker <me@thoys.nl> Date: Wed, 7 Mar 2018 02:55:47 +0100 Subject: [PATCH 01/62] MyAvatar.hasScriptedBlendshapes property --- interface/src/avatar/MyAvatar.h | 4 ++++ interface/src/avatar/MyHead.cpp | 7 ++++--- libraries/avatars/src/AvatarData.cpp | 3 ++- libraries/avatars/src/AvatarData.h | 2 ++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fa5206e128..f2d1baf0aa 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -133,6 +133,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(AudioListenerMode audioListenerModeHead READ getAudioListenerModeHead) Q_PROPERTY(AudioListenerMode audioListenerModeCamera READ getAudioListenerModeCamera) Q_PROPERTY(AudioListenerMode audioListenerModeCustom READ getAudioListenerModeCustom) + Q_PROPERTY(bool hasScriptedBlendshapes READ getHasScriptedBlendshapes WRITE setHasScriptedBlendshapes) //TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity) Q_PROPERTY(glm::vec3 leftHandPosition READ getLeftHandPosition) @@ -654,6 +655,8 @@ private: virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override; void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); } bool getShouldRenderLocally() const { return _shouldRender; } + void setHasScriptedBlendshapes(bool hasScriptedBlendshapes) { _hasScriptedBlendShapes = hasScriptedBlendshapes; } + bool getHasScriptedBlendshapes() const override { return _hasScriptedBlendShapes; } bool isMyAvatar() const override { return true; } virtual int parseDataFromBuffer(const QByteArray& buffer) override; virtual glm::vec3 getSkeletonPosition() const override; @@ -764,6 +767,7 @@ private: bool _hmdRollControlEnabled { true }; float _hmdRollControlDeadZone { ROLL_CONTROL_DEAD_ZONE_DEFAULT }; float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT }; + bool _hasScriptedBlendShapes { false }; // working copy -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access glm::mat4 _sensorToWorldMatrix { glm::mat4() }; diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index cad2f9e5d0..b7b8aa5e52 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -46,9 +46,10 @@ void MyHead::simulate(float deltaTime) { auto player = DependencyManager::get<recording::Deck>(); // Only use face trackers when not playing back a recording. if (!player->isPlaying()) { - FaceTracker* faceTracker = qApp->getActiveFaceTracker(); - _isFaceTrackerConnected = faceTracker != nullptr && !faceTracker->isMuted(); - if (_isFaceTrackerConnected) { + auto faceTracker = qApp->getActiveFaceTracker(); + bool hasActualFaceTrackerConnected = faceTracker && !faceTracker->isMuted(); + _isFaceTrackerConnected = hasActualFaceTrackerConnected || _owningAvatar->getHasScriptedBlendshapes(); + if (hasActualFaceTrackerConnected) { _transientBlendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); if (typeid(*faceTracker) == typeid(DdeFaceTracker)) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 1bbc8cc1a5..dcaae59a38 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -300,7 +300,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent tranlationChangedSince(lastSentTime) || parentInfoChangedSince(lastSentTime)); - hasFaceTrackerInfo = !dropFaceTracking && hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime)); + hasFaceTrackerInfo = !dropFaceTracking && (hasFaceTracker() || getHasScriptedBlendshapes()) && + (sendAll || faceTrackerInfoChangedSince(lastSentTime)); hasJointData = sendAll || !sendMinimum; hasJointDefaultPoseFlags = hasJointData; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e927120b07..1f6d2e3630 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -497,6 +497,8 @@ public: float getDomainLimitedScale() const; + virtual bool getHasScriptedBlendshapes() const { return false; } + /**jsdoc * returns the minimum scale allowed for this avatar in the current domain. * This value can change as the user changes avatars or when changing domains. From b0187ecfd3dfdceb084884a72cc1a432f6018ebf Mon Sep 17 00:00:00 2001 From: Thijs Wenker <me@thoys.nl> Date: Tue, 24 Apr 2018 19:24:23 +0200 Subject: [PATCH 02/62] add MyAvatar.hasAudioEnabledFaceMovement API property which is enabled by default --- interface/src/avatar/MyAvatar.h | 4 +++ interface/src/avatar/MyHead.cpp | 45 ++++++++++++++++-------------- libraries/avatars/src/AvatarData.h | 1 + 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b8c9e4d595..537b5de8d8 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -134,6 +134,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(AudioListenerMode audioListenerModeCamera READ getAudioListenerModeCamera) Q_PROPERTY(AudioListenerMode audioListenerModeCustom READ getAudioListenerModeCustom) Q_PROPERTY(bool hasScriptedBlendshapes READ getHasScriptedBlendshapes WRITE setHasScriptedBlendshapes) + Q_PROPERTY(bool hasAudioEnabledFaceMovement READ getHasAudioEnabledFaceMovement WRITE setHasAudioEnabledFaceMovement) //TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity) Q_PROPERTY(glm::vec3 leftHandPosition READ getLeftHandPosition) @@ -684,6 +685,8 @@ private: bool getShouldRenderLocally() const { return _shouldRender; } void setHasScriptedBlendshapes(bool hasScriptedBlendshapes) { _hasScriptedBlendShapes = hasScriptedBlendshapes; } bool getHasScriptedBlendshapes() const override { return _hasScriptedBlendShapes; } + void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement) { _hasAudioEnabledFaceMovement = hasAudioEnabledFaceMovement; } + bool getHasAudioEnabledFaceMovement() const override { return _hasAudioEnabledFaceMovement; } bool isMyAvatar() const override { return true; } virtual int parseDataFromBuffer(const QByteArray& buffer) override; virtual glm::vec3 getSkeletonPosition() const override; @@ -793,6 +796,7 @@ private: float _hmdRollControlDeadZone { ROLL_CONTROL_DEAD_ZONE_DEFAULT }; float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT }; bool _hasScriptedBlendShapes { false }; + bool _hasAudioEnabledFaceMovement { true }; // working copy -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access glm::mat4 _sensorToWorldMatrix { glm::mat4() }; diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index b7b8aa5e52..ed38fdd004 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -47,29 +47,32 @@ void MyHead::simulate(float deltaTime) { // Only use face trackers when not playing back a recording. if (!player->isPlaying()) { auto faceTracker = qApp->getActiveFaceTracker(); - bool hasActualFaceTrackerConnected = faceTracker && !faceTracker->isMuted(); + const bool hasActualFaceTrackerConnected = faceTracker && !faceTracker->isMuted(); _isFaceTrackerConnected = hasActualFaceTrackerConnected || _owningAvatar->getHasScriptedBlendshapes(); - if (hasActualFaceTrackerConnected) { - _transientBlendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - - if (typeid(*faceTracker) == typeid(DdeFaceTracker)) { - - if (Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) { - calculateMouthShapes(deltaTime); - - const int JAW_OPEN_BLENDSHAPE = 21; - const int MMMM_BLENDSHAPE = 34; - const int FUNNEL_BLENDSHAPE = 40; - const int SMILE_LEFT_BLENDSHAPE = 28; - const int SMILE_RIGHT_BLENDSHAPE = 29; - _transientBlendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; - _transientBlendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; - _transientBlendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; - _transientBlendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; - _transientBlendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; - } - applyEyelidOffset(getFinalOrientationInWorldFrame()); + if (_isFaceTrackerConnected) { + if (hasActualFaceTrackerConnected) { + _transientBlendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + } else { + _transientBlendshapeCoefficients.fill(0, _blendshapeCoefficients.size()); } + + if (_owningAvatar->getHasAudioEnabledFaceMovement() || (faceTracker && (typeid(*faceTracker) == typeid(DdeFaceTracker)) + && Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth))) { + + calculateMouthShapes(deltaTime); + + const int JAW_OPEN_BLENDSHAPE = 21; + const int MMMM_BLENDSHAPE = 34; + const int FUNNEL_BLENDSHAPE = 40; + const int SMILE_LEFT_BLENDSHAPE = 28; + const int SMILE_RIGHT_BLENDSHAPE = 29; + _transientBlendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; + _transientBlendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; + _transientBlendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; + _transientBlendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; + _transientBlendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; + } + applyEyelidOffset(getFinalOrientationInWorldFrame()); } auto eyeTracker = DependencyManager::get<EyeTracker>(); _isEyeTrackerConnected = eyeTracker->isTracking(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index fbef083dcd..fe4ff364ae 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -503,6 +503,7 @@ public: float getDomainLimitedScale() const; virtual bool getHasScriptedBlendshapes() const { return false; } + virtual bool getHasAudioEnabledFaceMovement() const { return false; } /**jsdoc * returns the minimum scale allowed for this avatar in the current domain. From 192e48a376026b565ce89b39992b6060fc48d1c6 Mon Sep 17 00:00:00 2001 From: Thijs Wenker <me@thoys.nl> Date: Wed, 25 Apr 2018 13:47:00 +0200 Subject: [PATCH 03/62] style fix + JSDocs --- interface/src/avatar/MyAvatar.h | 2 ++ interface/src/avatar/MyHead.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 537b5de8d8..9bccc93fbf 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -80,6 +80,8 @@ class MyAvatar : public Avatar { * MyAvatar.audioListenerModeCamera - the listener is relative to the camera. * MyAvatar.audioListenerModeCustom - the listener is at a custom location specified by the MyAvatar.customListenPosition * and MyAvatar.customListenOrientation properties. + * @property hasScriptedBlendshapes {bool} Blendshapes will be transmitted over the network if set to true. + * @property hasAudioEnabledFaceMovement {bool} If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled. * @property customListenPosition {Vec3} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this determines the position * of audio spatialization listener. * @property customListenOrientation {Quat} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this determines the orientation diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index ed38fdd004..44d679f3f8 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -72,7 +72,7 @@ void MyHead::simulate(float deltaTime) { _transientBlendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; _transientBlendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; } - applyEyelidOffset(getFinalOrientationInWorldFrame()); + applyEyelidOffset(getFinalOrientationInWorldFrame()); } auto eyeTracker = DependencyManager::get<EyeTracker>(); _isEyeTrackerConnected = eyeTracker->isTracking(); From 484e20ea55dc6027b06447e6ca56baeabed88f52 Mon Sep 17 00:00:00 2001 From: Thijs Wenker <me@thoys.nl> Date: Wed, 25 Apr 2018 19:01:18 +0200 Subject: [PATCH 04/62] JSDOC - change bool type to boolean, to match JS type --- interface/src/avatar/MyAvatar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9bccc93fbf..23faff88ee 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -80,8 +80,8 @@ class MyAvatar : public Avatar { * MyAvatar.audioListenerModeCamera - the listener is relative to the camera. * MyAvatar.audioListenerModeCustom - the listener is at a custom location specified by the MyAvatar.customListenPosition * and MyAvatar.customListenOrientation properties. - * @property hasScriptedBlendshapes {bool} Blendshapes will be transmitted over the network if set to true. - * @property hasAudioEnabledFaceMovement {bool} If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled. + * @property hasScriptedBlendshapes {boolean} Blendshapes will be transmitted over the network if set to true. + * @property hasAudioEnabledFaceMovement {boolean} If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled. * @property customListenPosition {Vec3} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this determines the position * of audio spatialization listener. * @property customListenOrientation {Quat} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this determines the orientation From bbd31d590bb5f465fa5f906ac7dbf756abf7af53 Mon Sep 17 00:00:00 2001 From: Thijs Wenker <me@thoys.nl> Date: Thu, 26 Apr 2018 03:12:44 +0200 Subject: [PATCH 05/62] defaults --- interface/src/avatar/MyAvatar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ef2b0cd042..512273aee6 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -82,8 +82,8 @@ class MyAvatar : public Avatar { * @property {number} audioListenerModeCamera=1 - The audio listening position is at the camera. <em>Read-only.</em> * @property {number} audioListenerModeCustom=2 - The audio listening position is at a the position specified by set by the * <code>customListenPosition</code> and <code>customListenOrientation</code> property values. <em>Read-only.</em> - * @property hasScriptedBlendshapes {boolean} Blendshapes will be transmitted over the network if set to true. - * @property hasAudioEnabledFaceMovement {boolean} If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled. + * @property {boolean} hasScriptedBlendshapes=false - Blendshapes will be transmitted over the network if set to true. + * @property {boolean} hasAudioEnabledFaceMovement=true - If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled. * @property {Vec3} customListenPosition=Vec3.ZERO - The listening position used when the <code>audioListenerMode</code> * property value is <code>audioListenerModeCustom</code>. * @property {Quat} customListenOrientation=Quat.IDENTITY - The listening orientation used when the From 8b4298514e58530d9c5236cef450ad03431a7d0a Mon Sep 17 00:00:00 2001 From: Thijs Wenker <me@thoys.nl> Date: Tue, 15 May 2018 21:39:17 +0200 Subject: [PATCH 06/62] send out one last blendshape update when setting MyAvatar.hasScriptedBlendshapes to false --- interface/src/avatar/MyAvatar.cpp | 13 +++++++++++++ interface/src/avatar/MyAvatar.h | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6c6f6d4d41..e4d255f4ee 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2081,6 +2081,19 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { return !defaultMode || !firstPerson || !insideHead; } +void MyAvatar::setHasScriptedBlendshapes(bool hasScriptedBlendshapes) { + if (hasScriptedBlendshapes == _hasScriptedBlendShapes) { + return; + } + if (!hasScriptedBlendshapes) { + // send a forced avatarData update to make sure the script can send neutal blendshapes on unload + // without having to wait for the update loop, make sure _hasScriptedBlendShapes is still true + // before sending the update, or else it won't send the neutal blendshapes to the receiving clients + sendAvatarDataPacket(true); + } + _hasScriptedBlendShapes = hasScriptedBlendshapes; +} + void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 76966b5ab3..46cdd7b8ae 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1345,7 +1345,7 @@ private: virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override; void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); } bool getShouldRenderLocally() const { return _shouldRender; } - void setHasScriptedBlendshapes(bool hasScriptedBlendshapes) { _hasScriptedBlendShapes = hasScriptedBlendshapes; } + void setHasScriptedBlendshapes(bool hasScriptedBlendshapes); bool getHasScriptedBlendshapes() const override { return _hasScriptedBlendShapes; } void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement) { _hasAudioEnabledFaceMovement = hasAudioEnabledFaceMovement; } bool getHasAudioEnabledFaceMovement() const override { return _hasAudioEnabledFaceMovement; } @@ -1457,7 +1457,7 @@ private: bool _hmdRollControlEnabled { true }; float _hmdRollControlDeadZone { ROLL_CONTROL_DEAD_ZONE_DEFAULT }; float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT }; - bool _hasScriptedBlendShapes { false }; + std::atomic<bool> _hasScriptedBlendShapes { false }; bool _hasAudioEnabledFaceMovement { true }; // working copy -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access From adee5e9ef7a544e201fadf3a5e75ff71aa8d0287 Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Thu, 24 May 2018 17:54:53 -0700 Subject: [PATCH 07/62] fix crash --- interface/src/ui/overlays/Web3DOverlay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index c678e3d2a2..8af818edc6 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -259,7 +259,6 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("Web3DOverlay", this); _webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface()); - _webSurface->getSurfaceContext()->setContextProperty("desktop", DependencyManager::get<OffscreenUi>()->getDesktop()); _webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance()); // Override min fps for tablet UI, for silky smooth scrolling From 720b0a896323a309e71486d1bc0193e337aad3b3 Mon Sep 17 00:00:00 2001 From: Wayne Chen <wayne@highfidelity.io> Date: Fri, 25 May 2018 09:51:16 -0700 Subject: [PATCH 08/62] Adding fix for enabling saved front/back advanced controls. --- ...oggleAdvancedMovementForHandControllers.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js index a1b96ac607..78b074573f 100644 --- a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js +++ b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js @@ -171,4 +171,24 @@ Messages.subscribe(HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL); Messages.messageReceived.connect(handleMessage); + function initializeControls() { + if(HMD.active) { + if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) { + if (MyAvatar.useAdvancedMovementControls) { + Controller.disableMapping(DRIVING_MAPPING_NAME); + } else { + Controller.enableMapping(DRIVING_MAPPING_NAME); + } + + if (MyAvatar.getFlyingEnabled()) { + Controller.disableMapping(FLYING_MAPPING_NAME); + } else { + Controller.enableMapping(FLYING_MAPPING_NAME); + } + }); + + } + } + + initializeControls(); }()); // END LOCAL_SCOPE From 68b18def2252f15f0e72fed81e2feb8e919ca6ac Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Fri, 25 May 2018 15:34:17 -0700 Subject: [PATCH 09/62] fix copy delete cut paste commands and menus --- interface/src/Menu.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f55c389a1f..42618796a5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -103,16 +103,32 @@ Menu::Menu() { editMenu->addSeparator(); // Edit > Cut - addActionToQMenuAndActionHash(editMenu, "Cut", Qt::CTRL | Qt::Key_X); + auto cutAction = addActionToQMenuAndActionHash(editMenu, "Cut", QKeySequence::Cut); + connect(cutAction, &QAction::triggered, [] { + QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_X, Qt::ControlModifier); + QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); + }); // Edit > Copy - addActionToQMenuAndActionHash(editMenu, "Copy", Qt::CTRL | Qt::Key_C); + auto copyAction = addActionToQMenuAndActionHash(editMenu, "Copy", QKeySequence::Copy); + connect(copyAction, &QAction::triggered, [] { + QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier); + QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); + }); // Edit > Paste - addActionToQMenuAndActionHash(editMenu, "Paste", Qt::CTRL | Qt::Key_V); + auto pasteAction = addActionToQMenuAndActionHash(editMenu, "Paste", QKeySequence::Paste); + connect(pasteAction, &QAction::triggered, [] { + QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_V, Qt::ControlModifier); + QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); + }); // Edit > Delete - addActionToQMenuAndActionHash(editMenu, "Delete", Qt::Key_Delete); + auto deleteAction =addActionToQMenuAndActionHash(editMenu, "Delete", QKeySequence::Delete); + connect(deleteAction, &QAction::triggered, [] { + QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Delete, Qt::ControlModifier); + QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); + }); editMenu->addSeparator(); From 3942f397d006fb3aefc72f7e4af1c660301c1ba7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Tue, 29 May 2018 17:38:02 -0700 Subject: [PATCH 10/62] adding back reload scripts --- interface/src/AboutUtil.cpp | 16 ++++++++-------- interface/src/AboutUtil.h | 19 ++++++++----------- interface/src/Application.cpp | 8 +++++++- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/interface/src/AboutUtil.cpp b/interface/src/AboutUtil.cpp index 5179897443..43b4ac1ff4 100644 --- a/interface/src/AboutUtil.cpp +++ b/interface/src/AboutUtil.cpp @@ -20,9 +20,9 @@ #include <OffscreenQmlDialog.h> AboutUtil::AboutUtil(QObject *parent) : QObject(parent) { - QLocale locale_; - m_DateConverted = QDate::fromString(BuildInfo::BUILD_TIME, "dd/MM/yyyy"). - toString(locale_.dateFormat(QLocale::ShortFormat)); + QLocale locale; + _dateConverted = QDate::fromString(BuildInfo::BUILD_TIME, "dd/MM/yyyy"). + toString(locale.dateFormat(QLocale::ShortFormat)); } AboutUtil *AboutUtil::getInstance() @@ -31,17 +31,17 @@ AboutUtil *AboutUtil::getInstance() return &instance; } -QString AboutUtil::buildDate() const +QString AboutUtil::getBuildDate() const { - return m_DateConverted; + return _dateConverted; } -QString AboutUtil::buildVersion() const +QString AboutUtil::getBuildVersion() const { return BuildInfo::VERSION; } -QString AboutUtil::qtVersion() const +QString AboutUtil::getQtVersion() const { return qVersion(); } @@ -49,7 +49,7 @@ QString AboutUtil::qtVersion() const void AboutUtil::openUrl(const QString& url) const { auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); - auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + auto tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); auto hmd = DependencyManager::get<HMDScriptingInterface>(); auto offscreenUi = DependencyManager::get<OffscreenUi>(); diff --git a/interface/src/AboutUtil.h b/interface/src/AboutUtil.h index 9b65b887b9..06c04cc9df 100644 --- a/interface/src/AboutUtil.h +++ b/interface/src/AboutUtil.h @@ -16,27 +16,24 @@ #include <QObject> class AboutUtil : public QObject { - Q_OBJECT - Q_PROPERTY(QString buildDate READ buildDate CONSTANT) - Q_PROPERTY(QString buildVersion READ buildVersion CONSTANT) - Q_PROPERTY(QString qtVersion READ qtVersion CONSTANT) - - AboutUtil(QObject* parent = nullptr); + Q_PROPERTY(QString buildDate READ getBuildDate CONSTANT) + Q_PROPERTY(QString buildVersion READ getBuildVersion CONSTANT) + Q_PROPERTY(QString qtVersion READ getQtVersion CONSTANT) public: static AboutUtil* getInstance(); ~AboutUtil() {} - QString buildDate() const; - QString buildVersion() const; - QString qtVersion() const; + QString getBuildDate() const; + QString getBuildVersion() const; + QString getQtVersion() const; public slots: void openUrl(const QString &url) const; private: - - QString m_DateConverted; + AboutUtil(QObject* parent = nullptr); + QString _dateConverted; }; #endif // hifi_AboutUtil_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6a102f418b..626ece9fe5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3642,7 +3642,6 @@ void Application::keyPressEvent(QKeyEvent* event) { _keysPressed.insert(event->key()); _controllerScriptingInterface->emitKeyPressEvent(event); // send events to any registered scripts - // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isKeyCaptured(event)) { return; @@ -3727,6 +3726,13 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; + case Qt::Key_R: + if (isMeta && !event->isAutoRepeat()) { + DependencyManager::get<ScriptEngines>()->reloadAllScripts(); + DependencyManager::get<OffscreenUi>()->clearCache(); + } + break; + case Qt::Key_Asterisk: Menu::getInstance()->triggerOption(MenuOption::DefaultSkybox); break; From 646b852aefa6d3c0643de54a4f6cab9d964b9c2d Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Tue, 29 May 2018 17:55:42 -0700 Subject: [PATCH 11/62] fix headers --- interface/src/AboutUtil.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/interface/src/AboutUtil.cpp b/interface/src/AboutUtil.cpp index 43b4ac1ff4..634e52b481 100644 --- a/interface/src/AboutUtil.cpp +++ b/interface/src/AboutUtil.cpp @@ -8,16 +8,18 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +#include "AboutUtil.h" #include <QDate> #include <QLocale> -#include "AboutUtil.h" -#include "BuildInfo.h" #include <ui/TabletScriptingInterface.h> +#include <OffscreenQmlDialog.h> + +#include "BuildInfo.h" #include "DependencyManager.h" #include "scripting/HMDScriptingInterface.h" #include "Application.h" -#include <OffscreenQmlDialog.h> AboutUtil::AboutUtil(QObject *parent) : QObject(parent) { QLocale locale; @@ -25,24 +27,20 @@ AboutUtil::AboutUtil(QObject *parent) : QObject(parent) { toString(locale.dateFormat(QLocale::ShortFormat)); } -AboutUtil *AboutUtil::getInstance() -{ +AboutUtil *AboutUtil::getInstance() { static AboutUtil instance; return &instance; } -QString AboutUtil::getBuildDate() const -{ +QString AboutUtil::getBuildDate() const { return _dateConverted; } -QString AboutUtil::getBuildVersion() const -{ +QString AboutUtil::getBuildVersion() const { return BuildInfo::VERSION; } -QString AboutUtil::getQtVersion() const -{ +QString AboutUtil::getQtVersion() const { return qVersion(); } From 19308c3a58bcbf8e3d6680fb6ad74463008ff318 Mon Sep 17 00:00:00 2001 From: Wayne Chen <wayne@highfidelity.io> Date: Wed, 30 May 2018 11:22:17 -0700 Subject: [PATCH 12/62] fixing typo in script file. --- .../toggleAdvancedMovementForHandControllers.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js index 78b074573f..92d079cff6 100644 --- a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js +++ b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js @@ -185,10 +185,9 @@ } else { Controller.enableMapping(FLYING_MAPPING_NAME); } - }); + } + } + } - } - } - - initializeControls(); + initializeControls(); }()); // END LOCAL_SCOPE From 6fa58fce1f22c1bd3efa838feff1566d41d00f2b Mon Sep 17 00:00:00 2001 From: Gabriel <gcalero1984@gmail.com> Date: Tue, 29 May 2018 16:42:09 -0300 Subject: [PATCH 13/62] Update Application.cpp Remove the mic bar for android --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6a102f418b..b4372cf8c2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3011,9 +3011,11 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { auto surfaceContext = DependencyManager::get<OffscreenUi>()->getSurfaceContext(); surfaceContext->setContextProperty("Stats", Stats::getInstance()); +#if !defined(Q_OS_ANDROID) auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto qml = PathUtils::qmlUrl("AvatarInputsBar.qml"); offscreenUi->show(qml, "AvatarInputsBar"); +#endif } void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { From 3f696df3a50fc26e2f3c6ef6a4ca57d42d362d8f Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Tue, 29 May 2018 17:21:44 -0300 Subject: [PATCH 14/62] Show stats button only in debug mode. Add isDebugMode to Script public interface --- libraries/script-engine/src/ScriptEngine.cpp | 8 ++++++++ libraries/script-engine/src/ScriptEngine.h | 6 ++++++ scripts/+android/defaultScripts.js | 17 +++++++++++++++-- scripts/system/+android/stats.js | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 23ffbabe77..72860acbc5 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -237,6 +237,14 @@ QString ScriptEngine::getContext() const { return "unknown"; } +bool ScriptEngine::isDebugMode() const { +#if defined(DEBUG) + return true; +#else + return false; +#endif +} + ScriptEngine::~ScriptEngine() { auto scriptEngines = DependencyManager::get<ScriptEngines>(); if (scriptEngines) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 3001666b5d..c02a63ef3c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -232,6 +232,12 @@ public: */ Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } + /**jsdoc + * @function Script.isDebugMode + * @returns {boolean} + */ + Q_INVOKABLE bool isDebugMode() const; + /**jsdoc * @function Script.isEntityClientScript * @returns {boolean} diff --git a/scripts/+android/defaultScripts.js b/scripts/+android/defaultScripts.js index 98fbb4b1a7..8950af808d 100644 --- a/scripts/+android/defaultScripts.js +++ b/scripts/+android/defaultScripts.js @@ -16,8 +16,7 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/+android/touchscreenvirtualpad.js", "system/+android/actionbar.js", "system/+android/audio.js" , - "system/+android/modes.js", - "system/+android/stats.js"/*, + "system/+android/modes.js"/*, "system/away.js", "system/controllers/controllerDisplayManager.js", "system/controllers/handControllerGrabAndroid.js", @@ -33,6 +32,10 @@ var DEFAULT_SCRIPTS_COMBINED = [ "developer/debugging/debugAndroidMouse.js"*/ ]; +var DEBUG_SCRIPTS = [ + "system/+android/stats.js" +]; + var DEFAULT_SCRIPTS_SEPARATE = [ ]; // add a menu item for debugging @@ -70,6 +73,11 @@ function runDefaultsTogether() { for (var i in DEFAULT_SCRIPTS_COMBINED) { Script.include(DEFAULT_SCRIPTS_COMBINED[i]); } + if (Script.isDebugMode()) { + for (var i in DEBUG_SCRIPTS) { + Script.include(DEBUG_SCRIPTS[i]); + } + } loadSeparateDefaults(); } @@ -77,6 +85,11 @@ function runDefaultsSeparately() { for (var i in DEFAULT_SCRIPTS_COMBINED) { Script.load(DEFAULT_SCRIPTS_COMBINED[i]); } + if (Script.isDebugMode()) { + for (var i in DEBUG_SCRIPTS) { + Script.load(DEBUG_SCRIPTS[i]); + } + } loadSeparateDefaults(); } diff --git a/scripts/system/+android/stats.js b/scripts/system/+android/stats.js index a93bcb5794..0731684291 100644 --- a/scripts/system/+android/stats.js +++ b/scripts/system/+android/stats.js @@ -30,7 +30,7 @@ function init() { text: "STATS" }); statsButton.clicked.connect(function() { - Menu.triggerOption("Stats"); + Menu.triggerOption("Show Statistics"); }); } From 785c0b634d1e98117815e280ab45260177ff32bd Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Fri, 25 May 2018 17:42:41 -0300 Subject: [PATCH 15/62] Change gradle configuration to sign release apk. Remove Daydream intent from AndroidManifest --- android/app/build.gradle | 9 +++++++++ android/app/src/main/AndroidManifest.xml | 6 ------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 70f7c622a0..5f92417ba4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -27,6 +27,14 @@ android { '-DDISABLE_KTX_CACHE=OFF' } } + signingConfigs { + release { + storeFile file(HIFI_ANDROID_KEYSTORE) + storePassword HIFI_ANDROID_KEYSTORE_PASSWORD + keyAlias HIFI_ANDROID_KEY_ALIAS + keyPassword HIFI_ANDROID_KEY_PASSWORD + } + } } compileOptions { @@ -38,6 +46,7 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e105f5bccf..0b52046057 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -49,12 +49,6 @@ android:label="@string/app_name" android:launchMode="singleTop" > - - <intent-filter> - <category android:name="com.google.intent.category.DAYDREAM"/> - <action android:name="android.intent.action.MAIN" /> - </intent-filter> - <meta-data android:name="android.app.lib_name" android:value="native-lib"/> <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/> From a0274f8b4bac07ae45f70efcbc670202c0f14078 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Wed, 30 May 2018 12:43:44 -0300 Subject: [PATCH 16/62] Make APK release signature optional --- android/app/build.gradle | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 5f92417ba4..46de9642d9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,10 +29,10 @@ android { } signingConfigs { release { - storeFile file(HIFI_ANDROID_KEYSTORE) - storePassword HIFI_ANDROID_KEYSTORE_PASSWORD - keyAlias HIFI_ANDROID_KEY_ALIAS - keyPassword HIFI_ANDROID_KEY_PASSWORD + storeFile project.hasProperty("HIFI_ANDROID_KEYSTORE") ? file(HIFI_ANDROID_KEYSTORE) : null + storePassword project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") ? HIFI_ANDROID_KEYSTORE_PASSWORD : '' + keyAlias project.hasProperty("HIFI_ANDROID_KEY_ALIAS") ? HIFI_ANDROID_KEY_ALIAS : '' + keyPassword project.hasProperty("HIFI_ANDROID_KEY_PASSWORD") ? HIFI_ANDROID_KEY_PASSWORD : '' } } } @@ -46,7 +46,10 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release + signingConfig project.hasProperty("HIFI_ANDROID_KEYSTORE") && + project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") && + project.hasProperty("HIFI_ANDROID_KEY_ALIAS") && + project.hasProperty("HIFI_ANDROID_KEY_PASSWORD")? signingConfigs.release : null } } From 8cdbf460db8590487ece33be01a93888d55842be Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Wed, 30 May 2018 13:36:02 -0700 Subject: [PATCH 17/62] adding back notifcations --- scripts/defaultScripts.js | 1 + scripts/system/notifications.js | 49 --------------------------------- 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index b0cbf0e246..59a51830be 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -23,6 +23,7 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/makeUserConnection.js", "system/tablet-goto.js", "system/marketplaces/marketplaces.js", + "system/notifications.js", "system/commerce/wallet.js", "system/edit.js", "system/dialTone.js", diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index a28f343ad3..0778e2a44b 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -79,11 +79,7 @@ var frame = 0; var ctrlIsPressed = false; var ready = true; - var MENU_NAME = 'Tools > Notifications'; - var PLAY_NOTIFICATION_SOUNDS_MENU_ITEM = "Play Notification Sounds"; var NOTIFICATION_MENU_ITEM_POST = " Notifications"; - var PLAY_NOTIFICATION_SOUNDS_SETTING = "play_notification_sounds"; - var PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE = "play_notification_sounds_type_"; var NOTIFICATIONS_MESSAGE_CHANNEL = "Hifi-Notifications"; var NotificationType = { @@ -401,11 +397,6 @@ alpha: backgroundAlpha }; - if (Menu.isOptionChecked(PLAY_NOTIFICATION_SOUNDS_MENU_ITEM) && - Menu.isOptionChecked(NotificationType.getMenuString(notificationType))) { - randomSounds.playRandom(); - } - return notify(noticeProperties, buttonProperties, height, imageProperties); } @@ -618,30 +609,6 @@ } } - function setup() { - var type; - Menu.addMenu(MENU_NAME); - var checked = Settings.getValue(PLAY_NOTIFICATION_SOUNDS_SETTING); - checked = checked === '' ? true : checked; - Menu.addMenuItem({ - menuName: MENU_NAME, - menuItemName: PLAY_NOTIFICATION_SOUNDS_MENU_ITEM, - isCheckable: true, - isChecked: Settings.getValue(PLAY_NOTIFICATION_SOUNDS_SETTING) - }); - Menu.addSeparator(MENU_NAME, "Play sounds for:"); - for (type in NotificationType.properties) { - checked = Settings.getValue(PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE + (parseInt(type, 10) + 1)); - checked = checked === '' ? true : checked; - Menu.addMenuItem({ - menuName: MENU_NAME, - menuItemName: NotificationType.properties[type].text + NOTIFICATION_MENU_ITEM_POST, - isCheckable: true, - isChecked: checked - }); - } - } - // When our script shuts down, we should clean up all of our overlays function scriptEnding() { var notificationIndex; @@ -649,27 +616,14 @@ Overlays.deleteOverlay(notifications[notificationIndex]); Overlays.deleteOverlay(buttons[notificationIndex]); } - Menu.removeMenu(MENU_NAME); Messages.unsubscribe(NOTIFICATIONS_MESSAGE_CHANNEL); } - function menuItemEvent(menuItem) { - if (menuItem === PLAY_NOTIFICATION_SOUNDS_MENU_ITEM) { - Settings.setValue(PLAY_NOTIFICATION_SOUNDS_SETTING, Menu.isOptionChecked(PLAY_NOTIFICATION_SOUNDS_MENU_ITEM)); - return; - } - var notificationType = NotificationType.getTypeFromMenuItem(menuItem); - if (notificationType !== notificationType.UNKNOWN) { - Settings.setValue(PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE + notificationType, Menu.isOptionChecked(menuItem)); - } - } - Controller.keyPressEvent.connect(keyPressEvent); Controller.mousePressEvent.connect(mousePressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); - Menu.menuItemEvent.connect(menuItemEvent); Window.domainConnectionRefused.connect(onDomainConnectionRefused); Window.stillSnapshotTaken.connect(onSnapshotTaken); Window.snapshot360Taken.connect(onSnapshotTaken); @@ -684,7 +638,4 @@ Messages.subscribe(NOTIFICATIONS_MESSAGE_CHANNEL); Messages.messageReceived.connect(onMessageReceived); - - setup(); - }()); // END LOCAL_SCOPE From 03bad0265c3a4259eddc4d97a160440c693b887e Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Thu, 31 May 2018 11:09:51 +1200 Subject: [PATCH 18/62] Fix properties not populating particle explorer tab --- scripts/system/edit.js | 11 +++----- .../particle_explorer/particleExplorerTool.js | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index f549c7dd85..9285023ed8 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -2366,22 +2366,19 @@ var selectedParticleEntity = 0; var selectedParticleEntityID = null; function selectParticleEntity(entityID) { - var properties = Entities.getEntityProperties(entityID); selectedParticleEntityID = entityID; + + var properties = Entities.getEntityProperties(entityID); if (properties.emitOrientation) { properties.emitOrientation = Quat.safeEulerAngles(properties.emitOrientation); } - var particleData = { - messageType: "particle_settings", - currentProperties: properties - }; + particleExplorerTool.destroyWebView(); particleExplorerTool.createWebView(); selectedParticleEntity = entityID; particleExplorerTool.setActiveParticleEntity(entityID); - - particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); + particleExplorerTool.setActiveParticleProperties(properties); // Switch to particle explorer var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); diff --git a/scripts/system/particle_explorer/particleExplorerTool.js b/scripts/system/particle_explorer/particleExplorerTool.js index d85fc169b1..016691e2b6 100644 --- a/scripts/system/particle_explorer/particleExplorerTool.js +++ b/scripts/system/particle_explorer/particleExplorerTool.js @@ -16,37 +16,55 @@ var PARTICLE_EXPLORER_HTML_URL = Script.resolvePath('particleExplorer.html'); ParticleExplorerTool = function() { var that = {}; + that.activeParticleEntity = 0; + that.activeParticleProperties = {}; + that.createWebView = function() { that.webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); that.webView.setVisible = function(value) {}; that.webView.webEventReceived.connect(that.webEventReceived); - } + }; that.destroyWebView = function() { if (!that.webView) { return; } that.activeParticleEntity = 0; + that.activeParticleProperties = {}; var messageData = { messageType: "particle_close" }; that.webView.emitScriptEvent(JSON.stringify(messageData)); + }; + + function sendActiveParticleProperies() { + that.webView.emitScriptEvent(JSON.stringify({ + messageType: "particle_settings", + currentProperties: that.activeParticleProperties + })); } that.webEventReceived = function(data) { - var data = JSON.parse(data); + data = JSON.parse(data); if (data.messageType === "settings_update") { if (data.updatedSettings.emitOrientation) { data.updatedSettings.emitOrientation = Quat.fromVec3Degrees(data.updatedSettings.emitOrientation); } Entities.editEntity(that.activeParticleEntity, data.updatedSettings); + } else if (data.messageType === "page_loaded") { + sendActiveParticleProperies(); } - } + }; that.setActiveParticleEntity = function(id) { that.activeParticleEntity = id; - } + }; + + that.setActiveParticleProperties = function(properties) { + that.activeParticleProperties = properties; + sendActiveParticleProperies(); + }; return that; }; From 4efdba738283a58b7619bb001a18029c4fb4cb38 Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Thu, 31 May 2018 11:10:54 +1200 Subject: [PATCH 19/62] Remove redundant variable --- scripts/system/edit.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 9285023ed8..05f5e3cb19 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -2362,7 +2362,6 @@ var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); var propertiesTool = new PropertiesTool(); var particleExplorerTool = new ParticleExplorerTool(); -var selectedParticleEntity = 0; var selectedParticleEntityID = null; function selectParticleEntity(entityID) { @@ -2376,7 +2375,6 @@ function selectParticleEntity(entityID) { particleExplorerTool.destroyWebView(); particleExplorerTool.createWebView(); - selectedParticleEntity = entityID; particleExplorerTool.setActiveParticleEntity(entityID); particleExplorerTool.setActiveParticleProperties(properties); @@ -2401,13 +2399,13 @@ entityListTool.webView.webEventReceived.connect(function (data) { var ids = data.entityIds; if (ids.length === 1) { if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") { - if (JSON.stringify(selectedParticleEntity) === JSON.stringify(ids[0])) { + if (JSON.stringify(selectedParticleEntityID) === JSON.stringify(ids[0])) { // This particle entity is already selected, so return return; } // Destroy the old particles web view first } else { - selectedParticleEntity = 0; + selectedParticleEntityID = 0; particleExplorerTool.destroyWebView(); } } From f99b2dd23fd1e0bc81b0d3afa1494f323ba4dac8 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte <cristian.duarte.mb@gmail.com> Date: Thu, 31 May 2018 16:02:41 -0300 Subject: [PATCH 20/62] Android - Fix joystick and view control bug that makes it bounce --- .../src/input-plugins/TouchscreenVirtualPadDevice.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 8d63b82911..32194e1b84 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -350,6 +350,8 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { if (idxMoveStartingPointCandidate != -1) { _moveCurrentTouchId = tPoints[idxMoveStartingPointCandidate].id(); _unusedTouches.erase(_moveCurrentTouchId); + thisPoint.x = tPoints[idxMoveStartingPointCandidate].pos().x(); + thisPoint.y = tPoints[idxMoveStartingPointCandidate].pos().y(); moveTouchBegin(thisPoint); } else { moveTouchEnd(); @@ -359,6 +361,8 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { if (idxViewStartingPointCandidate != -1) { _viewCurrentTouchId = tPoints[idxViewStartingPointCandidate].id(); _unusedTouches.erase(_viewCurrentTouchId); + thisPoint.x = tPoints[idxViewStartingPointCandidate].pos().x(); + thisPoint.y = tPoints[idxViewStartingPointCandidate].pos().y(); viewTouchBegin(thisPoint); } else { viewTouchEnd(); @@ -368,6 +372,8 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { if (idxJumpStartingPointCandidate != -1) { _jumpCurrentTouchId = tPoints[idxJumpStartingPointCandidate].id(); _unusedTouches.erase(_jumpCurrentTouchId); + thisPoint.x = tPoints[idxJumpStartingPointCandidate].pos().x(); + thisPoint.y = tPoints[idxJumpStartingPointCandidate].pos().y(); jumpTouchBegin(thisPoint); } else { if (_jumpHasValidTouch) { @@ -424,6 +430,7 @@ void TouchscreenVirtualPadDevice::moveTouchBegin(glm::vec2 touchPoint) { } else { _moveRefTouchPoint = touchPoint; } + _moveCurrentTouchPoint = touchPoint; _moveHasValidTouch = true; } } From 146f871bec463dcb62f621c741c4eabe36888167 Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Fri, 1 Jun 2018 09:39:39 +1200 Subject: [PATCH 21/62] Don't modify function parameter --- scripts/system/particle_explorer/particleExplorerTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/particle_explorer/particleExplorerTool.js b/scripts/system/particle_explorer/particleExplorerTool.js index 016691e2b6..0543cfc56b 100644 --- a/scripts/system/particle_explorer/particleExplorerTool.js +++ b/scripts/system/particle_explorer/particleExplorerTool.js @@ -45,8 +45,8 @@ ParticleExplorerTool = function() { })); } - that.webEventReceived = function(data) { - data = JSON.parse(data); + that.webEventReceived = function(message) { + var data = JSON.parse(message); if (data.messageType === "settings_update") { if (data.updatedSettings.emitOrientation) { data.updatedSettings.emitOrientation = Quat.fromVec3Degrees(data.updatedSettings.emitOrientation); From 1a128abdfd098625914db983b817d28186425c08 Mon Sep 17 00:00:00 2001 From: Wayne Chen <wayne@highfidelity.io> Date: Thu, 31 May 2018 15:05:33 -0700 Subject: [PATCH 22/62] adding alternate solution. --- ...oggleAdvancedMovementForHandControllers.js | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js index 92d079cff6..92f72f8724 100644 --- a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js +++ b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js @@ -28,7 +28,7 @@ var isDisabled = false; var previousFlyingState = MyAvatar.getFlyingEnabled(); - var previousDrivingState = MyAvatar.useAdvancedMovementControls; + var previousDrivingState = false; function rotate180() { var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.angleAxis(180, { @@ -100,7 +100,7 @@ Controller.enableMapping(DRIVING_MAPPING_NAME); } - if (MyAvatar.getFyingEnabled()) { + if (MyAvatar.getFlyingEnabled()) { Controller.disableMapping(FLYING_MAPPING_NAME); } else { Controller.enableMapping(FLYING_MAPPING_NAME); @@ -171,23 +171,4 @@ Messages.subscribe(HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL); Messages.messageReceived.connect(handleMessage); - function initializeControls() { - if(HMD.active) { - if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) { - if (MyAvatar.useAdvancedMovementControls) { - Controller.disableMapping(DRIVING_MAPPING_NAME); - } else { - Controller.enableMapping(DRIVING_MAPPING_NAME); - } - - if (MyAvatar.getFlyingEnabled()) { - Controller.disableMapping(FLYING_MAPPING_NAME); - } else { - Controller.enableMapping(FLYING_MAPPING_NAME); - } - } - } - } - - initializeControls(); }()); // END LOCAL_SCOPE From 3bda5bf6a0609f23067731cae51210a9e05631e7 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 31 May 2018 17:58:37 -0700 Subject: [PATCH 23/62] added MyAvatar.hasProceduralBlinkFaceMovement and MyAvatar.hasProceduralEyeFaceMovement properties to MyAvatar.h and cpp and HeadData.h --- interface/src/avatar/MyAvatar.cpp | 12 + interface/src/avatar/MyAvatar.h | 12 +- .../src/avatars-renderer/Head.cpp | 62 +-- libraries/avatars/src/AvatarData.h | 2 + libraries/avatars/src/HeadData.h | 23 ++ .../DefaultStylizedFemale_Clothed.fst | 139 +++++++ scripts/developer/facialExpressions.js | 374 ++++++++++++++++++ 7 files changed, 596 insertions(+), 28 deletions(-) create mode 100644 scripts/developer/DefaultStylizedFemale_Clothed.fst create mode 100644 scripts/developer/facialExpressions.js diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e231a42f92..0f6fe88ce9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2094,6 +2094,18 @@ void MyAvatar::setHasScriptedBlendshapes(bool hasScriptedBlendshapes) { _hasScriptedBlendShapes = hasScriptedBlendshapes; } +void MyAvatar::setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement) { + _headData->setHasProceduralBlinkFaceMovement(hasProceduralBlinkFaceMovement); +} + +void MyAvatar::setHasProceduralEyeFaceMovement(bool hasProceduralEyeFaceMovement) { + _headData->setHasProceduralEyeFaceMovement(hasProceduralEyeFaceMovement); +} + +void MyAvatar::setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement) { + _headData->setHasAudioEnabledFaceMovement(hasAudioEnabledFaceMovement); +} + void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 55780b56ac..813dddcc98 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -87,6 +87,8 @@ class MyAvatar : public Avatar { * @property {number} audioListenerModeCustom=2 - The audio listening position is at a the position specified by set by the * <code>customListenPosition</code> and <code>customListenOrientation</code> property values. <em>Read-only.</em> * @property {boolean} hasScriptedBlendshapes=false - Blendshapes will be transmitted over the network if set to true. + * @property {boolean} hasProceduralBlinkFaceMovement=true - procedural blinking will be turned on if set to true. + * @property {boolean} hasProceduralEyeFaceMovement=true - procedural eye movement will be turned on if set to true. * @property {boolean} hasAudioEnabledFaceMovement=true - If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled. * @property {Vec3} customListenPosition=Vec3.ZERO - The listening position used when the <code>audioListenerMode</code> * property value is <code>audioListenerModeCustom</code>. @@ -187,6 +189,8 @@ class MyAvatar : public Avatar { Q_PROPERTY(AudioListenerMode audioListenerModeCamera READ getAudioListenerModeCamera) Q_PROPERTY(AudioListenerMode audioListenerModeCustom READ getAudioListenerModeCustom) Q_PROPERTY(bool hasScriptedBlendshapes READ getHasScriptedBlendshapes WRITE setHasScriptedBlendshapes) + Q_PROPERTY(bool hasProceduralBlinkFaceMovement READ getHasProceduralBlinkFaceMovement WRITE setHasProceduralBlinkFaceMovement) + Q_PROPERTY(bool hasProceduralEyeFaceMovement READ getHasProceduralEyeFaceMovement WRITE setHasProceduralEyeFaceMovement) Q_PROPERTY(bool hasAudioEnabledFaceMovement READ getHasAudioEnabledFaceMovement WRITE setHasAudioEnabledFaceMovement) //TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity) @@ -1347,8 +1351,12 @@ private: bool getShouldRenderLocally() const { return _shouldRender; } void setHasScriptedBlendshapes(bool hasScriptedBlendshapes); bool getHasScriptedBlendshapes() const override { return _hasScriptedBlendShapes; } - void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement) { _hasAudioEnabledFaceMovement = hasAudioEnabledFaceMovement; } - bool getHasAudioEnabledFaceMovement() const override { return _hasAudioEnabledFaceMovement; } + void setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement); + bool getHasProceduralBlinkFaceMovement() const override { return _headData->getHasProceduralBlinkFaceMovement(); } + void setHasProceduralEyeFaceMovement(bool hasProceduralEyeFaceMovement); + bool getHasProceduralEyeFaceMovement() const override { return _headData->getHasProceduralEyeFaceMovement(); } + void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement); + bool getHasAudioEnabledFaceMovement() const override { return _headData->getHasAudioEnabledFaceMovement(); } bool isMyAvatar() const override { return true; } virtual int parseDataFromBuffer(const QByteArray& buffer) override; virtual glm::vec3 getSkeletonPosition() const override; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 256b3bf8a6..b0707922ea 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -100,41 +100,51 @@ void Head::simulate(float deltaTime) { } _browAudioLift = glm::clamp(_browAudioLift *= 0.7f, 0.0f, 1.0f); + const float BLINK_SPEED = 10.0f; const float BLINK_SPEED_VARIABILITY = 1.0f; const float BLINK_START_VARIABILITY = 0.25f; const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; - if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { - // no blinking when brows are raised; blink less with increasing loudness - const float BASE_BLINK_RATE = 15.0f / 60.0f; - const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; - if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * + if (getHasProceduralBlinkFaceMovement()) { + if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { + // no blinking when brows are raised; blink less with increasing loudness + const float BASE_BLINK_RATE = 15.0f / 60.0f; + const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; + if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { - _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; - _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; - if (randFloat() < 0.5f) { - _leftEyeBlink = BLINK_START_VARIABILITY; - } else { - _rightEyeBlink = BLINK_START_VARIABILITY; + _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + if (randFloat() < 0.5f) { + _leftEyeBlink = BLINK_START_VARIABILITY; + } + else { + _rightEyeBlink = BLINK_START_VARIABILITY; + } + } + } + else { + _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); + _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); + + if (_leftEyeBlink == FULLY_CLOSED) { + _leftEyeBlinkVelocity = -BLINK_SPEED; + + } + else if (_leftEyeBlink == FULLY_OPEN) { + _leftEyeBlinkVelocity = 0.0f; + } + if (_rightEyeBlink == FULLY_CLOSED) { + _rightEyeBlinkVelocity = -BLINK_SPEED; + + } + else if (_rightEyeBlink == FULLY_OPEN) { + _rightEyeBlinkVelocity = 0.0f; } } } else { - _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); - _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); - - if (_leftEyeBlink == FULLY_CLOSED) { - _leftEyeBlinkVelocity = -BLINK_SPEED; - - } else if (_leftEyeBlink == FULLY_OPEN) { - _leftEyeBlinkVelocity = 0.0f; - } - if (_rightEyeBlink == FULLY_CLOSED) { - _rightEyeBlinkVelocity = -BLINK_SPEED; - - } else if (_rightEyeBlink == FULLY_OPEN) { - _rightEyeBlinkVelocity = 0.0f; - } + _rightEyeBlink = FULLY_OPEN; + _leftEyeBlink = FULLY_OPEN; } // use data to update fake Faceshift blendshape coefficients diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 568c48dd62..2d8ee52ea1 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -502,6 +502,8 @@ public: float getDomainLimitedScale() const; virtual bool getHasScriptedBlendshapes() const { return false; } + virtual bool getHasProceduralBlinkFaceMovement() const { return true; } + virtual bool getHasProceduralEyeFaceMovement() const { return true; } virtual bool getHasAudioEnabledFaceMovement() const { return false; } /**jsdoc diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index bcc2cacde5..f8eca0915e 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -69,6 +69,24 @@ public: } bool lookAtPositionChangedSince(quint64 time) { return _lookAtPositionChanged >= time; } + bool getHasProceduralEyeFaceMovement() const { return _hasProceduralEyeFaceMovement; } + + void setHasProceduralEyeFaceMovement(const bool hasProceduralEyeFaceMovement) { + _hasProceduralEyeFaceMovement = hasProceduralEyeFaceMovement; + } + + bool getHasProceduralBlinkFaceMovement() const { return _hasProceduralBlinkFaceMovement; } + + void setHasProceduralBlinkFaceMovement(const bool hasProceduralBlinkFaceMovement) { + _hasProceduralBlinkFaceMovement = hasProceduralBlinkFaceMovement; + } + + bool getHasAudioEnabledFaceMovement() const { return _hasAudioEnabledFaceMovement; } + + void setHasAudioEnabledFaceMovement(const bool hasAudioEnabledFaceMovement) { + _hasAudioEnabledFaceMovement = hasAudioEnabledFaceMovement; + } + friend class AvatarData; QJsonObject toJson() const; @@ -83,6 +101,11 @@ protected: glm::vec3 _lookAtPosition; quint64 _lookAtPositionChanged { 0 }; + //std::atomic<bool> _hasProceduralBlinkFaceMovement{ true }; + //std::atomic<bool> _hasProceduralEyeFaceMovement{ true }; + bool _hasAudioEnabledFaceMovement { true }; + bool _hasProceduralBlinkFaceMovement{ true }; + bool _hasProceduralEyeFaceMovement{ true }; bool _isFaceTrackerConnected { false }; bool _isEyeTrackerConnected { false }; float _leftEyeBlink { 0.0f }; diff --git a/scripts/developer/DefaultStylizedFemale_Clothed.fst b/scripts/developer/DefaultStylizedFemale_Clothed.fst new file mode 100644 index 0000000000..3e46d6a15c --- /dev/null +++ b/scripts/developer/DefaultStylizedFemale_Clothed.fst @@ -0,0 +1,139 @@ +name = DefaultStylizedFemale_Clothed +type = body+head +scale = 1 +filename = DefaultStylizedFemale_Clothed/DefaultStylizedFemale_Clothed.fbx +texdir = DefaultStylizedFemale_Clothed/textures +joint = jointLean = Spine +joint = jointRightHand = RightHand +joint = jointEyeLeft = LeftEye +joint = jointHead = HeadTop_End +joint = jointNeck = Neck +joint = jointRoot = Hips +joint = jointEyeRight = RightEye +joint = jointLeftHand = LeftHand +freeJoint = LeftArm +freeJoint = LeftForeArm +freeJoint = RightArm +freeJoint = RightForeArm +bs = EyeBlink_L = Blink_Left = 1 +bs = Sneer = Squint_Right = 0.5 +bs = Sneer = Squint_Left = 0.5 +bs = Sneer = NoseScrunch_Right = 0.75 +bs = Sneer = NoseScrunch_Left = 0.75 +bs = ChinLowerRaise = Jaw_Up = 1 +bs = EyeSquint_R = Squint_Right = 1 +bs = MouthSmile_R = Smile_Right = 1 +bs = ChinUpperRaise = UpperLipUp_Right = 0.5 +bs = ChinUpperRaise = UpperLipUp_Left = 0.5 +bs = LipsLowerOpen = LowerLipOut = 1 +bs = LipsLowerDown = LowerLipDown_Right = 0.7 +bs = LipsLowerDown = LowerLipDown_Left = 0.7 +bs = BrowsU_L = BrowsUp_Left = 1 +bs = MouthRight = Midmouth_Right = 1 +bs = MouthDimple_R = Smile_Right = 0.25 +bs = LipsPucker = MouthNarrow_Right = 1 +bs = LipsPucker = MouthNarrow_Left = 1 +bs = Puff = CheekPuff_Right = 1 +bs = Puff = CheekPuff_Left = 1 +bs = JawFwd = JawForeward = 1 +bs = BrowsD_L = BrowsDown_Left = 1 +bs = LipsFunnel = TongueUp = 1 +bs = LipsFunnel = MouthWhistle_NarrowAdjust_Right = 0.5 +bs = LipsFunnel = MouthWhistle_NarrowAdjust_Left = 0.5 +bs = LipsFunnel = MouthNarrow_Right = 1 +bs = LipsFunnel = MouthNarrow_Left = 1 +bs = LipsFunnel = Jaw_Down = 0.36 +bs = LipsFunnel = JawForeward = 0.39 +bs = LipsUpperOpen = UpperLipOut = 1 +bs = EyeSquint_L = Squint_Left = 1 +bs = MouthDimple_L = Smile_Left = 0.25 +bs = LipsLowerClose = LowerLipIn = 1 +bs = MouthFrown_R = Frown_Right = 1 +bs = MouthFrown_L = Frown_Left = 1 +bs = BrowsU_R = BrowsUp_Right = 1 +bs = JawOpen = MouthOpen = 0.7 +bs = JawRight = Jaw_Right = 1 +bs = MouthLeft = Midmouth_Left = 1 +bs = BrowsU_C = BrowsUp_Right = 1 +bs = BrowsU_C = BrowsUp_Left = 1 +bs = LipsUpperUp = UpperLipUp_Right = 0.7 +bs = LipsUpperUp = UpperLipUp_Left = 0.7 +bs = EyeBlink_R = Blink_Right = 1 +bs = EyeOpen_R = EyesWide_Right = 1 +bs = LipsUpperClose = UpperLipIn = 1 +bs = MouthSmile_L = Smile_Left = 1 +bs = EyeOpen_L = EyesWide_Left = 1 +bs = JawLeft = JawRotateY_Left = 0.5 +bs = BrowsD_R = BrowsDown_Right = 1 +jointIndex = RightHandThumb4 = 21 +jointIndex = Neck = 62 +jointIndex = LeftHandIndex4 = 57 +jointIndex = Body = 71 +jointIndex = LeftHandIndex1 = 54 +jointIndex = RightHand = 17 +jointIndex = RightHandMiddle1 = 26 +jointIndex = Spine = 11 +jointIndex = RightHandRing2 = 31 +jointIndex = RightArm = 15 +jointIndex = RightHandPinky2 = 35 +jointIndex = LeftToeBase = 9 +jointIndex = RightHandIndex3 = 24 +jointIndex = RightHandRing1 = 30 +jointIndex = RightHandPinky1 = 34 +jointIndex = RightEye = 66 +jointIndex = LeftHandRing4 = 49 +jointIndex = LeftHandRing2 = 47 +jointIndex = RightHandMiddle2 = 27 +jointIndex = Head = 63 +jointIndex = LeftHandMiddle4 = 53 +jointIndex = LeftLeg = 7 +jointIndex = LeftHandPinky2 = 43 +jointIndex = LeftHandThumb1 = 58 +jointIndex = LeftHandPinky4 = 45 +jointIndex = RightHandIndex1 = 22 +jointIndex = Tops = 67 +jointIndex = Hips = 0 +jointIndex = LeftUpLeg = 6 +jointIndex = RightShoulder = 14 +jointIndex = Spine2 = 13 +jointIndex = RightHandRing4 = 33 +jointIndex = RightHandThumb3 = 20 +jointIndex = RightHandIndex4 = 25 +jointIndex = LeftFoot = 8 +jointIndex = LeftHandRing3 = 48 +jointIndex = LeftHand = 41 +jointIndex = LeftForeArm = 40 +jointIndex = LeftToe_End = 10 +jointIndex = Bottoms = 68 +jointIndex = RightFoot = 3 +jointIndex = LeftHandMiddle2 = 51 +jointIndex = LeftHandThumb3 = 60 +jointIndex = RightHandPinky3 = 36 +jointIndex = LeftEye = 65 +jointIndex = LeftHandIndex2 = 55 +jointIndex = RightHandIndex2 = 23 +jointIndex = LeftHandPinky1 = 42 +jointIndex = LeftHandMiddle3 = 52 +jointIndex = RightHandMiddle4 = 29 +jointIndex = LeftHandThumb2 = 59 +jointIndex = Shoes = 69 +jointIndex = RightHandThumb1 = 18 +jointIndex = RightToe_End = 5 +jointIndex = RightHandThumb2 = 19 +jointIndex = RightUpLeg = 1 +jointIndex = RightLeg = 2 +jointIndex = LeftHandMiddle1 = 50 +jointIndex = LeftHandIndex3 = 56 +jointIndex = LeftHandThumb4 = 61 +jointIndex = RightHandRing3 = 32 +jointIndex = Hair = 70 +jointIndex = Spine1 = 12 +jointIndex = LeftHandRing1 = 46 +jointIndex = LeftArm = 39 +jointIndex = LeftShoulder = 38 +jointIndex = RightForeArm = 16 +jointIndex = HeadTop_End = 64 +jointIndex = RightHandPinky4 = 37 +jointIndex = LeftHandPinky3 = 44 +jointIndex = RightToeBase = 4 +jointIndex = RightHandMiddle3 = 28 diff --git a/scripts/developer/facialExpressions.js b/scripts/developer/facialExpressions.js new file mode 100644 index 0000000000..84e3966c4a --- /dev/null +++ b/scripts/developer/facialExpressions.js @@ -0,0 +1,374 @@ +// +// facialExpressions.js +// A script to set different emotions using blend shapes +// +// Author: Elisa Lupin-Jimenez +// Copyright High Fidelity 2018 +// +// Licensed under the Apache 2.0 License +// See accompanying license file or http://apache.org/ +// +// All assets are under CC Attribution Non-Commerical +// http://creativecommons.org/licenses/ +// + +(function() { + + var TABLET_BUTTON_NAME = "EMOTIONS"; + // TODO: ADD HTML LANDING PAGE + + var TRANSITION_TIME_SECONDS = 0.25; + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var icon = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/icons/emoji-i.svg"; + var activeIcon = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/icons/emoji-a.svg"; + var isActive = true; + + var controllerMappingName; + var controllerMapping; + + var tabletButton = tablet.addButton({ + icon: icon, + activeIcon: activeIcon, + text: TABLET_BUTTON_NAME, + isActive: true + }); + + var toggle = function() { + isActive = !isActive; + tabletButton.editProperties({isActive: isActive}); + if (isActive) { + Controller.enableMapping(controllerMappingName); + } else { + setEmotion(DEFAULT); + Controller.disableMapping(controllerMappingName); + } + }; + + tabletButton.clicked.connect(toggle); + + var DEFAULT = { + "EyeOpen_L": 0.00, + "EyeOpen_R": 0.00, + "EyeBlink_L": 0.00, + "EyeBlink_R": 0.00, + "EyeSquint_L": 0.00, + "EyeSquint_R": 0.00, + "BrowsD_L": 0.00, + "BrowsD_R": 0.00, + "BrowsU_L": 0.00, + "BrowsU_C": 0.00, + "JawOpen": 0.00, + "JawFwd": 0.00, + "MouthFrown_L": 0.00, + "MouthFrown_R": 0.00, + "MouthSmile_L": 0.00, + "MouthSmile_R": 0.00, + "MouthDimple_L": 0.00, + "MouthDimple_R": 0.00, + "LipsUpperClose": 0.00, + "LipsLowerClose": 0.00, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.00, + "Sneer": 0.00, + "Puff": 0.00 + }; + + var SMILE = { + "EyeOpen_L": 0.00, + "EyeOpen_R": 0.00, + "EyeBlink_L": 0.30, + "EyeBlink_R": 0.30, + "EyeSquint_L": 0.90, + "EyeSquint_R": 0.90, + "BrowsD_L": 1.00, + "BrowsD_R": 1.00, + "BrowsU_L": 0.00, + "BrowsU_C": 0.00, + "JawOpen": 0.00, + "JawFwd": 0.00, + "MouthFrown_L": 0.00, + "MouthFrown_R": 0.00, + "MouthSmile_L": 1.00, + "MouthSmile_R": 1.00, + "MouthDimple_L": 1.00, + "MouthDimple_R": 1.00, + "LipsUpperClose": 0.40, + "LipsLowerClose": 0.30, + "LipsLowerOpen": 0.25, + "ChinUpperRaise": 0.35, + "Sneer": 0.00, + "Puff": 0.00 + }; + + var LAUGH = { + "EyeOpen_L": 0.00, + "EyeOpen_R": 0.00, + "EyeBlink_L": 0.45, + "EyeBlink_R": 0.45, + "EyeSquint_L": 0.75, + "EyeSquint_R": 0.75, + "BrowsD_L": 0.00, + "BrowsD_R": 0.00, + "BrowsU_L": 0.00, + "BrowsU_C": 0.50, + "JawOpen": 0.50, + "JawFwd": 0.00, + "MouthFrown_L": 0.00, + "MouthFrown_R": 0.00, + "MouthSmile_L": 1.00, + "MouthSmile_R": 1.00, + "MouthDimple_L": 1.00, + "MouthDimple_R": 1.00, + "LipsUpperClose": 0.00, + "LipsLowerClose": 0.00, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.30, + "Sneer": 1.00, + "Puff": 0.30 + }; + + var FLIRT = { + "EyeOpen_L": 0.00, + "EyeOpen_R": 0.00, + "EyeBlink_L": 0.50, + "EyeBlink_R": 0.50, + "EyeSquint_L": 0.25, + "EyeSquint_R": 0.25, + "BrowsD_L": 0.00, + "BrowsD_R": 1.00, + "BrowsU_L": 0.55, + "BrowsU_C": 0.00, + "JawOpen": 0.00, + "JawFwd": 0.00, + "MouthFrown_L": 0.00, + "MouthFrown_R": 0.00, + "MouthSmile_L": 0.50, + "MouthSmile_R": 0.00, + "MouthDimple_L": 1.00, + "MouthDimple_R": 1.00, + "LipsUpperClose": 0.00, + "LipsLowerClose": 0.00, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.00, + "Sneer": 0.00, + "Puff": 0.00 + }; + + var SAD = { + "EyeOpen_L": 0.00, + "EyeOpen_R": 0.00, + "EyeBlink_L": 0.30, + "EyeBlink_R": 0.30, + "EyeSquint_L": 0.30, + "EyeSquint_R": 0.30, + "BrowsD_L": 0.00, + "BrowsD_R": 0.00, + "BrowsU_L": 0.00, + "BrowsU_C": 0.50, + "JawOpen": 0.00, + "JawFwd": 0.80, + "MouthFrown_L": 0.80, + "MouthFrown_R": 0.80, + "MouthSmile_L": 0.00, + "MouthSmile_R": 0.00, + "MouthDimple_L": 0.00, + "MouthDimple_R": 0.00, + "LipsUpperClose": 0.00, + "LipsLowerClose": 0.50, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.00, + "Sneer": 0.00, + "Puff": 0.00 + }; + + var ANGRY = { + "EyeOpen_L": 1.00, + "EyeOpen_R": 1.00, + "EyeBlink_L": 0.00, + "EyeBlink_R": 0.00, + "EyeSquint_L": 1.00, + "EyeSquint_R": 1.00, + "BrowsD_L": 1.00, + "BrowsD_R": 1.00, + "BrowsU_L": 0.00, + "BrowsU_C": 0.00, + "JawOpen": 0.00, + "JawFwd": 0.00, + "MouthFrown_L": 0.50, + "MouthFrown_R": 0.50, + "MouthSmile_L": 0.00, + "MouthSmile_R": 0.00, + "MouthDimple_L": 0.00, + "MouthDimple_R": 0.00, + "LipsUpperClose": 0.50, + "LipsLowerClose": 0.50, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.00, + "Sneer": 0.50, + "Puff": 0.00 + }; + + var FEAR = { + "EyeOpen_L": 1.00, + "EyeOpen_R": 1.00, + "EyeBlink_L": 0.00, + "EyeBlink_R": 0.00, + "EyeSquint_L": 0.00, + "EyeSquint_R": 0.00, + "BrowsD_L": 0.00, + "BrowsD_R": 0.00, + "BrowsU_L": 0.00, + "BrowsU_C": 1.00, + "JawOpen": 0.15, + "JawFwd": 0.00, + "MouthFrown_L": 0.30, + "MouthFrown_R": 0.30, + "MouthSmile_L": 0.00, + "MouthSmile_R": 0.00, + "MouthDimple_L": 0.00, + "MouthDimple_R": 0.00, + "LipsUpperClose": 0.00, + "LipsLowerClose": 0.00, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.00, + "Sneer": 0.00, + "Puff": 0.00 + }; + + var DISGUST = { + "EyeOpen_L": 0.00, + "EyeOpen_R": 0.00, + "EyeBlink_L": 0.25, + "EyeBlink_R": 0.25, + "EyeSquint_L": 1.00, + "EyeSquint_R": 1.00, + "BrowsD_L": 1.00, + "BrowsD_R": 1.00, + "BrowsU_L": 0.00, + "BrowsU_C": 0.00, + "JawOpen": 0.00, + "JawFwd": 0.00, + "MouthFrown_L": 1.00, + "MouthFrown_R": 1.00, + "MouthSmile_L": 0.00, + "MouthSmile_R": 0.00, + "MouthDimple_L": 0.00, + "MouthDimple_R": 0.00, + "LipsUpperClose": 0.00, + "LipsLowerClose": 0.75, + "LipsLowerOpen": 0.00, + "ChinUpperRaise": 0.75, + "Sneer": 1.00, + "Puff": 0.00 + }; + + + function mixValue(valueA, valueB, percentage) { + return valueA + ((valueB - valueA) * percentage); + } + + var lastEmotionUsed = DEFAULT; + var emotion = DEFAULT; + var isChangingEmotion = false; + var changingEmotionPercentage = 0.0; + + Script.update.connect(function(deltaTime) { + if (!isChangingEmotion) { + return; + } + changingEmotionPercentage += deltaTime / TRANSITION_TIME_SECONDS; + if (changingEmotionPercentage >= 1.0) { + changingEmotionPercentage = 1.0; + isChangingEmotion = false; + if (emotion === DEFAULT) { + MyAvatar.hasScriptedBlendshapes = false; + } + } + for (var blendshape in emotion) { + MyAvatar.setBlendshape(blendshape, + mixValue(lastEmotionUsed[blendshape], emotion[blendshape], changingEmotionPercentage)); + } + }); + + function setEmotion(currentEmotion) { + if (emotion !== lastEmotionUsed) { + lastEmotionUsed = emotion; + } + if (currentEmotion !== lastEmotionUsed) { + changingEmotionPercentage = 0.0; + emotion = currentEmotion; + isChangingEmotion = true; + MyAvatar.hasScriptedBlendshapes = true; + } + } + + + controllerMappingName = 'Hifi-FacialExpressions-Mapping'; + controllerMapping = Controller.newMapping(controllerMappingName); + + controllerMapping.from(Controller.Hardware.Keyboard.H).to(function(value) { + if (value !== 0) { + setEmotion(SMILE); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.J).to(function(value) { + if (value !== 0) { + setEmotion(LAUGH); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.K).to(function(value) { + if (value !== 0) { + setEmotion(FLIRT); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.L).to(function(value) { + if (value !== 0) { + setEmotion(SAD); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.V).to(function(value) { + if (value !== 0) { + setEmotion(ANGRY); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.B).to(function(value) { + if (value !== 0) { + setEmotion(FEAR); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.M).to(function(value) { + if (value !== 0) { + setEmotion(DISGUST); + } + }); + + controllerMapping.from(Controller.Hardware.Keyboard.N).to(function(value) { + if (value !== 0) { + setEmotion(DEFAULT); + } + }); + + Controller.enableMapping(controllerMappingName); + + Script.scriptEnding.connect(function() { + tabletButton.clicked.disconnect(toggle); + tablet.removeButton(tabletButton); + Controller.disableMapping(controllerMappingName); + + if (emotion !== DEFAULT || isChangingEmotion) { + isChangingEmotion = false; + for (var blendshape in DEFAULT) { + MyAvatar.setBlendshape(blendshape, DEFAULT[blendshape]); + } + MyAvatar.hasScriptedBlendshapes = false; + } + }); + +}()); \ No newline at end of file From 01848fafe0b716872a8dd781c7c7d3f6faacc2ff Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Fri, 1 Jun 2018 11:37:11 -0700 Subject: [PATCH 24/62] made all changes except those to AvatarData toByteArray function also to do: verify that transientBlendshapes are set to 0 in headData simulate when there are blendshapes from script but no face tracker present --- interface/src/avatar/MyHead.cpp | 2 +- .../src/avatars-renderer/Head.cpp | 30 ++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index 44d679f3f8..13d635bdd8 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -51,7 +51,7 @@ void MyHead::simulate(float deltaTime) { _isFaceTrackerConnected = hasActualFaceTrackerConnected || _owningAvatar->getHasScriptedBlendshapes(); if (_isFaceTrackerConnected) { if (hasActualFaceTrackerConnected) { - _transientBlendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } else { _transientBlendshapeCoefficients.fill(0, _blendshapeCoefficients.size()); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index b0707922ea..06b52c8d44 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -148,18 +148,28 @@ void Head::simulate(float deltaTime) { } // use data to update fake Faceshift blendshape coefficients - calculateMouthShapes(deltaTime); + if (getHasAudioEnabledFaceMovement()) { + calculateMouthShapes(deltaTime); + } else { + _audioJawOpen = 0.0f; + _browAudioLift = 0.0f; + _mouth2 = 0.0f; + _mouth3 = 0.0f; + _mouth4 = 0.0f; + _mouthTime = 0.0f; + } FaceTracker::updateFakeCoefficients(_leftEyeBlink, - _rightEyeBlink, - _browAudioLift, - _audioJawOpen, - _mouth2, - _mouth3, - _mouth4, - _transientBlendshapeCoefficients); - - applyEyelidOffset(getOrientation()); + _rightEyeBlink, + _browAudioLift, + _audioJawOpen, + _mouth2, + _mouth3, + _mouth4, + _transientBlendshapeCoefficients); + if (getHasProceduralEyeFaceMovement()) { + applyEyelidOffset(getOrientation()); + } } else { _saccade = glm::vec3(); } From 89c4b1ecdd65747b15b993fe627bcad0e4b880dc Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Fri, 1 Jun 2018 15:00:00 -0300 Subject: [PATCH 25/62] Workaround for android buffer corruption issue --- .../hifiinterface/InterfaceActivity.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index 2165339918..e850ec639b 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -20,6 +20,9 @@ import android.os.Vibrator; import android.view.HapticFeedbackConstants; import android.view.WindowManager; import android.util.Log; + +import org.qtproject.qt5.android.QtLayout; +import org.qtproject.qt5.android.QtSurface; import org.qtproject.qt5.android.bindings.QtActivity; /*import com.google.vr.cardboard.DisplaySynchronizer; @@ -31,6 +34,9 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.view.View; +import android.widget.FrameLayout; + +import java.lang.reflect.Field; public class InterfaceActivity extends QtActivity { @@ -134,6 +140,7 @@ public class InterfaceActivity extends QtActivity { protected void onResume() { super.onResume(); nativeEnterForeground(); + surfacesWorkaround(); //gvrApi.resumeTracking(); } @@ -158,6 +165,31 @@ public class InterfaceActivity extends QtActivity { Log.w("[VR]", "Portrait detected but not in VR mode. Should not happen"); } } + surfacesWorkaround(); + } + + private void surfacesWorkaround() { + FrameLayout fl = findViewById(android.R.id.content); + QtLayout qtLayout = (QtLayout) fl.getChildAt(0); + QtSurface s1 = (QtSurface) qtLayout.getChildAt(0); + QtSurface s2 = (QtSurface) qtLayout.getChildAt(1); + Integer subLayer1 = 0; + Integer subLayer2 = 0; + try { + Field f = s1.getClass().getSuperclass().getDeclaredField("mSubLayer"); + f.setAccessible(true); + subLayer1 = (Integer) f.get(s1); + subLayer2 = (Integer) f.get(s2); + if (subLayer1 < subLayer2) { + s1.setVisibility(View.VISIBLE); + s2.setVisibility(View.INVISIBLE); + } else { + s1.setVisibility(View.INVISIBLE); + s2.setVisibility(View.VISIBLE); + } + } catch (ReflectiveOperationException e) { + Log.e(TAG, "Workaround failed"); + } } public void openUrlInAndroidWebView(String urlString) { From 61953d0070b60d8f0a71748ead97b2cccd0e0204 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Fri, 1 Jun 2018 15:48:57 -0300 Subject: [PATCH 26/62] Fix NullPointerException introduced with the workaround --- .../hifiinterface/InterfaceActivity.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index e850ec639b..da938ab85b 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -170,25 +170,29 @@ public class InterfaceActivity extends QtActivity { private void surfacesWorkaround() { FrameLayout fl = findViewById(android.R.id.content); - QtLayout qtLayout = (QtLayout) fl.getChildAt(0); - QtSurface s1 = (QtSurface) qtLayout.getChildAt(0); - QtSurface s2 = (QtSurface) qtLayout.getChildAt(1); - Integer subLayer1 = 0; - Integer subLayer2 = 0; - try { - Field f = s1.getClass().getSuperclass().getDeclaredField("mSubLayer"); - f.setAccessible(true); - subLayer1 = (Integer) f.get(s1); - subLayer2 = (Integer) f.get(s2); - if (subLayer1 < subLayer2) { - s1.setVisibility(View.VISIBLE); - s2.setVisibility(View.INVISIBLE); - } else { - s1.setVisibility(View.INVISIBLE); - s2.setVisibility(View.VISIBLE); + if (fl.getChildCount() > 0) { + QtLayout qtLayout = (QtLayout) fl.getChildAt(0); + if (qtLayout.getChildCount() > 1) { + QtSurface s1 = (QtSurface) qtLayout.getChildAt(0); + QtSurface s2 = (QtSurface) qtLayout.getChildAt(1); + Integer subLayer1 = 0; + Integer subLayer2 = 0; + try { + Field f = s1.getClass().getSuperclass().getDeclaredField("mSubLayer"); + f.setAccessible(true); + subLayer1 = (Integer) f.get(s1); + subLayer2 = (Integer) f.get(s2); + if (subLayer1 < subLayer2) { + s1.setVisibility(View.VISIBLE); + s2.setVisibility(View.INVISIBLE); + } else { + s1.setVisibility(View.INVISIBLE); + s2.setVisibility(View.VISIBLE); + } + } catch (ReflectiveOperationException e) { + Log.e(TAG, "Workaround failed"); + } } - } catch (ReflectiveOperationException e) { - Log.e(TAG, "Workaround failed"); } } From 44027f74fc4558b4d67f546af70d3f9611590f3b Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Fri, 1 Jun 2018 17:11:14 -0300 Subject: [PATCH 27/62] Workaround for android < Oreo --- .../io/highfidelity/hifiinterface/InterfaceActivity.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index da938ab85b..28acc77609 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -14,6 +14,7 @@ package io.highfidelity.hifiinterface; import android.content.Intent; import android.content.res.AssetManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Vibrator; @@ -178,7 +179,13 @@ public class InterfaceActivity extends QtActivity { Integer subLayer1 = 0; Integer subLayer2 = 0; try { - Field f = s1.getClass().getSuperclass().getDeclaredField("mSubLayer"); + String field; + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + field = "mSubLayer"; + } else { + field = "mWindowType"; + } + Field f = s1.getClass().getSuperclass().getDeclaredField(field); f.setAccessible(true); subLayer1 = (Integer) f.get(s1); subLayer2 = (Integer) f.get(s2); From 2879eeb687d4885cf220799bbade8fcd3960aaf1 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Fri, 1 Jun 2018 17:18:48 -0700 Subject: [PATCH 28/62] added flags for procedural face movement AvatarData.cpp toByteArray and parseDataFromBuffer --- libraries/avatars/src/AvatarData.cpp | 54 ++++++++++++++++++++-------- libraries/avatars/src/AvatarData.h | 7 ++-- libraries/shared/src/SharedUtil.cpp | 17 ++++++--- libraries/shared/src/SharedUtil.h | 6 ++-- 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 649460d6c7..247fc2a76a 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -308,7 +308,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE + - (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) + + (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getBlendshapeCoefficients().size()) : 0) + (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0) + (hasJointDefaultPoseFlags ? AvatarDataPacket::maxJointDefaultPoseFlagsSize(_jointData.size()) : 0); @@ -443,7 +443,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent auto startSection = destinationBuffer; auto data = reinterpret_cast<AvatarDataPacket::AdditionalFlags*>(destinationBuffer); - uint8_t flags { 0 }; + uint16_t flags { 0 }; setSemiNibbleAt(flags, KEY_STATE_START_BIT, _keyState); @@ -451,20 +451,33 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent bool isFingerPointing = _handState & IS_FINGER_POINTING_FLAG; setSemiNibbleAt(flags, HAND_STATE_START_BIT, _handState & ~IS_FINGER_POINTING_FLAG); if (isFingerPointing) { - setAtBit(flags, HAND_STATE_FINGER_POINTING_BIT); + setAtBit16(flags, HAND_STATE_FINGER_POINTING_BIT); } // face tracker state if (_headData->_isFaceTrackerConnected) { - setAtBit(flags, IS_FACE_TRACKER_CONNECTED); + setAtBit16(flags, IS_FACE_TRACKER_CONNECTED); } // eye tracker state if (_headData->_isEyeTrackerConnected) { - setAtBit(flags, IS_EYE_TRACKER_CONNECTED); + setAtBit16(flags, IS_EYE_TRACKER_CONNECTED); } // referential state if (!parentID.isNull()) { - setAtBit(flags, HAS_REFERENTIAL); + setAtBit16(flags, HAS_REFERENTIAL); } + // audio face movement + if (_headData->getHasAudioEnabledFaceMovement()) { + setAtBit16(flags, AUDIO_ENABLED_FACE_MOVEMENT); + } + // procedural eye face movement + if (_headData->getHasProceduralEyeFaceMovement()) { + setAtBit16(flags, PROCEDURAL_EYE_FACE_MOVEMENT); + } + // procedural blink face movement + if (_headData->getHasProceduralBlinkFaceMovement()) { + setAtBit16(flags, PROCEDURAL_BLINK_FACE_MOVEMENT); + } + data->flags = flags; destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags); @@ -507,7 +520,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (hasFaceTrackerInfo) { auto startSection = destinationBuffer; auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer); - const auto& blendshapeCoefficients = _headData->getSummedBlendshapeCoefficients(); + const auto& blendshapeCoefficients = _headData->getBlendshapeCoefficients(); faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink; faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink; @@ -973,7 +986,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { PACKET_READ_CHECK(AdditionalFlags, sizeof(AvatarDataPacket::AdditionalFlags)); auto data = reinterpret_cast<const AvatarDataPacket::AdditionalFlags*>(sourceBuffer); - uint8_t bitItems = data->flags; + uint16_t bitItems = data->flags; // key state, stored as a semi-nibble in the bitItems auto newKeyState = (KeyState)getSemiNibbleAt(bitItems, KEY_STATE_START_BIT); @@ -981,26 +994,37 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { // hand state, stored as a semi-nibble plus a bit in the bitItems // we store the hand state as well as other items in a shared bitset. The hand state is an octal, but is split // into two sections to maintain backward compatibility. The bits are ordered as such (0-7 left to right). - // +---+-----+-----+--+ - // |x,x|H0,H1|x,x,x|H2| - // +---+-----+-----+--+ + // AA 6/1/18 added three more flags here for procedural audio, blink, and eye saccade enabled + // +---+-----+-----+--+--+--+--+-----+ + // |x,x|H0,H1|x,x,x|H2|Au|Bl|Ey|xxxxx| + // +---+-----+-----+--+--+--+--+-----+ // Hand state - H0,H1,H2 is found in the 3rd, 4th, and 8th bits auto newHandState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) - + (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); + + (oneAtBit16(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); - auto newFaceTrackerConnected = oneAtBit(bitItems, IS_FACE_TRACKER_CONNECTED); - auto newEyeTrackerConnected = oneAtBit(bitItems, IS_EYE_TRACKER_CONNECTED); + auto newFaceTrackerConnected = oneAtBit16(bitItems, IS_FACE_TRACKER_CONNECTED); + auto newEyeTrackerConnected = oneAtBit16(bitItems, IS_EYE_TRACKER_CONNECTED); + + auto newHasAudioEnabledFaceMovement = oneAtBit16(bitItems, AUDIO_ENABLED_FACE_MOVEMENT); + auto newHasProceduralEyeFaceMovement = oneAtBit16(bitItems, PROCEDURAL_EYE_FACE_MOVEMENT); + auto newHasProceduralBlinkFaceMovement = oneAtBit16(bitItems, PROCEDURAL_BLINK_FACE_MOVEMENT); bool keyStateChanged = (_keyState != newKeyState); bool handStateChanged = (_handState != newHandState); bool faceStateChanged = (_headData->_isFaceTrackerConnected != newFaceTrackerConnected); bool eyeStateChanged = (_headData->_isEyeTrackerConnected != newEyeTrackerConnected); - bool somethingChanged = keyStateChanged || handStateChanged || faceStateChanged || eyeStateChanged; + bool audioEnableFaceMovementChanged = (_headData->getHasAudioEnabledFaceMovement() != newHasAudioEnabledFaceMovement); + bool proceduralEyeFaceMovementChanged = (_headData->getHasProceduralEyeFaceMovement() != newHasProceduralEyeFaceMovement); + bool proceduralBlinkFaceMovementChanged = (_headData->getHasProceduralBlinkFaceMovement() != newHasProceduralBlinkFaceMovement); + bool somethingChanged = keyStateChanged || handStateChanged || faceStateChanged || eyeStateChanged || audioEnableFaceMovementChanged || proceduralEyeFaceMovementChanged || proceduralBlinkFaceMovementChanged; _keyState = newKeyState; _handState = newHandState; _headData->_isFaceTrackerConnected = newFaceTrackerConnected; _headData->_isEyeTrackerConnected = newEyeTrackerConnected; + _headData->setHasAudioEnabledFaceMovement(newHasAudioEnabledFaceMovement); + _headData->setHasProceduralEyeFaceMovement(newHasProceduralEyeFaceMovement); + _headData->setHasProceduralBlinkFaceMovement(newHasProceduralBlinkFaceMovement); sourceBuffer += sizeof(AvatarDataPacket::AdditionalFlags); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 2d8ee52ea1..ad304d5796 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -93,6 +93,9 @@ const int IS_FACE_TRACKER_CONNECTED = 4; // 5th bit const int IS_EYE_TRACKER_CONNECTED = 5; // 6th bit (was CHAT_CIRCLING) const int HAS_REFERENTIAL = 6; // 7th bit const int HAND_STATE_FINGER_POINTING_BIT = 7; // 8th bit +const int AUDIO_ENABLED_FACE_MOVEMENT = 8; // 9th bit +const int PROCEDURAL_EYE_FACE_MOVEMENT = 9; // 10th bit +const int PROCEDURAL_BLINK_FACE_MOVEMENT = 10; // 11th bit const char HAND_STATE_NULL = 0; @@ -200,9 +203,9 @@ namespace AvatarDataPacket { static_assert(sizeof(SensorToWorldMatrix) == SENSOR_TO_WORLD_SIZE, "AvatarDataPacket::SensorToWorldMatrix size doesn't match."); PACKED_BEGIN struct AdditionalFlags { - uint8_t flags; // additional flags: hand state, key state, eye tracking + uint16_t flags; // additional flags: hand state, key state, eye tracking } PACKED_END; - const size_t ADDITIONAL_FLAGS_SIZE = 1; + const size_t ADDITIONAL_FLAGS_SIZE = 2; static_assert(sizeof(AdditionalFlags) == ADDITIONAL_FLAGS_SIZE, "AvatarDataPacket::AdditionalFlags size doesn't match."); // only present if HAS_REFERENTIAL flag is set in AvatarInfo.flags diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 7c4a9b6d6c..35aab3fac1 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -297,14 +297,23 @@ void setAtBit(unsigned char& byte, int bitIndex) { byte |= (1 << (7 - bitIndex)); } +bool oneAtBit16(unsigned short word, int bitIndex) { + return (word >> (7 - bitIndex) & 1); +} + +void setAtBit16(unsigned short& word, int bitIndex) { + word |= (1 << (7 - bitIndex)); +} + + void clearAtBit(unsigned char& byte, int bitIndex) { if (oneAtBit(byte, bitIndex)) { byte -= (1 << (7 - bitIndex)); } } -int getSemiNibbleAt(unsigned char byte, int bitIndex) { - return (byte >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 +int getSemiNibbleAt(unsigned short word, int bitIndex) { + return (word >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 } int getNthBit(unsigned char byte, int ordinal) { @@ -326,9 +335,9 @@ int getNthBit(unsigned char byte, int ordinal) { return ERROR_RESULT; } -void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) { +void setSemiNibbleAt(unsigned short& word, int bitIndex, int value) { //assert(value <= 3 && value >= 0); - byte |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 + word |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 } bool isInEnvironment(const char* environment) { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 9875314aa4..db9fff3e93 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -163,9 +163,11 @@ void printVoxelCode(unsigned char* voxelCode); int numberOfOnes(unsigned char byte); bool oneAtBit(unsigned char byte, int bitIndex); void setAtBit(unsigned char& byte, int bitIndex); +bool oneAtBit16(unsigned short word, int bitIndex); +void setAtBit16(unsigned short& word, int bitIndex); void clearAtBit(unsigned char& byte, int bitIndex); -int getSemiNibbleAt(unsigned char byte, int bitIndex); -void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value); +int getSemiNibbleAt(unsigned short word, int bitIndex); +void setSemiNibbleAt(unsigned short& word, int bitIndex, int value); int getNthBit(unsigned char byte, int ordinal); /// determines the bit placement 0-7 of the ordinal set bit From beaea7abe6bcf2f76c0ef24962e3df3c12217980 Mon Sep 17 00:00:00 2001 From: Angus Antley <amantley@googlemail.com> Date: Sat, 2 Jun 2018 14:39:30 +0100 Subject: [PATCH 29/62] changed max face tracker info size to reflect summed coeff --- libraries/avatars/src/AvatarData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 247fc2a76a..4a3967a938 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -308,7 +308,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE + - (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getBlendshapeCoefficients().size()) : 0) + + (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) + (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0) + (hasJointDefaultPoseFlags ? AvatarDataPacket::maxJointDefaultPoseFlagsSize(_jointData.size()) : 0); From 606b6d8947b87f646166d4cd8c0630dc65933330 Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Mon, 4 Jun 2018 09:16:39 -0700 Subject: [PATCH 30/62] fix code standard issue --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 42618796a5..e9de94ac57 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -124,7 +124,7 @@ Menu::Menu() { }); // Edit > Delete - auto deleteAction =addActionToQMenuAndActionHash(editMenu, "Delete", QKeySequence::Delete); + auto deleteAction = addActionToQMenuAndActionHash(editMenu, "Delete", QKeySequence::Delete); connect(deleteAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Delete, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); From 61592cdadac1277e129ec378160c63aa80578586 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Mon, 4 Jun 2018 16:37:47 -0700 Subject: [PATCH 31/62] completed first try at all changes for scripted blendshapes --- interface/src/avatar/MyHead.cpp | 4 +++- libraries/avatars/src/AvatarData.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index 13d635bdd8..8f53522b5a 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -72,7 +72,9 @@ void MyHead::simulate(float deltaTime) { _transientBlendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; _transientBlendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; } - applyEyelidOffset(getFinalOrientationInWorldFrame()); + if (_owningAvatar->getHasProceduralEyeFaceMovement()) { + applyEyelidOffset(getFinalOrientationInWorldFrame()); + } } auto eyeTracker = DependencyManager::get<EyeTracker>(); _isEyeTrackerConnected = eyeTracker->isTracking(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 247fc2a76a..7ae9ba1257 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1102,6 +1102,8 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { int numBytesRead = sourceBuffer - startSection; _faceTrackerRate.increment(numBytesRead); _faceTrackerUpdateRate.increment(); + } else { + _headData->_blendshapeCoefficients.fill(0, _headData->_blendshapeCoefficients.size()); } if (hasJointData) { From f87775c269475158c10c7c28b59025324b1a6dde Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Mon, 4 Jun 2018 14:39:48 -0700 Subject: [PATCH 32/62] Update serverless content to v2 --- cmake/externals/serverless-content/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index aa1c59a86b..81b82e8651 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC68.zip - URL_MD5 a068f74d4045e257cfa7926fe6e38ad5 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC68-v2.zip + URL_MD5 f7d290471baf7f5694c147217b8fc548 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 5132466ca0c4d3f5ac623643f6ee3b707010167b Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Tue, 5 Jun 2018 13:32:29 -0700 Subject: [PATCH 33/62] kept the transient coeff. and sending the blendshapes accross the network. and removed procedural updates to face from myhead.cpp --- interface/src/avatar/MyHead.cpp | 29 +--- .../src/avatars-renderer/Head.cpp | 160 +++++++++--------- 2 files changed, 81 insertions(+), 108 deletions(-) diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index 8f53522b5a..55db478d85 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -50,32 +50,11 @@ void MyHead::simulate(float deltaTime) { const bool hasActualFaceTrackerConnected = faceTracker && !faceTracker->isMuted(); _isFaceTrackerConnected = hasActualFaceTrackerConnected || _owningAvatar->getHasScriptedBlendshapes(); if (_isFaceTrackerConnected) { - if (hasActualFaceTrackerConnected) { - _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - } else { - _transientBlendshapeCoefficients.fill(0, _blendshapeCoefficients.size()); - } - - if (_owningAvatar->getHasAudioEnabledFaceMovement() || (faceTracker && (typeid(*faceTracker) == typeid(DdeFaceTracker)) - && Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth))) { - - calculateMouthShapes(deltaTime); - - const int JAW_OPEN_BLENDSHAPE = 21; - const int MMMM_BLENDSHAPE = 34; - const int FUNNEL_BLENDSHAPE = 40; - const int SMILE_LEFT_BLENDSHAPE = 28; - const int SMILE_RIGHT_BLENDSHAPE = 29; - _transientBlendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; - _transientBlendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; - _transientBlendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; - _transientBlendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; - _transientBlendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; - } - if (_owningAvatar->getHasProceduralEyeFaceMovement()) { - applyEyelidOffset(getFinalOrientationInWorldFrame()); - } + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + } else { + _blendshapeCoefficients.fill(0, _blendshapeCoefficients.size()); } + auto eyeTracker = DependencyManager::get<EyeTracker>(); _isEyeTrackerConnected = eyeTracker->isTracking(); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 06b52c8d44..81b58c7aa1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -58,24 +58,32 @@ void Head::simulate(float deltaTime) { _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); } - if (!_isFaceTrackerConnected) { - if (!_isEyeTrackerConnected) { - // Update eye saccades - const float AVERAGE_MICROSACCADE_INTERVAL = 1.0f; - const float AVERAGE_SACCADE_INTERVAL = 6.0f; - const float MICROSACCADE_MAGNITUDE = 0.002f; - const float SACCADE_MAGNITUDE = 0.04f; - const float NOMINAL_FRAME_RATE = 60.0f; + //if (!_isFaceTrackerConnected) { + if (!_isEyeTrackerConnected) { + // Update eye saccades + const float AVERAGE_MICROSACCADE_INTERVAL = 1.0f; + const float AVERAGE_SACCADE_INTERVAL = 6.0f; + const float MICROSACCADE_MAGNITUDE = 0.002f; + const float SACCADE_MAGNITUDE = 0.04f; + const float NOMINAL_FRAME_RATE = 60.0f; - if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) { - _saccadeTarget = MICROSACCADE_MAGNITUDE * randVector(); - } else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) { - _saccadeTarget = SACCADE_MAGNITUDE * randVector(); - } - _saccade += (_saccadeTarget - _saccade) * pow(0.5f, NOMINAL_FRAME_RATE * deltaTime); - } else { - _saccade = glm::vec3(); + if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) { + _saccadeTarget = MICROSACCADE_MAGNITUDE * randVector(); + } else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) { + _saccadeTarget = SACCADE_MAGNITUDE * randVector(); } + _saccade += (_saccadeTarget - _saccade) * pow(0.5f, NOMINAL_FRAME_RATE * deltaTime); + } else { + _saccade = glm::vec3(); + } + + + const float BLINK_SPEED = 10.0f; + const float BLINK_SPEED_VARIABILITY = 1.0f; + const float BLINK_START_VARIABILITY = 0.25f; + const float FULLY_OPEN = 0.0f; + const float FULLY_CLOSED = 1.0f; + if (getHasProceduralBlinkFaceMovement()) { // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; @@ -88,26 +96,7 @@ void Head::simulate(float deltaTime) { forceBlink = true; } - // Update audio attack data for facial animation (eyebrows and mouth) - float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz - _audioAttack = audioAttackAveragingRate * _audioAttack + - (1.0f - audioAttackAveragingRate) * fabs((audioLoudness - _longTermAverageLoudness) - _lastLoudness); - _lastLoudness = (audioLoudness - _longTermAverageLoudness); - - const float BROW_LIFT_THRESHOLD = 100.0f; - if (_audioAttack > BROW_LIFT_THRESHOLD) { - _browAudioLift += sqrtf(_audioAttack) * 0.01f; - } - _browAudioLift = glm::clamp(_browAudioLift *= 0.7f, 0.0f, 1.0f); - - - const float BLINK_SPEED = 10.0f; - const float BLINK_SPEED_VARIABILITY = 1.0f; - const float BLINK_START_VARIABILITY = 0.25f; - const float FULLY_OPEN = 0.0f; - const float FULLY_CLOSED = 1.0f; - if (getHasProceduralBlinkFaceMovement()) { - if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { + if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { // no blinking when brows are raised; blink less with increasing loudness const float BASE_BLINK_RATE = 15.0f / 60.0f; const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; @@ -117,63 +106,68 @@ void Head::simulate(float deltaTime) { _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; if (randFloat() < 0.5f) { _leftEyeBlink = BLINK_START_VARIABILITY; - } - else { + } else { _rightEyeBlink = BLINK_START_VARIABILITY; } } - } - else { - _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); - _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); - - if (_leftEyeBlink == FULLY_CLOSED) { - _leftEyeBlinkVelocity = -BLINK_SPEED; - - } - else if (_leftEyeBlink == FULLY_OPEN) { - _leftEyeBlinkVelocity = 0.0f; - } - if (_rightEyeBlink == FULLY_CLOSED) { - _rightEyeBlinkVelocity = -BLINK_SPEED; - - } - else if (_rightEyeBlink == FULLY_OPEN) { - _rightEyeBlinkVelocity = 0.0f; - } - } } else { - _rightEyeBlink = FULLY_OPEN; - _leftEyeBlink = FULLY_OPEN; - } + _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); + _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); - // use data to update fake Faceshift blendshape coefficients - if (getHasAudioEnabledFaceMovement()) { - calculateMouthShapes(deltaTime); - } else { - _audioJawOpen = 0.0f; - _browAudioLift = 0.0f; - _mouth2 = 0.0f; - _mouth3 = 0.0f; - _mouth4 = 0.0f; - _mouthTime = 0.0f; - } - FaceTracker::updateFakeCoefficients(_leftEyeBlink, - _rightEyeBlink, - _browAudioLift, - _audioJawOpen, - _mouth2, - _mouth3, - _mouth4, - _transientBlendshapeCoefficients); + if (_leftEyeBlink == FULLY_CLOSED) { + _leftEyeBlinkVelocity = -BLINK_SPEED; - if (getHasProceduralEyeFaceMovement()) { - applyEyelidOffset(getOrientation()); + } else if (_leftEyeBlink == FULLY_OPEN) { + _leftEyeBlinkVelocity = 0.0f; + } + if (_rightEyeBlink == FULLY_CLOSED) { + _rightEyeBlinkVelocity = -BLINK_SPEED; + + } else if (_rightEyeBlink == FULLY_OPEN) { + _rightEyeBlinkVelocity = 0.0f; + } } } else { - _saccade = glm::vec3(); + _rightEyeBlink = FULLY_OPEN; + _leftEyeBlink = FULLY_OPEN; } + // use data to update fake Faceshift blendshape coefficients + if (getHasAudioEnabledFaceMovement()) { + // Update audio attack data for facial animation (eyebrows and mouth) + float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz + _audioAttack = audioAttackAveragingRate * _audioAttack + + (1.0f - audioAttackAveragingRate) * fabs((audioLoudness - _longTermAverageLoudness) - _lastLoudness); + _lastLoudness = (audioLoudness - _longTermAverageLoudness); + const float BROW_LIFT_THRESHOLD = 100.0f; + if (_audioAttack > BROW_LIFT_THRESHOLD) { + _browAudioLift += sqrtf(_audioAttack) * 0.01f; + } + _browAudioLift = glm::clamp(_browAudioLift *= 0.7f, 0.0f, 1.0f); + calculateMouthShapes(deltaTime); + + } else { + _audioJawOpen = 0.0f; + _browAudioLift = 0.0f; + _mouth2 = 0.0f; + _mouth3 = 0.0f; + _mouth4 = 0.0f; + _mouthTime = 0.0f; + } + + FaceTracker::updateFakeCoefficients(_leftEyeBlink, + _rightEyeBlink, + _browAudioLift, + _audioJawOpen, + _mouth2, + _mouth3, + _mouth4, + _transientBlendshapeCoefficients); + + if (getHasProceduralEyeFaceMovement()) { + applyEyelidOffset(getOrientation()); + } + _leftEyePosition = _rightEyePosition = getPosition(); if (_owningAvatar) { auto skeletonModel = static_cast<Avatar*>(_owningAvatar)->getSkeletonModel(); From f21431ca88c17020f09932e9ee2fb9985029d4b9 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Tue, 5 Jun 2018 16:33:28 -0700 Subject: [PATCH 34/62] added check for the actual face tracker in MyHead.cpp to prevent crash --- interface/src/avatar/MyHead.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index 55db478d85..eb365c20fb 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -50,9 +50,9 @@ void MyHead::simulate(float deltaTime) { const bool hasActualFaceTrackerConnected = faceTracker && !faceTracker->isMuted(); _isFaceTrackerConnected = hasActualFaceTrackerConnected || _owningAvatar->getHasScriptedBlendshapes(); if (_isFaceTrackerConnected) { - _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - } else { - _blendshapeCoefficients.fill(0, _blendshapeCoefficients.size()); + if (hasActualFaceTrackerConnected) { + _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); + } } auto eyeTracker = DependencyManager::get<EyeTracker>(); From 0c879d85b5d89b00ff3daf4bbed090e64bd97381 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Tue, 5 Jun 2018 17:33:32 -0700 Subject: [PATCH 35/62] added print statements and removed summed coeff from avatarData.cpp --- libraries/avatars-renderer/src/avatars-renderer/Head.cpp | 5 ++++- libraries/avatars/src/AvatarData.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 81b58c7aa1..39b50b9255 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -20,6 +20,7 @@ #include <trackers/FaceTracker.h> #include <trackers/EyeTracker.h> #include <Rig.h> +#include "Logging.h" #include "Avatar.h" @@ -84,7 +85,7 @@ void Head::simulate(float deltaTime) { const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; if (getHasProceduralBlinkFaceMovement()) { - + qCDebug(avatars_renderer) << "in the blink code"; // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; const float TALKING_LOUDNESS = 100.0f; @@ -134,6 +135,7 @@ void Head::simulate(float deltaTime) { // use data to update fake Faceshift blendshape coefficients if (getHasAudioEnabledFaceMovement()) { + qCDebug(avatars_renderer) << "in the audio face code"; // Update audio attack data for facial animation (eyebrows and mouth) float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz _audioAttack = audioAttackAveragingRate * _audioAttack + @@ -165,6 +167,7 @@ void Head::simulate(float deltaTime) { _transientBlendshapeCoefficients); if (getHasProceduralEyeFaceMovement()) { + qCDebug(avatars_renderer) << "in the eye face code"; applyEyelidOffset(getOrientation()); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d72abe592b..7ae9ba1257 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -308,7 +308,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE + - (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) + + (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getBlendshapeCoefficients().size()) : 0) + (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0) + (hasJointDefaultPoseFlags ? AvatarDataPacket::maxJointDefaultPoseFlagsSize(_jointData.size()) : 0); From 9b91f7bb5af849d3b2a359ab6285d803473de04e Mon Sep 17 00:00:00 2001 From: Alexander Ivash <elderorb@gmail.com> Date: Wed, 6 Jun 2018 03:43:27 +0300 Subject: [PATCH 36/62] FB15569 - Debug default scripts no longer on developer menu --- scripts/defaultScripts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 59a51830be..045dff1295 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -57,7 +57,6 @@ if (Menu.menuExists(MENU_CATEGORY) && !Menu.menuItemExists(MENU_CATEGORY, MENU_I menuItemName: MENU_ITEM, isCheckable: true, isChecked: previousSetting, - grouping: "Advanced" }); } From dca93ca61f8fe2ef51f6ba0a809a3dd59a7e364a Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Wed, 6 Jun 2018 16:44:12 -0700 Subject: [PATCH 37/62] fixed setatone16 function to return the correct result for additional flags --- .../avatars-renderer/src/avatars-renderer/Head.cpp | 14 +++++++++++--- libraries/avatars/src/AvatarData.cpp | 11 +++++++++++ libraries/shared/src/SharedUtil.cpp | 4 ++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 39b50b9255..9b6333a4b5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -45,6 +45,13 @@ void Head::reset() { void Head::simulate(float deltaTime) { const float NORMAL_HZ = 60.0f; // the update rate the constant values were tuned for + qCDebug(avatars_renderer) << "name " << _owningAvatar->getName(); + if (_owningAvatar->isMyAvatar()) { + qCDebug(avatars_renderer) << "my avatar"; + } else { + qCDebug(avatars_renderer) << "not my avatar " << _owningAvatar->getAudioLoudness(); + } + // grab the audio loudness from the owning avatar, if we have one float audioLoudness = _owningAvatar ? _owningAvatar->getAudioLoudness() : 0.0f; @@ -78,6 +85,7 @@ void Head::simulate(float deltaTime) { _saccade = glm::vec3(); } + const float BLINK_SPEED = 10.0f; const float BLINK_SPEED_VARIABILITY = 1.0f; @@ -85,7 +93,7 @@ void Head::simulate(float deltaTime) { const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; if (getHasProceduralBlinkFaceMovement()) { - qCDebug(avatars_renderer) << "in the blink code"; + qCDebug(avatars_renderer) << "in the blink code " << _owningAvatar->getName(); // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; const float TALKING_LOUDNESS = 100.0f; @@ -135,7 +143,7 @@ void Head::simulate(float deltaTime) { // use data to update fake Faceshift blendshape coefficients if (getHasAudioEnabledFaceMovement()) { - qCDebug(avatars_renderer) << "in the audio face code"; + //qCDebug(avatars_renderer) << "in the audio face code"; // Update audio attack data for facial animation (eyebrows and mouth) float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz _audioAttack = audioAttackAveragingRate * _audioAttack + @@ -167,7 +175,7 @@ void Head::simulate(float deltaTime) { _transientBlendshapeCoefficients); if (getHasProceduralEyeFaceMovement()) { - qCDebug(avatars_renderer) << "in the eye face code"; + //qCDebug(avatars_renderer) << "in the eye face code"; applyEyelidOffset(getOrientation()); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 7ae9ba1257..43b490719f 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -522,12 +522,17 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer); const auto& blendshapeCoefficients = _headData->getBlendshapeCoefficients(); + //for (int i = 0; i < blendshapeCoefficients.size(); i++) { + // qCWarning(avatars) << "blend coeff " << i << " " << blendshapeCoefficients[i]; + //} + faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink; faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink; faceTrackerInfo->averageLoudness = _headData->_averageLoudness; faceTrackerInfo->browAudioLift = _headData->_browAudioLift; faceTrackerInfo->numBlendshapeCoefficients = blendshapeCoefficients.size(); destinationBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); + qCWarning(avatars) << "face tracker info left eye blink " << faceTrackerInfo->leftEyeBlink; memcpy(destinationBuffer, blendshapeCoefficients.data(), blendshapeCoefficients.size() * sizeof(float)); destinationBuffer += blendshapeCoefficients.size() * sizeof(float); @@ -1009,6 +1014,11 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { auto newHasProceduralEyeFaceMovement = oneAtBit16(bitItems, PROCEDURAL_EYE_FACE_MOVEMENT); auto newHasProceduralBlinkFaceMovement = oneAtBit16(bitItems, PROCEDURAL_BLINK_FACE_MOVEMENT); + if (newHasAudioEnabledFaceMovement) { + qCWarning(avatars) << "name " << getName() << "audio enabled flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "audio enabled flag is false"; + } bool keyStateChanged = (_keyState != newKeyState); bool handStateChanged = (_handState != newHandState); bool faceStateChanged = (_headData->_isFaceTrackerConnected != newFaceTrackerConnected); @@ -1086,6 +1096,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { PACKET_READ_CHECK(FaceTrackerInfo, sizeof(AvatarDataPacket::FaceTrackerInfo)); auto faceTrackerInfo = reinterpret_cast<const AvatarDataPacket::FaceTrackerInfo*>(sourceBuffer); sourceBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); + qCWarning(avatars) << "parse data left eye blink " << faceTrackerInfo->leftEyeBlink; _headData->_leftEyeBlink = faceTrackerInfo->leftEyeBlink; _headData->_rightEyeBlink = faceTrackerInfo->rightEyeBlink; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 35aab3fac1..c0203106c0 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -298,11 +298,11 @@ void setAtBit(unsigned char& byte, int bitIndex) { } bool oneAtBit16(unsigned short word, int bitIndex) { - return (word >> (7 - bitIndex) & 1); + return (word >> (16 - bitIndex) & 1); } void setAtBit16(unsigned short& word, int bitIndex) { - word |= (1 << (7 - bitIndex)); + word |= (1 << (16 - bitIndex)); } From 6a11ddc3497b9cd3a393e24ed8ae6bc96f1c97da Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Wed, 6 Jun 2018 17:50:50 -0700 Subject: [PATCH 38/62] removed print statements and removed the setting of procedural head variables in avatarData.cpp --- .../src/avatars-renderer/Head.cpp | 14 ++--- libraries/avatars/src/AvatarData.cpp | 55 +++++++++++++++---- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 9b6333a4b5..538c928902 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -45,12 +45,12 @@ void Head::reset() { void Head::simulate(float deltaTime) { const float NORMAL_HZ = 60.0f; // the update rate the constant values were tuned for - qCDebug(avatars_renderer) << "name " << _owningAvatar->getName(); - if (_owningAvatar->isMyAvatar()) { - qCDebug(avatars_renderer) << "my avatar"; - } else { - qCDebug(avatars_renderer) << "not my avatar " << _owningAvatar->getAudioLoudness(); - } + //qCDebug(avatars_renderer) << "name " << _owningAvatar->getName(); + //if (_owningAvatar->isMyAvatar()) { + // qCDebug(avatars_renderer) << "my avatar"; + //} else { + // qCDebug(avatars_renderer) << "not my avatar " << _owningAvatar->getAudioLoudness(); + //} // grab the audio loudness from the owning avatar, if we have one float audioLoudness = _owningAvatar ? _owningAvatar->getAudioLoudness() : 0.0f; @@ -93,7 +93,7 @@ void Head::simulate(float deltaTime) { const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; if (getHasProceduralBlinkFaceMovement()) { - qCDebug(avatars_renderer) << "in the blink code " << _owningAvatar->getName(); + //qCDebug(avatars_renderer) << "in the blink code " << _owningAvatar->getName(); // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; const float TALKING_LOUDNESS = 100.0f; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 43b490719f..feb73fd0fb 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -532,7 +532,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent faceTrackerInfo->browAudioLift = _headData->_browAudioLift; faceTrackerInfo->numBlendshapeCoefficients = blendshapeCoefficients.size(); destinationBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); - qCWarning(avatars) << "face tracker info left eye blink " << faceTrackerInfo->leftEyeBlink; + //qCWarning(avatars) << "face tracker info left eye blink " << faceTrackerInfo->leftEyeBlink; memcpy(destinationBuffer, blendshapeCoefficients.data(), blendshapeCoefficients.size() * sizeof(float)); destinationBuffer += blendshapeCoefficients.size() * sizeof(float); @@ -1014,11 +1014,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { auto newHasProceduralEyeFaceMovement = oneAtBit16(bitItems, PROCEDURAL_EYE_FACE_MOVEMENT); auto newHasProceduralBlinkFaceMovement = oneAtBit16(bitItems, PROCEDURAL_BLINK_FACE_MOVEMENT); - if (newHasAudioEnabledFaceMovement) { - qCWarning(avatars) << "name " << getName() << "audio enabled flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "audio enabled flag is false"; - } + bool keyStateChanged = (_keyState != newKeyState); bool handStateChanged = (_handState != newHandState); bool faceStateChanged = (_headData->_isFaceTrackerConnected != newFaceTrackerConnected); @@ -1040,6 +1036,43 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { if (somethingChanged) { _additionalFlagsChanged = usecTimestampNow(); + if (newHasAudioEnabledFaceMovement) { + qCWarning(avatars) << "name " << getName() << "audio enabled flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "audio enabled flag is false"; + } + if (newHasProceduralEyeFaceMovement) { + qCWarning(avatars) << "name " << getName() << "eye face enabled flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "eye face flag is false"; + } + if (newHasProceduralBlinkFaceMovement) { + qCWarning(avatars) << "name " << getName() << "blink flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "blink flag is false"; + } + if (newFaceTrackerConnected) { + qCWarning(avatars) << "name " << getName() << "face tracker flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "face tracker flag is false"; + } + if (newEyeTrackerConnected) { + qCWarning(avatars) << "name " << getName() << "eye tracker flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "eye tracker flag is false"; + } + if (newHandState) { + qCWarning(avatars) << "name " << getName() << "hand state flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "hand state flag is false"; + } + if (newKeyState) { + qCWarning(avatars) << "name " << getName() << "key state flag is true"; + } else { + qCWarning(avatars) << "name " << getName() << "key state flag is false"; + } + + } int numBytesRead = sourceBuffer - startSection; _additionalFlagsRate.increment(numBytesRead); @@ -1096,12 +1129,12 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { PACKET_READ_CHECK(FaceTrackerInfo, sizeof(AvatarDataPacket::FaceTrackerInfo)); auto faceTrackerInfo = reinterpret_cast<const AvatarDataPacket::FaceTrackerInfo*>(sourceBuffer); sourceBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); - qCWarning(avatars) << "parse data left eye blink " << faceTrackerInfo->leftEyeBlink; + //qCWarning(avatars) << "parse data left eye blink " << faceTrackerInfo->leftEyeBlink; - _headData->_leftEyeBlink = faceTrackerInfo->leftEyeBlink; - _headData->_rightEyeBlink = faceTrackerInfo->rightEyeBlink; - _headData->_averageLoudness = faceTrackerInfo->averageLoudness; - _headData->_browAudioLift = faceTrackerInfo->browAudioLift; + //_headData->_leftEyeBlink = faceTrackerInfo->leftEyeBlink; + //_headData->_rightEyeBlink = faceTrackerInfo->rightEyeBlink; + //_headData->_averageLoudness = faceTrackerInfo->averageLoudness; + //_headData->_browAudioLift = faceTrackerInfo->browAudioLift; int numCoefficients = faceTrackerInfo->numBlendshapeCoefficients; const int coefficientsSize = sizeof(float) * numCoefficients; From 97831e61f054d496d1c9b3740bd8e36ccc4a18f6 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 7 Jun 2018 12:54:46 -0700 Subject: [PATCH 39/62] removed stray comments --- interface/src/avatar/MyHead.cpp | 1 + .../src/avatars-renderer/Head.cpp | 3 --- libraries/avatars/src/AvatarData.cpp | 23 ++++++++----------- libraries/avatars/src/AvatarData.h | 13 ++++++++--- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index eb365c20fb..960dfd3402 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -57,6 +57,7 @@ void MyHead::simulate(float deltaTime) { auto eyeTracker = DependencyManager::get<EyeTracker>(); _isEyeTrackerConnected = eyeTracker->isTracking(); + // if eye tracker is connected we should get the data here. } Parent::simulate(deltaTime); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 538c928902..07d82f8af7 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -93,7 +93,6 @@ void Head::simulate(float deltaTime) { const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; if (getHasProceduralBlinkFaceMovement()) { - //qCDebug(avatars_renderer) << "in the blink code " << _owningAvatar->getName(); // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; const float TALKING_LOUDNESS = 100.0f; @@ -143,7 +142,6 @@ void Head::simulate(float deltaTime) { // use data to update fake Faceshift blendshape coefficients if (getHasAudioEnabledFaceMovement()) { - //qCDebug(avatars_renderer) << "in the audio face code"; // Update audio attack data for facial animation (eyebrows and mouth) float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz _audioAttack = audioAttackAveragingRate * _audioAttack + @@ -175,7 +173,6 @@ void Head::simulate(float deltaTime) { _transientBlendshapeCoefficients); if (getHasProceduralEyeFaceMovement()) { - //qCDebug(avatars_renderer) << "in the eye face code"; applyEyelidOffset(getOrientation()); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index feb73fd0fb..539e109501 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -522,17 +522,14 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer); const auto& blendshapeCoefficients = _headData->getBlendshapeCoefficients(); - //for (int i = 0; i < blendshapeCoefficients.size(); i++) { - // qCWarning(avatars) << "blend coeff " << i << " " << blendshapeCoefficients[i]; - //} - + //note: we don't use the blink and average loudness, we just use the numBlendShapes and + // compute the procedural info on the client side. faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink; faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink; faceTrackerInfo->averageLoudness = _headData->_averageLoudness; faceTrackerInfo->browAudioLift = _headData->_browAudioLift; faceTrackerInfo->numBlendshapeCoefficients = blendshapeCoefficients.size(); destinationBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); - //qCWarning(avatars) << "face tracker info left eye blink " << faceTrackerInfo->leftEyeBlink; memcpy(destinationBuffer, blendshapeCoefficients.data(), blendshapeCoefficients.size() * sizeof(float)); destinationBuffer += blendshapeCoefficients.size() * sizeof(float); @@ -999,7 +996,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { // hand state, stored as a semi-nibble plus a bit in the bitItems // we store the hand state as well as other items in a shared bitset. The hand state is an octal, but is split // into two sections to maintain backward compatibility. The bits are ordered as such (0-7 left to right). - // AA 6/1/18 added three more flags here for procedural audio, blink, and eye saccade enabled + // AA 6/1/18 added three more flags bits 8,9, and 10 for procedural audio, blink, and eye saccade enabled // +---+-----+-----+--+--+--+--+-----+ // |x,x|H0,H1|x,x,x|H2|Au|Bl|Ey|xxxxx| // +---+-----+-----+--+--+--+--+-----+ @@ -1124,25 +1121,23 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } if (hasFaceTrackerInfo) { + //qCWarning(avatars) << "parsing face tracker info "; auto startSection = sourceBuffer; PACKET_READ_CHECK(FaceTrackerInfo, sizeof(AvatarDataPacket::FaceTrackerInfo)); auto faceTrackerInfo = reinterpret_cast<const AvatarDataPacket::FaceTrackerInfo*>(sourceBuffer); - sourceBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); - //qCWarning(avatars) << "parse data left eye blink " << faceTrackerInfo->leftEyeBlink; - - //_headData->_leftEyeBlink = faceTrackerInfo->leftEyeBlink; - //_headData->_rightEyeBlink = faceTrackerInfo->rightEyeBlink; - //_headData->_averageLoudness = faceTrackerInfo->averageLoudness; - //_headData->_browAudioLift = faceTrackerInfo->browAudioLift; - int numCoefficients = faceTrackerInfo->numBlendshapeCoefficients; const int coefficientsSize = sizeof(float) * numCoefficients; + sourceBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); + PACKET_READ_CHECK(FaceTrackerCoefficients, coefficientsSize); _headData->_blendshapeCoefficients.resize(numCoefficients); // make sure there's room for the copy! _headData->_transientBlendshapeCoefficients.resize(numCoefficients); + + //only copy the blendshapes to headData not the procedural face info memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer, coefficientsSize); sourceBuffer += coefficientsSize; + int numBytesRead = sourceBuffer - startSection; _faceTrackerRate.increment(numBytesRead); _faceTrackerUpdateRate.increment(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index ad304d5796..51b3257ba2 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -79,14 +79,21 @@ const quint32 AVATAR_MOTION_SCRIPTABLE_BITS = // Bitset of state flags - we store the key state, hand state, Faceshift, eye tracking, and existence of // referential data in this bit set. The hand state is an octal, but is split into two sections to maintain // backward compatibility. The bits are ordered as such (0-7 left to right). -// +-----+-----+-+-+-+--+ -// |K0,K1|H0,H1|F|E|R|H2| -// +-----+-----+-+-+-+--+ +// AA 6/1/18 added three more flags bits 8,9, and 10 for procedural audio, blink, and eye saccade enabled +// +// +-----+-----+-+-+-+--+--+--+--+-----+ +// |K0,K1|H0,H1|F|E|R|H2|Au|Bl|Ey|xxxxx| +// +-----+-----+-+-+-+--+--+--+--+-----+ +// // Key state - K0,K1 is found in the 1st and 2nd bits // Hand state - H0,H1,H2 is found in the 3rd, 4th, and 8th bits // Face tracker - F is found in the 5th bit // Eye tracker - E is found in the 6th bit // Referential Data - R is found in the 7th bit +// Procedural audio to mouth movement is enabled 8th bit +// Procedural Blink is enabled 9th bit +// Procedural Eyelid is enabled 10th bit + const int KEY_STATE_START_BIT = 0; // 1st and 2nd bits const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits const int IS_FACE_TRACKER_CONNECTED = 4; // 5th bit From da92ff993f76f961923895b39d62f26390396316 Mon Sep 17 00:00:00 2001 From: Alexander Ivash <elderorb@gmail.com> Date: Wed, 6 Jun 2018 03:52:22 +0300 Subject: [PATCH 40/62] terminate thread if it didn't complete during MAX_SCRIPT_QUITTING_TIME --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 72860acbc5..8e329c9c07 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -419,7 +419,7 @@ void ScriptEngine::waitTillDoneRunning() { // Wait for the scripting thread to stop running, as // flooding it with aborts/exceptions will persist it longer static const auto MAX_SCRIPT_QUITTING_TIME = 0.5 * MSECS_PER_SECOND; - if (workerThread->wait(MAX_SCRIPT_QUITTING_TIME)) { + if (!workerThread->wait(MAX_SCRIPT_QUITTING_TIME)) { workerThread->terminate(); } } From 836c3da8581c6db43cbda0754cefd2266dff137f Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 7 Jun 2018 15:11:57 -0700 Subject: [PATCH 41/62] cleaned up white space and removed extra declaration of hadAudioEnabledFaceMovement --- interface/src/avatar/MyAvatar.h | 1 - interface/src/avatar/MyHead.cpp | 2 +- .../src/avatars-renderer/Head.cpp | 17 +-- libraries/avatars/src/AvatarData.cpp | 11 +- libraries/avatars/src/HeadData.h | 2 - .../DefaultStylizedFemale_Clothed.fst | 139 ------------------ scripts/developer/facialExpressions.js | 4 +- 7 files changed, 10 insertions(+), 166 deletions(-) delete mode 100644 scripts/developer/DefaultStylizedFemale_Clothed.fst diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 813dddcc98..b401b2469a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1466,7 +1466,6 @@ private: float _hmdRollControlDeadZone { ROLL_CONTROL_DEAD_ZONE_DEFAULT }; float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT }; std::atomic<bool> _hasScriptedBlendShapes { false }; - bool _hasAudioEnabledFaceMovement { true }; // working copy -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access glm::mat4 _sensorToWorldMatrix { glm::mat4() }; diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index 960dfd3402..9b05a26c76 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -54,7 +54,7 @@ void MyHead::simulate(float deltaTime) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } } - + auto eyeTracker = DependencyManager::get<EyeTracker>(); _isEyeTrackerConnected = eyeTracker->isTracking(); // if eye tracker is connected we should get the data here. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 07d82f8af7..50f20918fa 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -45,13 +45,6 @@ void Head::reset() { void Head::simulate(float deltaTime) { const float NORMAL_HZ = 60.0f; // the update rate the constant values were tuned for - //qCDebug(avatars_renderer) << "name " << _owningAvatar->getName(); - //if (_owningAvatar->isMyAvatar()) { - // qCDebug(avatars_renderer) << "my avatar"; - //} else { - // qCDebug(avatars_renderer) << "not my avatar " << _owningAvatar->getAudioLoudness(); - //} - // grab the audio loudness from the owning avatar, if we have one float audioLoudness = _owningAvatar ? _owningAvatar->getAudioLoudness() : 0.0f; @@ -84,9 +77,7 @@ void Head::simulate(float deltaTime) { } else { _saccade = glm::vec3(); } - - - + const float BLINK_SPEED = 10.0f; const float BLINK_SPEED_VARIABILITY = 1.0f; const float BLINK_START_VARIABILITY = 0.25f; @@ -162,7 +153,7 @@ void Head::simulate(float deltaTime) { _mouth4 = 0.0f; _mouthTime = 0.0f; } - + FaceTracker::updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink, _browAudioLift, @@ -171,11 +162,11 @@ void Head::simulate(float deltaTime) { _mouth3, _mouth4, _transientBlendshapeCoefficients); - + if (getHasProceduralEyeFaceMovement()) { applyEyelidOffset(getOrientation()); } - + _leftEyePosition = _rightEyePosition = getPosition(); if (_owningAvatar) { auto skeletonModel = static_cast<Avatar*>(_owningAvatar)->getSkeletonModel(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 539e109501..b8ccbce962 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -521,8 +521,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent auto startSection = destinationBuffer; auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer); const auto& blendshapeCoefficients = _headData->getBlendshapeCoefficients(); - - //note: we don't use the blink and average loudness, we just use the numBlendShapes and + // note: we don't use the blink and average loudness, we just use the numBlendShapes and // compute the procedural info on the client side. faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink; faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink; @@ -1068,7 +1067,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } else { qCWarning(avatars) << "name " << getName() << "key state flag is false"; } - } int numBytesRead = sourceBuffer - startSection; @@ -1121,7 +1119,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } if (hasFaceTrackerInfo) { - //qCWarning(avatars) << "parsing face tracker info "; auto startSection = sourceBuffer; PACKET_READ_CHECK(FaceTrackerInfo, sizeof(AvatarDataPacket::FaceTrackerInfo)); @@ -1129,12 +1126,10 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { int numCoefficients = faceTrackerInfo->numBlendshapeCoefficients; const int coefficientsSize = sizeof(float) * numCoefficients; sourceBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo); - + PACKET_READ_CHECK(FaceTrackerCoefficients, coefficientsSize); _headData->_blendshapeCoefficients.resize(numCoefficients); // make sure there's room for the copy! - _headData->_transientBlendshapeCoefficients.resize(numCoefficients); - - //only copy the blendshapes to headData not the procedural face info + //only copy the blendshapes to headData, not the procedural face info memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer, coefficientsSize); sourceBuffer += coefficientsSize; diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index f8eca0915e..e8289269d8 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -101,8 +101,6 @@ protected: glm::vec3 _lookAtPosition; quint64 _lookAtPositionChanged { 0 }; - //std::atomic<bool> _hasProceduralBlinkFaceMovement{ true }; - //std::atomic<bool> _hasProceduralEyeFaceMovement{ true }; bool _hasAudioEnabledFaceMovement { true }; bool _hasProceduralBlinkFaceMovement{ true }; bool _hasProceduralEyeFaceMovement{ true }; diff --git a/scripts/developer/DefaultStylizedFemale_Clothed.fst b/scripts/developer/DefaultStylizedFemale_Clothed.fst deleted file mode 100644 index 3e46d6a15c..0000000000 --- a/scripts/developer/DefaultStylizedFemale_Clothed.fst +++ /dev/null @@ -1,139 +0,0 @@ -name = DefaultStylizedFemale_Clothed -type = body+head -scale = 1 -filename = DefaultStylizedFemale_Clothed/DefaultStylizedFemale_Clothed.fbx -texdir = DefaultStylizedFemale_Clothed/textures -joint = jointLean = Spine -joint = jointRightHand = RightHand -joint = jointEyeLeft = LeftEye -joint = jointHead = HeadTop_End -joint = jointNeck = Neck -joint = jointRoot = Hips -joint = jointEyeRight = RightEye -joint = jointLeftHand = LeftHand -freeJoint = LeftArm -freeJoint = LeftForeArm -freeJoint = RightArm -freeJoint = RightForeArm -bs = EyeBlink_L = Blink_Left = 1 -bs = Sneer = Squint_Right = 0.5 -bs = Sneer = Squint_Left = 0.5 -bs = Sneer = NoseScrunch_Right = 0.75 -bs = Sneer = NoseScrunch_Left = 0.75 -bs = ChinLowerRaise = Jaw_Up = 1 -bs = EyeSquint_R = Squint_Right = 1 -bs = MouthSmile_R = Smile_Right = 1 -bs = ChinUpperRaise = UpperLipUp_Right = 0.5 -bs = ChinUpperRaise = UpperLipUp_Left = 0.5 -bs = LipsLowerOpen = LowerLipOut = 1 -bs = LipsLowerDown = LowerLipDown_Right = 0.7 -bs = LipsLowerDown = LowerLipDown_Left = 0.7 -bs = BrowsU_L = BrowsUp_Left = 1 -bs = MouthRight = Midmouth_Right = 1 -bs = MouthDimple_R = Smile_Right = 0.25 -bs = LipsPucker = MouthNarrow_Right = 1 -bs = LipsPucker = MouthNarrow_Left = 1 -bs = Puff = CheekPuff_Right = 1 -bs = Puff = CheekPuff_Left = 1 -bs = JawFwd = JawForeward = 1 -bs = BrowsD_L = BrowsDown_Left = 1 -bs = LipsFunnel = TongueUp = 1 -bs = LipsFunnel = MouthWhistle_NarrowAdjust_Right = 0.5 -bs = LipsFunnel = MouthWhistle_NarrowAdjust_Left = 0.5 -bs = LipsFunnel = MouthNarrow_Right = 1 -bs = LipsFunnel = MouthNarrow_Left = 1 -bs = LipsFunnel = Jaw_Down = 0.36 -bs = LipsFunnel = JawForeward = 0.39 -bs = LipsUpperOpen = UpperLipOut = 1 -bs = EyeSquint_L = Squint_Left = 1 -bs = MouthDimple_L = Smile_Left = 0.25 -bs = LipsLowerClose = LowerLipIn = 1 -bs = MouthFrown_R = Frown_Right = 1 -bs = MouthFrown_L = Frown_Left = 1 -bs = BrowsU_R = BrowsUp_Right = 1 -bs = JawOpen = MouthOpen = 0.7 -bs = JawRight = Jaw_Right = 1 -bs = MouthLeft = Midmouth_Left = 1 -bs = BrowsU_C = BrowsUp_Right = 1 -bs = BrowsU_C = BrowsUp_Left = 1 -bs = LipsUpperUp = UpperLipUp_Right = 0.7 -bs = LipsUpperUp = UpperLipUp_Left = 0.7 -bs = EyeBlink_R = Blink_Right = 1 -bs = EyeOpen_R = EyesWide_Right = 1 -bs = LipsUpperClose = UpperLipIn = 1 -bs = MouthSmile_L = Smile_Left = 1 -bs = EyeOpen_L = EyesWide_Left = 1 -bs = JawLeft = JawRotateY_Left = 0.5 -bs = BrowsD_R = BrowsDown_Right = 1 -jointIndex = RightHandThumb4 = 21 -jointIndex = Neck = 62 -jointIndex = LeftHandIndex4 = 57 -jointIndex = Body = 71 -jointIndex = LeftHandIndex1 = 54 -jointIndex = RightHand = 17 -jointIndex = RightHandMiddle1 = 26 -jointIndex = Spine = 11 -jointIndex = RightHandRing2 = 31 -jointIndex = RightArm = 15 -jointIndex = RightHandPinky2 = 35 -jointIndex = LeftToeBase = 9 -jointIndex = RightHandIndex3 = 24 -jointIndex = RightHandRing1 = 30 -jointIndex = RightHandPinky1 = 34 -jointIndex = RightEye = 66 -jointIndex = LeftHandRing4 = 49 -jointIndex = LeftHandRing2 = 47 -jointIndex = RightHandMiddle2 = 27 -jointIndex = Head = 63 -jointIndex = LeftHandMiddle4 = 53 -jointIndex = LeftLeg = 7 -jointIndex = LeftHandPinky2 = 43 -jointIndex = LeftHandThumb1 = 58 -jointIndex = LeftHandPinky4 = 45 -jointIndex = RightHandIndex1 = 22 -jointIndex = Tops = 67 -jointIndex = Hips = 0 -jointIndex = LeftUpLeg = 6 -jointIndex = RightShoulder = 14 -jointIndex = Spine2 = 13 -jointIndex = RightHandRing4 = 33 -jointIndex = RightHandThumb3 = 20 -jointIndex = RightHandIndex4 = 25 -jointIndex = LeftFoot = 8 -jointIndex = LeftHandRing3 = 48 -jointIndex = LeftHand = 41 -jointIndex = LeftForeArm = 40 -jointIndex = LeftToe_End = 10 -jointIndex = Bottoms = 68 -jointIndex = RightFoot = 3 -jointIndex = LeftHandMiddle2 = 51 -jointIndex = LeftHandThumb3 = 60 -jointIndex = RightHandPinky3 = 36 -jointIndex = LeftEye = 65 -jointIndex = LeftHandIndex2 = 55 -jointIndex = RightHandIndex2 = 23 -jointIndex = LeftHandPinky1 = 42 -jointIndex = LeftHandMiddle3 = 52 -jointIndex = RightHandMiddle4 = 29 -jointIndex = LeftHandThumb2 = 59 -jointIndex = Shoes = 69 -jointIndex = RightHandThumb1 = 18 -jointIndex = RightToe_End = 5 -jointIndex = RightHandThumb2 = 19 -jointIndex = RightUpLeg = 1 -jointIndex = RightLeg = 2 -jointIndex = LeftHandMiddle1 = 50 -jointIndex = LeftHandIndex3 = 56 -jointIndex = LeftHandThumb4 = 61 -jointIndex = RightHandRing3 = 32 -jointIndex = Hair = 70 -jointIndex = Spine1 = 12 -jointIndex = LeftHandRing1 = 46 -jointIndex = LeftArm = 39 -jointIndex = LeftShoulder = 38 -jointIndex = RightForeArm = 16 -jointIndex = HeadTop_End = 64 -jointIndex = RightHandPinky4 = 37 -jointIndex = LeftHandPinky3 = 44 -jointIndex = RightToeBase = 4 -jointIndex = RightHandMiddle3 = 28 diff --git a/scripts/developer/facialExpressions.js b/scripts/developer/facialExpressions.js index 84e3966c4a..37a4f4f796 100644 --- a/scripts/developer/facialExpressions.js +++ b/scripts/developer/facialExpressions.js @@ -1,7 +1,7 @@ // // facialExpressions.js // A script to set different emotions using blend shapes -// +// // Author: Elisa Lupin-Jimenez // Copyright High Fidelity 2018 // @@ -286,7 +286,7 @@ } } for (var blendshape in emotion) { - MyAvatar.setBlendshape(blendshape, + MyAvatar.setBlendshape(blendshape, mixValue(lastEmotionUsed[blendshape], emotion[blendshape], changingEmotionPercentage)); } }); From 67fc7b90b5da4e51c1d9d4e4218a46e206ebde80 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 7 Jun 2018 15:43:21 -0700 Subject: [PATCH 42/62] fixed get and set semi nibble to deal with 16 bits --- libraries/avatars-renderer/src/avatars-renderer/Head.cpp | 3 +-- libraries/shared/src/SharedUtil.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 50f20918fa..598bc2b21a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -59,7 +59,6 @@ void Head::simulate(float deltaTime) { _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); } - //if (!_isFaceTrackerConnected) { if (!_isEyeTrackerConnected) { // Update eye saccades const float AVERAGE_MICROSACCADE_INTERVAL = 1.0f; @@ -77,7 +76,7 @@ void Head::simulate(float deltaTime) { } else { _saccade = glm::vec3(); } - + const float BLINK_SPEED = 10.0f; const float BLINK_SPEED_VARIABILITY = 1.0f; const float BLINK_START_VARIABILITY = 0.25f; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index c0203106c0..bb22a1e753 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -298,11 +298,11 @@ void setAtBit(unsigned char& byte, int bitIndex) { } bool oneAtBit16(unsigned short word, int bitIndex) { - return (word >> (16 - bitIndex) & 1); + return (word >> (15 - bitIndex) & 1); } void setAtBit16(unsigned short& word, int bitIndex) { - word |= (1 << (16 - bitIndex)); + word |= (1 << (15 - bitIndex)); } @@ -313,7 +313,7 @@ void clearAtBit(unsigned char& byte, int bitIndex) { } int getSemiNibbleAt(unsigned short word, int bitIndex) { - return (word >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 + return (word >> (14 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 } int getNthBit(unsigned char byte, int ordinal) { @@ -337,7 +337,7 @@ int getNthBit(unsigned char byte, int ordinal) { void setSemiNibbleAt(unsigned short& word, int bitIndex, int value) { //assert(value <= 3 && value >= 0); - word |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 + word |= ((value & 3) << (14 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 } bool isInEnvironment(const char* environment) { From 22f25835569b5d39dc45a1154c28a62cd02d8c11 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 7 Jun 2018 16:17:33 -0700 Subject: [PATCH 43/62] removed debug print statement in AvatarData.cpp --- libraries/avatars/src/AvatarData.cpp | 36 ---------------------------- 1 file changed, 36 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b8ccbce962..b5186ba8f4 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1032,42 +1032,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { if (somethingChanged) { _additionalFlagsChanged = usecTimestampNow(); - if (newHasAudioEnabledFaceMovement) { - qCWarning(avatars) << "name " << getName() << "audio enabled flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "audio enabled flag is false"; - } - if (newHasProceduralEyeFaceMovement) { - qCWarning(avatars) << "name " << getName() << "eye face enabled flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "eye face flag is false"; - } - if (newHasProceduralBlinkFaceMovement) { - qCWarning(avatars) << "name " << getName() << "blink flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "blink flag is false"; - } - if (newFaceTrackerConnected) { - qCWarning(avatars) << "name " << getName() << "face tracker flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "face tracker flag is false"; - } - if (newEyeTrackerConnected) { - qCWarning(avatars) << "name " << getName() << "eye tracker flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "eye tracker flag is false"; - } - if (newHandState) { - qCWarning(avatars) << "name " << getName() << "hand state flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "hand state flag is false"; - } - if (newKeyState) { - qCWarning(avatars) << "name " << getName() << "key state flag is true"; - } else { - qCWarning(avatars) << "name " << getName() << "key state flag is false"; - } - } int numBytesRead = sourceBuffer - startSection; _additionalFlagsRate.increment(numBytesRead); From 3f5820266762f9962d9bb5bd91912272005e4f02 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 7 Jun 2018 17:41:12 -0700 Subject: [PATCH 44/62] updated the AvatarMixerPacketVersion to ProceduralFaceMovementFlagsAndBlendshapes in PacketHeaders.cpp --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index b69733c18d..c342ecffc5 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -40,7 +40,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::AvatarData: case PacketType::BulkAvatarData: case PacketType::KillAvatar: - return static_cast<PacketVersion>(AvatarMixerPacketVersion::FBXReaderNodeReparenting); + return static_cast<PacketVersion>(AvatarMixerPacketVersion::ProceduralFaceMovementFlagsAndBlendshapes); case PacketType::MessagesData: return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData); // ICE packets diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 5203a9d178..43495dab07 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -282,7 +282,8 @@ enum class AvatarMixerPacketVersion : PacketVersion { AvatarIdentityLookAtSnapping, UpdatedMannequinDefaultAvatar, AvatarJointDefaultPoseFlags, - FBXReaderNodeReparenting + FBXReaderNodeReparenting, + ProceduralFaceMovementFlagsAndBlendshapes }; enum class DomainConnectRequestVersion : PacketVersion { From 83e1db14cffb882c440b47f6f792249b2e1786ea Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 7 Jun 2018 18:56:23 -0700 Subject: [PATCH 45/62] Set UAL default value earlier to be caught by crashpad --- interface/src/Application.cpp | 10 +--------- interface/src/main.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7ae34e2f51..60d5cf20f3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1443,17 +1443,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // add firstRun flag from settings to launch event Setting::Handle<bool> firstRun { Settings::firstRun, true }; - // once the settings have been loaded, check if we need to flip the default for UserActivityLogger - auto& userActivityLogger = UserActivityLogger::getInstance(); - if (!userActivityLogger.isDisabledSettingSet()) { - // the user activity logger is opt-out for Interface - // but it's defaulted to disabled for other targets - // so we need to enable it here if it has never been disabled by the user - userActivityLogger.disable(false); - } - QString machineFingerPrint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + auto& userActivityLogger = UserActivityLogger::getInstance(); if (userActivityLogger.isEnabled()) { // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 22db128f7e..cd8c052d63 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -81,6 +81,13 @@ int main(int argc, const char* argv[]) { // Instance UserActivityLogger now that the settings are loaded auto& ual = UserActivityLogger::getInstance(); + // once the settings have been loaded, check if we need to flip the default for UserActivityLogger + if (!ual.isDisabledSettingSet()) { + // the user activity logger is opt-out for Interface + // but it's defaulted to disabled for other targets + // so we need to enable it here if it has never been disabled by the user + ual.disable(false); + } qDebug() << "UserActivityLogger is enabled:" << ual.isEnabled(); if (ual.isEnabled()) { From b1c578ecaa159536e814a0d528b3328269aa6e1f Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Thu, 7 Jun 2018 22:13:53 -0700 Subject: [PATCH 46/62] fixed white space in head.cpp --- .../src/avatars-renderer/Head.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 598bc2b21a..5800c1404b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -95,19 +95,19 @@ void Head::simulate(float deltaTime) { } if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { - // no blinking when brows are raised; blink less with increasing loudness - const float BASE_BLINK_RATE = 15.0f / 60.0f; - const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; - if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * - ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { - _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; - _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; - if (randFloat() < 0.5f) { - _leftEyeBlink = BLINK_START_VARIABILITY; - } else { - _rightEyeBlink = BLINK_START_VARIABILITY; - } + // no blinking when brows are raised; blink less with increasing loudness + const float BASE_BLINK_RATE = 15.0f / 60.0f; + const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; + if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * + ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { + _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + if (randFloat() < 0.5f) { + _leftEyeBlink = BLINK_START_VARIABILITY; + } else { + _rightEyeBlink = BLINK_START_VARIABILITY; } + } } else { _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); From dabcd4c234a58b118e0e5c01be336face48cca25 Mon Sep 17 00:00:00 2001 From: amantley <amantley@googlemail.com> Date: Fri, 8 Jun 2018 10:19:33 -0700 Subject: [PATCH 47/62] fixed bracket spacing in HeadData.h --- libraries/avatars/src/HeadData.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index e8289269d8..f9c4b52139 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -102,8 +102,8 @@ protected: quint64 _lookAtPositionChanged { 0 }; bool _hasAudioEnabledFaceMovement { true }; - bool _hasProceduralBlinkFaceMovement{ true }; - bool _hasProceduralEyeFaceMovement{ true }; + bool _hasProceduralBlinkFaceMovement { true }; + bool _hasProceduralEyeFaceMovement { true }; bool _isFaceTrackerConnected { false }; bool _isEyeTrackerConnected { false }; float _leftEyeBlink { 0.0f }; From faafd26d2a77228c4872f885d15df6769f11f2a1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 31 May 2018 16:50:32 -0700 Subject: [PATCH 48/62] Add uncompressed KTX files to baked texture output --- assignment-client/src/assets/AssetServer.cpp | 18 ---- assignment-client/src/assets/AssetServer.h | 5 - libraries/baking/src/TextureBaker.cpp | 98 +++++++++++++------ libraries/image/src/image/Image.cpp | 88 ++++++++--------- libraries/image/src/image/Image.h | 56 +++++------ libraries/ktx/src/TextureMeta.cpp | 4 + libraries/ktx/src/TextureMeta.h | 1 + .../src/model-networking/TextureCache.cpp | 23 ++++- libraries/shared/src/OwningBuffer.h | 29 ++++++ tools/oven/src/Oven.cpp | 6 -- 10 files changed, 190 insertions(+), 138 deletions(-) create mode 100644 libraries/shared/src/OwningBuffer.h diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 22ed01fd00..e0c35b7148 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -291,18 +291,6 @@ AssetServer::AssetServer(ReceivedMessage& message) : _bakingTaskPool(this), _filesizeLimit(AssetUtils::MAX_UPLOAD_SIZE) { - // store the current state of image compression so we can reset it when this assignment is complete - _wasColorTextureCompressionEnabled = image::isColorTexturesCompressionEnabled(); - _wasGrayscaleTextureCompressionEnabled = image::isGrayscaleTexturesCompressionEnabled(); - _wasNormalTextureCompressionEnabled = image::isNormalTexturesCompressionEnabled(); - _wasCubeTextureCompressionEnabled = image::isCubeTexturesCompressionEnabled(); - - // enable compression in image library - image::setColorTexturesCompressionEnabled(true); - image::setGrayscaleTexturesCompressionEnabled(true); - image::setNormalTexturesCompressionEnabled(true); - image::setCubeTexturesCompressionEnabled(true); - BAKEABLE_TEXTURE_EXTENSIONS = image::getSupportedFormats(); qDebug() << "Supported baking texture formats:" << BAKEABLE_MODEL_EXTENSIONS; @@ -354,12 +342,6 @@ void AssetServer::aboutToFinish() { while (_pendingBakes.size() > 0) { QCoreApplication::processEvents(); } - - // re-set defaults in image library - image::setColorTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled); - image::setGrayscaleTexturesCompressionEnabled(_wasGrayscaleTextureCompressionEnabled); - image::setNormalTexturesCompressionEnabled(_wasNormalTextureCompressionEnabled); - image::setCubeTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled); } void AssetServer::run() { diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index 96a220d64d..b3d0f18a8f 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -167,11 +167,6 @@ private: using RequestQueue = QVector<QPair<QSharedPointer<ReceivedMessage>, SharedNodePointer>>; RequestQueue _queuedRequests; - bool _wasColorTextureCompressionEnabled { false }; - bool _wasGrayscaleTextureCompressionEnabled { false }; - bool _wasNormalTextureCompressionEnabled { false }; - bool _wasCubeTextureCompressionEnabled { false }; - uint64_t _filesizeLimit; }; diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index b6957a2712..cadc1a2d7e 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -22,6 +22,8 @@ #include <SharedUtil.h> #include <TextureMeta.h> +#include <OwningBuffer.h> + #include "ModelBakingLoggingCategory.h" const QString BAKED_TEXTURE_KTX_EXT = ".ktx"; @@ -124,47 +126,51 @@ void TextureBaker::processTexture() { TextureMeta meta; + auto originalCopyFilePath = _outputDirectory.absoluteFilePath(_textureURL.fileName()); { - auto filePath = _outputDirectory.absoluteFilePath(_textureURL.fileName()); - QFile file { filePath }; + QFile file { originalCopyFilePath }; if (!file.open(QIODevice::WriteOnly) || file.write(_originalTexture) == -1) { handleError("Could not write original texture for " + _textureURL.toString()); return; } - _outputFiles.push_back(filePath); + _originalTexture.clear(); + _outputFiles.push_back(originalCopyFilePath); meta.original = _metaTexturePathPrefix +_textureURL.fileName(); } - // IMPORTANT: _originalTexture is empty past this point - auto processedTexture = image::processImage(std::move(_originalTexture), _textureURL.toString().toStdString(), - ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, _abortProcessing); - processedTexture->setSourceHash(hash); - - if (shouldStop()) { + auto buffer = std::shared_ptr<QIODevice>((QIODevice*)new QFile(originalCopyFilePath)); + if (!buffer->open(QIODevice::ReadOnly)) { + handleError("Could not open original file at " + originalCopyFilePath); return; } - if (!processedTexture) { - handleError("Could not process texture " + _textureURL.toString()); - return; - } - - - auto memKTX = gpu::Texture::serialize(*processedTexture); - - if (!memKTX) { - handleError("Could not serialize " + _textureURL.toString() + " to KTX"); - return; - } - - const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat()); - if (name == nullptr) { - handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString()); - return; - } - - // attempt to write the baked texture to the destination file path + // Compressed KTX { + // IMPORTANT: _originalTexture is empty past this point + auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), + ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, _abortProcessing); + if (!processedTexture) { + handleError("Could not process texture " + _textureURL.toString()); + return; + } + processedTexture->setSourceHash(hash); + + if (shouldStop()) { + return; + } + + auto memKTX = gpu::Texture::serialize(*processedTexture); + if (!memKTX) { + handleError("Could not serialize " + _textureURL.toString() + " to KTX"); + return; + } + + const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat()); + if (name == nullptr) { + handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString()); + return; + } + const char* data = reinterpret_cast<const char*>(memKTX->_storage->data()); const size_t length = memKTX->_storage->size(); @@ -179,6 +185,40 @@ void TextureBaker::processTexture() { meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName; } + // Uncompressed KTX + { + buffer->reset(); + auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), + ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, _abortProcessing); + if (!processedTexture) { + handleError("Could not process texture " + _textureURL.toString()); + return; + } + processedTexture->setSourceHash(hash); + + if (shouldStop()) { + return; + } + + auto memKTX = gpu::Texture::serialize(*processedTexture); + if (!memKTX) { + handleError("Could not serialize " + _textureURL.toString() + " to KTX"); + return; + } + + const char* data = reinterpret_cast<const char*>(memKTX->_storage->data()); + const size_t length = memKTX->_storage->size(); + + auto fileName = _baseFilename + ".ktx"; + auto filePath = _outputDirectory.absoluteFilePath(fileName); + QFile bakedTextureFile { filePath }; + if (!bakedTextureFile.open(QIODevice::WriteOnly) || bakedTextureFile.write(data, length) == -1) { + handleError("Could not write baked texture for " + _textureURL.toString()); + return; + } + _outputFiles.push_back(filePath); + meta.uncompressed = _metaTexturePathPrefix + fileName; + } { auto data = meta.serialize(); diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 63a4725f64..7faf811dec 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -126,63 +126,63 @@ TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, con } gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureColorFromImage(std::move(srcImage), srcImageName, true, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing); } gpu::TexturePointer TextureUsage::create2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, true, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing); } gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, true, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing); } gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } gpu::TexturePointer TextureUsage::createCubeTextureFromImage(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, true, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing); } gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(QImage&& srcImage, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing) { - return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing) { + return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } @@ -253,17 +253,11 @@ uint32 packR11G11B10F(const glm::vec3& color) { return glm::packF2x11_1x10(ucolor); } -QImage processRawImageData(QByteArray&& content, const std::string& filename) { - // Take a local copy to force move construction - // https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f18-for-consume-parameters-pass-by-x-and-stdmove-the-parameter - QByteArray localCopy = std::move(content); - +QImage processRawImageData(QIODevice& content, const std::string& filename) { // Help the QImage loader by extracting the image file format from the url filename ext. // Some tga are not created properly without it. auto filenameExtension = filename.substr(filename.find_last_of('.') + 1); - QBuffer buffer; - buffer.setData(localCopy); - QImageReader imageReader(&buffer, filenameExtension.c_str()); + QImageReader imageReader(&content, filenameExtension.c_str()); if (imageReader.canRead()) { return imageReader.read(); @@ -271,8 +265,8 @@ QImage processRawImageData(QByteArray&& content, const std::string& filename) { // Extension could be incorrect, try to detect the format from the content QImageReader newImageReader; newImageReader.setDecideFormatFromContent(true); - buffer.setData(localCopy); - newImageReader.setDevice(&buffer); + content.reset(); + newImageReader.setDevice(&content); if (newImageReader.canRead()) { qCWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str() @@ -284,11 +278,14 @@ QImage processRawImageData(QByteArray&& content, const std::string& filename) { return QImage(); } -gpu::TexturePointer processImage(QByteArray&& content, const std::string& filename, +gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::string& filename, int maxNumPixels, TextureUsage::Type textureType, - const std::atomic<bool>& abortProcessing) { + bool compress, const std::atomic<bool>& abortProcessing) { - QImage image = processRawImageData(std::move(content), filename); + QImage image = processRawImageData(*content.get(), filename); + // Texture content can take up a lot of memory. Here we release our ownership of that content + // in case it can be released. + content.reset(); int imageWidth = image.width(); int imageHeight = image.height(); @@ -314,7 +311,7 @@ gpu::TexturePointer processImage(QByteArray&& content, const std::string& filena } auto loader = TextureUsage::getTextureLoaderForType(textureType); - auto texture = loader(std::move(image), filename, abortProcessing); + auto texture = loader(std::move(image), filename, compress, abortProcessing); return texture; } @@ -804,7 +801,7 @@ void processTextureAlpha(const QImage& srcImage, bool& validAlpha, bool& alphaAs validAlpha = (numOpaques != NUM_PIXELS); } -gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, +gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress, bool isStrict, const std::atomic<bool>& abortProcessing) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); QImage image = processSourceImage(std::move(srcImage), false); @@ -825,7 +822,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatMip; gpu::Element formatGPU; - if (isColorTexturesCompressionEnabled()) { + if (compress) { if (validAlpha) { // NOTE: This disables BC1a compression because it was producing odd artifacts on text textures // for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts). @@ -941,7 +938,8 @@ QImage processBumpMap(QImage&& image) { return result; } gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, - bool isBumpMap, const std::atomic<bool>& abortProcessing) { + bool compress, bool isBumpMap, + const std::atomic<bool>& abortProcessing) { PROFILE_RANGE(resource_parse, "process2DTextureNormalMapFromImage"); QImage image = processSourceImage(std::move(srcImage), false); @@ -959,6 +957,7 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr gpu::Element formatMip; gpu::Element formatGPU; if (isNormalTexturesCompressionEnabled()) { + if (compress) { formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY; } else { #ifdef USE_GLES @@ -980,7 +979,7 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr } gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, - bool isInvertedPixels, + bool compress, bool isInvertedPixels, const std::atomic<bool>& abortProcessing) { PROFILE_RANGE(resource_parse, "process2DTextureGrayscaleFromImage"); QImage image = processSourceImage(std::move(srcImage), false); @@ -999,6 +998,7 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr gpu::Element formatMip; gpu::Element formatGPU; if (isGrayscaleTexturesCompressionEnabled()) { + if (compress) { formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED; } else { #ifdef USE_GLES @@ -1345,7 +1345,7 @@ QImage convertToHDRFormat(QImage&& srcImage, gpu::Element format) { } gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, - bool generateIrradiance, + bool compress, bool generateIrradiance, const std::atomic<bool>& abortProcessing) { PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); @@ -1373,7 +1373,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI gpu::Element formatMip; gpu::Element formatGPU; - if (isCubeTexturesCompressionEnabled()) { + if (compress) { formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB; } else { #ifdef USE_GLES diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 39f5ea3bab..3dca8f5586 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -41,60 +41,50 @@ enum Type { UNUSED_TEXTURE }; -using TextureLoader = std::function<gpu::TexturePointer(QImage&&, const std::string&, const std::atomic<bool>&)>; +using TextureLoader = std::function<gpu::TexturePointer(QImage&&, const std::string&, bool, const std::atomic<bool>&)>; TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap()); gpu::TexturePointer create2DTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createStrict2DTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createAlbedoTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createEmissiveTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createNormalTextureFromNormalImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createNormalTextureFromBumpImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createRoughnessTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createRoughnessTextureFromGlossImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createMetallicTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createCubeTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createCubeTextureFromImageWithoutIrradiance(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); gpu::TexturePointer createLightmapTextureFromImage(QImage&& image, const std::string& srcImageName, - const std::atomic<bool>& abortProcessing); + bool compress, const std::atomic<bool>& abortProcessing); -gpu::TexturePointer process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool isStrict, - const std::atomic<bool>& abortProcessing); -gpu::TexturePointer process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, bool isBumpMap, - const std::atomic<bool>& abortProcessing); -gpu::TexturePointer process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, bool isInvertedPixels, - const std::atomic<bool>& abortProcessing); -gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool generateIrradiance, - const std::atomic<bool>& abortProcessing); +gpu::TexturePointer process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress, + bool isStrict, const std::atomic<bool>& abortProcessing); +gpu::TexturePointer process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress, + bool isBumpMap, const std::atomic<bool>& abortProcessing); +gpu::TexturePointer process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress, + bool isInvertedPixels, const std::atomic<bool>& abortProcessing); +gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress, + bool generateIrradiance, const std::atomic<bool>& abortProcessing); } // namespace TextureUsage const QStringList getSupportedFormats(); -bool isColorTexturesCompressionEnabled(); -bool isNormalTexturesCompressionEnabled(); -bool isGrayscaleTexturesCompressionEnabled(); -bool isCubeTexturesCompressionEnabled(); - -void setColorTexturesCompressionEnabled(bool enabled); -void setNormalTexturesCompressionEnabled(bool enabled); -void setGrayscaleTexturesCompressionEnabled(bool enabled); -void setCubeTexturesCompressionEnabled(bool enabled); - -gpu::TexturePointer processImage(QByteArray&& content, const std::string& url, +gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::string& url, int maxNumPixels, TextureUsage::Type textureType, - const std::atomic<bool>& abortProcessing = false); + bool compress = true, const std::atomic<bool>& abortProcessing = false); } // namespace image diff --git a/libraries/ktx/src/TextureMeta.cpp b/libraries/ktx/src/TextureMeta.cpp index 3a2abf24c4..c8427c1f60 100644 --- a/libraries/ktx/src/TextureMeta.cpp +++ b/libraries/ktx/src/TextureMeta.cpp @@ -33,6 +33,9 @@ bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) { if (root.contains("original")) { meta->original = root["original"].toString(); } + if (root.contains("uncompressed")) { + meta->uncompressed = root["uncompressed"].toString(); + } if (root.contains("compressed")) { auto compressed = root["compressed"].toObject(); for (auto it = compressed.constBegin(); it != compressed.constEnd(); it++) { @@ -57,6 +60,7 @@ QByteArray TextureMeta::serialize() { compressed[name] = kv.second.toString(); } root["original"] = original.toString(); + root["uncompressed"] = uncompressed.toString(); root["compressed"] = compressed; doc.setObject(root); diff --git a/libraries/ktx/src/TextureMeta.h b/libraries/ktx/src/TextureMeta.h index 6582c29e70..5450fee110 100644 --- a/libraries/ktx/src/TextureMeta.h +++ b/libraries/ktx/src/TextureMeta.h @@ -35,6 +35,7 @@ struct TextureMeta { QByteArray serialize(); QUrl original; + QUrl uncompressed; std::unordered_map<khronos::gl::texture::InternalFormat, QUrl> availableTextureTypes; }; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index ed21fd35bc..40b31cac53 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -50,6 +50,8 @@ #include <TextureMeta.h> +#include <OwningBuffer.h> + Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image") Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw") Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx") @@ -277,7 +279,7 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path, image::Te return nullptr; } auto loader = image::TextureUsage::getTextureLoaderForType(type, options); - return gpu::TexturePointer(loader(std::move(image), path.toStdString(), false)); + return gpu::TexturePointer(loader(std::move(image), path.toStdString(), false, false)); } QSharedPointer<Resource> TextureCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback, @@ -964,7 +966,6 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) { return; } - auto& backend = DependencyManager::get<TextureCache>()->getGPUContext()->getBackend(); for (auto pair : meta.availableTextureTypes) { gpu::Element elFormat; @@ -990,6 +991,21 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) { } } +#ifndef Q_OS_ANDROID + if (!meta.uncompressed.isEmpty()) { + _currentlyLoadingResourceType = ResourceType::KTX; + _activeUrl = _activeUrl.resolved(meta.uncompressed); + + auto textureCache = DependencyManager::get<TextureCache>(); + auto self = _self.lock(); + if (!self) { + return; + } + QMetaObject::invokeMethod(this, "attemptRequest", Qt::QueuedConnection); + return; + } +#endif + if (!meta.original.isEmpty()) { _currentlyLoadingResourceType = ResourceType::ORIGINAL; _activeUrl = _activeUrl.resolved(meta.original); @@ -1143,7 +1159,8 @@ void ImageReader::read() { PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0); // IMPORTANT: _content is empty past this point - texture = image::processImage(std::move(_content), _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType()); + auto buffer = std::shared_ptr<QIODevice>((QIODevice*)new OwningBuffer(std::move(_content))); + texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType()); if (!texture) { qCWarning(modelnetworking) << "Could not process:" << _url; diff --git a/libraries/shared/src/OwningBuffer.h b/libraries/shared/src/OwningBuffer.h new file mode 100644 index 0000000000..80184286bc --- /dev/null +++ b/libraries/shared/src/OwningBuffer.h @@ -0,0 +1,29 @@ +// +// OwningBuffer.h +// shared/src +// +// Created by Ryan Huffman on 5/31/2018. +// Copyright 2018 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_OwningBuffer_h +#define hifi_OwningBuffer_h + +#include <QBuffer> +class OwningBuffer : public QBuffer { +public: + OwningBuffer(const QByteArray& content) : _content(content) { + setData(_content); + } + OwningBuffer(QByteArray&& content) : _content(std::move(content)) { + setData(_content); + } + +private: + QByteArray _content; +}; + +#endif // hifi_OwningBuffer_h diff --git a/tools/oven/src/Oven.cpp b/tools/oven/src/Oven.cpp index c3fec2d15e..52b6db1aa5 100644 --- a/tools/oven/src/Oven.cpp +++ b/tools/oven/src/Oven.cpp @@ -25,12 +25,6 @@ Oven* Oven::_staticInstance { nullptr }; Oven::Oven() { _staticInstance = this; - // enable compression in image library - image::setColorTexturesCompressionEnabled(true); - image::setGrayscaleTexturesCompressionEnabled(true); - image::setNormalTexturesCompressionEnabled(true); - image::setCubeTexturesCompressionEnabled(true); - // setup our worker threads setupWorkerThreads(QThread::idealThreadCount()); From e82edb8b66f521322a4bc2e056899ccd61dc02ea Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Wed, 6 Jun 2018 15:42:10 -0700 Subject: [PATCH 49/62] add domain packet dissector, improve entity dissector --- tools/dissectors/hf-domain.lua | 23 ++++++++++ tools/dissectors/hf-entity.lua | 81 +++++++++++++++++++++++++++++----- tools/dissectors/hfudt.lua | 65 ++++++++++++++++----------- 3 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 tools/dissectors/hf-domain.lua diff --git a/tools/dissectors/hf-domain.lua b/tools/dissectors/hf-domain.lua new file mode 100644 index 0000000000..093026bc92 --- /dev/null +++ b/tools/dissectors/hf-domain.lua @@ -0,0 +1,23 @@ +-- create the domain protocol +p_hf_domain = Proto("hf-domain", "HF Domain Protocol") + +-- domain packet fields +local f_domain_id = ProtoField.guid("hf_domain.domain_id", "Domain ID") +local f_domain_local_id = ProtoField.uint16("hf_domain.domain_local_id", "Domain Local ID") + +p_hf_domain.fields = { + f_domain_id, f_domain_local_id +} + +function p_hf_domain.dissector(buf, pinfo, tree) + pinfo.cols.protocol = p_hf_domain.name + + domain_subtree = tree:add(p_hf_domain, buf()) + + local i = 0 + + domain_subtree:add(f_domain_id, buf(i, 16)) + i = i + 16 + + domain_subtree:add_le(f_domain_local_id, buf(i, 2)) +end diff --git a/tools/dissectors/hf-entity.lua b/tools/dissectors/hf-entity.lua index f4de5a995d..51daa3497d 100644 --- a/tools/dissectors/hf-entity.lua +++ b/tools/dissectors/hf-entity.lua @@ -4,11 +4,21 @@ p_hf_entity = Proto("hf-entity", "HF Entity Protocol") -- entity packet fields local f_entity_sequence_number = ProtoField.uint16("hf_entity.sequence_number", "Sequence Number") local f_entity_timestamp = ProtoField.uint64("hf_entity.timestamp", "Timestamp") -local f_octal_code_bytes = ProtoField.uint8("hf_entity.octal_code_bytes", "Octal Code Bytes") +local f_octal_code_three_bit_sections = ProtoField.uint8("hf_entity.octal_code_three_bit_sections", "Octal Code Three Bit Sections") +local f_octal_code = ProtoField.bytes("hf_entity.octal_code", "Octal Code") local f_entity_id = ProtoField.guid("hf_entity.entity_id", "Entity ID") +local f_last_edited = ProtoField.uint64("hf_entity.last_edited", "Last Edited") +local f_coded_property_type = ProtoField.bytes("hf_entity.coded_property_type", "Coded Property Type") +local f_property_type = ProtoField.uint32("hf_entity.property_type", "Property Type") +local f_coded_update_delta = ProtoField.bytes("hf_entity.f_coded_update_delta", "Coded Update Delta") +local f_update_delta = ProtoField.uint32("hf_entity.update_delta", "Update Delta") p_hf_entity.fields = { - f_entity_sequence_number, f_entity_timestamp, f_octal_code_bytes, f_entity_id + f_entity_sequence_number, f_entity_timestamp, + f_octal_code_three_bit_sections, f_octal_code, + f_last_edited, f_entity_id, + f_coded_property_type, f_property_type, + f_coded_update_delta, f_update_delta } function p_hf_entity.dissector(buf, pinfo, tree) @@ -16,21 +26,72 @@ function p_hf_entity.dissector(buf, pinfo, tree) entity_subtree = tree:add(p_hf_entity, buf()) - i = 0 + local i = 0 entity_subtree:add_le(f_entity_sequence_number, buf(i, 2)) i = i + 2 - entity_subtree:add_le(f_entity_timestamp, buf(i, 4)) - i = i + 4 + entity_subtree:add_le(f_entity_timestamp, buf(i, 8)) + i = i + 8 - -- figure out the number of bytes the octal code takes - local octal_code_bytes = buf(i, 1):le_uint() - entity_subtree:add_le(f_octal_code_bytes, buf(i, 1)) + -- figure out the number of three bit sections in the octal code + local octal_code_three_bit_sections = buf(i, 1):le_uint() + entity_subtree:add_le(f_octal_code_three_bit_sections, buf(i, 1)) + i = i + 1 - -- skip over the octal code - i = i + 1 + octal_code_bytes + -- read the bytes for the octal code + local octal_code_bytes = math.ceil((octal_code_three_bit_sections * 3) / 8) + entity_subtree:add_le(f_octal_code, buf(i, octal_code_bytes)) + i = i + octal_code_bytes + + -- read the last edited timestamp + entity_subtree:add_le(f_last_edited, buf(i, 8)) + i = i + 8 -- read the entity ID entity_subtree:add(f_entity_id, buf(i, 16)) + i = i + 16 + + -- figure out the property type and the size of the coded value + local property_type, coded_property_bytes = number_of_coded_bytes(buf(i)) + entity_subtree:add(f_coded_property_type, buf(i, coded_property_bytes)) + entity_subtree:add(f_property_type, property_type) + i = i + coded_property_bytes + + -- figure out the update delta and the size of the coded value + local update_delta, coded_update_delta_bytes = number_of_coded_bytes(buf(i)) + entity_subtree:add(f_coded_update_delta, buf(i, coded_update_delta_bytes)) + entity_subtree:add(f_update_delta, update_delta) + i = i + coded_update_delta_bytes +end + +function number_of_coded_bytes(buf) + local coded_buffer = buf(0, 4):le_uint() -- max 64 bit value means max 10 header bits + + -- first figure out the total number of bytes for the coded value based + -- on the bits in the header + local total_coded_bytes = 1 + + for bit = 0, 10, 1 do + local header_bit = bit32.extract(coded_buffer, bit) + + if header_bit == 1 then + total_coded_bytes = total_coded_bytes + 1 + else + break + end + end + + -- pull out the bits and write them to our decoded value + local decoded_value = 0 + local decoded_position = 0 + local total_bits = total_coded_bytes * 8 + + for bit = total_coded_bytes, total_bits - 1, 1 do + local value_bit = bit32.extract(coded_buffer, total_bits - bit - 1) + decoded_value = bit32.replace(decoded_value, value_bit, decoded_position) + decoded_position = decoded_position + 1 + end + + return decoded_value, total_coded_bytes end diff --git a/tools/dissectors/hfudt.lua b/tools/dissectors/hfudt.lua index 9d2df801b2..c8b1d9feee 100644 --- a/tools/dissectors/hfudt.lua +++ b/tools/dissectors/hfudt.lua @@ -118,6 +118,10 @@ local packet_types = { [54] = "AssetGetInfoReply" } +local unsourced_packet_types = { + ["DomainList"] = true +} + function p_hfudt.dissector(buf, pinfo, tree) -- make sure this isn't a STUN packet - those don't follow HFUDT format @@ -230,54 +234,63 @@ function p_hfudt.dissector(buf, pinfo, tree) -- if the message bit is set, handle the second word if message_bit == 1 then - payload_offset = 12 + payload_offset = 12 - local second_word = buf(4, 4):le_uint() + local second_word = buf(4, 4):le_uint() - -- read message position from upper 2 bits - local message_position = bit32.rshift(second_word, 30) - local position = subtree:add(f_message_position, message_position) + -- read message position from upper 2 bits + local message_position = bit32.rshift(second_word, 30) + local position = subtree:add(f_message_position, message_position) - if message_positions[message_position] ~= nil then - -- if we know this position then add the name - position:append_text(" (".. message_positions[message_position] .. ")") - end + if message_positions[message_position] ~= nil then + -- if we know this position then add the name + position:append_text(" (".. message_positions[message_position] .. ")") + end - -- read message number from lower 30 bits - subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF)) + -- read message number from lower 30 bits + subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF)) - -- read the message part number - subtree:add(f_message_part_number, buf(8, 4):le_uint()) + -- read the message part number + subtree:add(f_message_part_number, buf(8, 4):le_uint()) end -- read the type local packet_type = buf(payload_offset, 1):le_uint() local ptype = subtree:add_le(f_type, buf(payload_offset, 1)) - if packet_types[packet_type] ~= nil then - subtree:add(f_type_text, packet_types[packet_type]) + local packet_type_text = packet_types[packet_type] + if packet_type_text ~= nil then + subtree:add(f_type_text, packet_type_text) -- if we know this packet type then add the name - ptype:append_text(" (".. packet_types[packet_type] .. ")") + ptype:append_text(" (".. packet_type_text .. ")") end - + -- read the version subtree:add_le(f_version, buf(payload_offset + 1, 1)) - -- read node local ID - local sender_id = buf(payload_offset + 2, 2) - subtree:add_le(f_sender_id, sender_id) + local i = payload_offset + 2 - local i = payload_offset + 4 + if unsourced_packet_types[packet_type_text] == nil then + -- read node local ID + local sender_id = buf(payload_offset + 2, 2) + subtree:add_le(f_sender_id, sender_id) + i = i + 2 - -- read HMAC MD5 hash - subtree:add(f_hmac_hash, buf(i, 16)) - i = i + 16 + -- read HMAC MD5 hash + subtree:add(f_hmac_hash, buf(i, 16)) + i = i + 16 + end + + -- Domain packets + if packet_type_text == "DomainList" then + Dissector.get("hf-domain"):call(buf(i):tvb(), pinfo, tree) + end -- AvatarData or BulkAvatarDataPacket - if packet_types[packet_type] == "AvatarData" or packet_types[packet_type] == "BulkAvatarDataPacket" then + if packet_type_text == "AvatarData" or packet_type_text == "BulkAvatarData" then Dissector.get("hf-avatar"):call(buf(i):tvb(), pinfo, tree) end - if packet_types[packet_type] == "EntityEdit" then + if packet_type_text == "EntityEdit" then Dissector.get("hf-entity"):call(buf(i):tvb(), pinfo, tree) end end From 24182d3451b828e659b55dd7199c807dc5a33a99 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 7 Jun 2018 15:27:50 -0700 Subject: [PATCH 50/62] Remove compression variables & functions in image.cpp --- libraries/image/src/image/Image.cpp | 56 ----------------------------- 1 file changed, 56 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 7faf811dec..f812e515de 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -48,11 +48,6 @@ std::atomic<size_t> RECTIFIED_TEXTURE_COUNT{ 0 }; static const auto HDR_FORMAT = gpu::Element::COLOR_R11G11B10; -static std::atomic<bool> compressColorTextures { false }; -static std::atomic<bool> compressNormalTextures { false }; -static std::atomic<bool> compressGrayscaleTextures { false }; -static std::atomic<bool> compressCubeTextures { false }; - uint rectifyDimension(const uint& dimension) { if (dimension == 0) { return 0; @@ -185,55 +180,6 @@ gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(QI return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing); } - -bool isColorTexturesCompressionEnabled() { -#if CPU_MIPMAPS - return compressColorTextures.load(); -#else - return false; -#endif -} - -bool isNormalTexturesCompressionEnabled() { -#if CPU_MIPMAPS - return compressNormalTextures.load(); -#else - return false; -#endif -} - -bool isGrayscaleTexturesCompressionEnabled() { -#if CPU_MIPMAPS - return compressGrayscaleTextures.load(); -#else - return false; -#endif -} - -bool isCubeTexturesCompressionEnabled() { -#if CPU_MIPMAPS - return compressCubeTextures.load(); -#else - return false; -#endif -} - -void setColorTexturesCompressionEnabled(bool enabled) { - compressColorTextures.store(enabled); -} - -void setNormalTexturesCompressionEnabled(bool enabled) { - compressNormalTextures.store(enabled); -} - -void setGrayscaleTexturesCompressionEnabled(bool enabled) { - compressGrayscaleTextures.store(enabled); -} - -void setCubeTexturesCompressionEnabled(bool enabled) { - compressCubeTextures.store(enabled); -} - static float denormalize(float value, const float minValue) { return value < minValue ? 0.0f : value; } @@ -956,7 +902,6 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatMip; gpu::Element formatGPU; - if (isNormalTexturesCompressionEnabled()) { if (compress) { formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY; } else { @@ -997,7 +942,6 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatMip; gpu::Element formatGPU; - if (isGrayscaleTexturesCompressionEnabled()) { if (compress) { formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED; } else { From 3e65e0b0cd914b43d1aa640a6b7a91d0f52d663b Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Fri, 8 Jun 2018 13:21:47 -0700 Subject: [PATCH 51/62] Update processImage to not compress by default --- libraries/image/src/image/Image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 3dca8f5586..ccf4845fca 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -84,7 +84,7 @@ const QStringList getSupportedFormats(); gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::string& url, int maxNumPixels, TextureUsage::Type textureType, - bool compress = true, const std::atomic<bool>& abortProcessing = false); + bool compress = false, const std::atomic<bool>& abortProcessing = false); } // namespace image From a2399ea1f637a798a80aaa788a753d7936d73e1e Mon Sep 17 00:00:00 2001 From: Seth Alves <seth.alves@gmail.com> Date: Fri, 8 Jun 2018 16:07:01 -0700 Subject: [PATCH 52/62] keep small masses from introducing NaN into bullet's calculations --- libraries/physics/src/PhysicsEngine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 83ffa21a55..1a258c0fc3 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -105,6 +105,10 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { } case MOTION_TYPE_DYNAMIC: { mass = motionState->getMass(); + if (mass != mass || mass < 1.0f) { + qCDebug(physics) << "mass is too low, setting to 1.0 Kg --" << mass; + mass = 1.0f; + } btCollisionShape* shape = const_cast<btCollisionShape*>(motionState->getShape()); assert(shape); shape->calculateLocalInertia(mass, inertia); From 9506e7edbe75d7a33805767ac554286ab8957ec0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Fri, 8 Jun 2018 14:47:20 -0700 Subject: [PATCH 53/62] check for update for dev-builds, handle semantic version --- interface/src/Application.cpp | 7 +- interface/src/ui/UpdateDialog.cpp | 36 +++++--- libraries/auto-updater/src/AutoUpdater.cpp | 68 ++++++++++----- libraries/auto-updater/src/AutoUpdater.h | 17 ++-- libraries/shared/src/ApplicationVersion.cpp | 94 +++++++++++++++++++++ libraries/shared/src/ApplicationVersion.h | 41 +++++++++ 6 files changed, 220 insertions(+), 43 deletions(-) create mode 100644 libraries/shared/src/ApplicationVersion.cpp create mode 100644 libraries/shared/src/ApplicationVersion.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c5857dac53..4a785db2c2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -905,7 +905,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set<DiscoverabilityManager>(); DependencyManager::set<SceneScriptingInterface>(); DependencyManager::set<OffscreenUi>(); - DependencyManager::set<AutoUpdater>(); DependencyManager::set<Midi>(); DependencyManager::set<PathUtils>(); DependencyManager::set<InterfaceDynamicFactory>(); @@ -1784,10 +1783,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // If launched from Steam, let it handle updates const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater"; bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1; - if (!noUpdater) { + bool buildCanUpdate = BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable + || BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Master; + if (!noUpdater && buildCanUpdate) { constexpr auto INSTALLER_TYPE_CLIENT_ONLY = "client_only"; - auto applicationUpdater = DependencyManager::get<AutoUpdater>(); + auto applicationUpdater = DependencyManager::set<AutoUpdater>(); AutoUpdater::InstallerType type = installerType == INSTALLER_TYPE_CLIENT_ONLY ? AutoUpdater::InstallerType::CLIENT_ONLY : AutoUpdater::InstallerType::FULL; diff --git a/interface/src/ui/UpdateDialog.cpp b/interface/src/ui/UpdateDialog.cpp index 2dcc0c07eb..7ff2132ab9 100644 --- a/interface/src/ui/UpdateDialog.cpp +++ b/interface/src/ui/UpdateDialog.cpp @@ -21,19 +21,31 @@ UpdateDialog::UpdateDialog(QQuickItem* parent) : OffscreenQmlDialog(parent) { auto applicationUpdater = DependencyManager::get<AutoUpdater>(); - int currentVersion = QCoreApplication::applicationVersion().toInt(); - int latestVersion = applicationUpdater.data()->getBuildData().lastKey(); - _updateAvailableDetails = "v" + QString::number(latestVersion) + " released on " - + QString(applicationUpdater.data()->getBuildData()[latestVersion]["releaseTime"]).replace(" ", " "); + if (applicationUpdater) { - _releaseNotes = ""; - for (int i = latestVersion; i > currentVersion; i--) { - if (applicationUpdater.data()->getBuildData().contains(i)) { - QString releaseNotes = applicationUpdater.data()->getBuildData()[i]["releaseNotes"]; - releaseNotes.remove("<br />"); - releaseNotes.remove(QRegExp("^\n+")); - _releaseNotes += "\n" + QString().sprintf("%d", i) + "\n" + releaseNotes + "\n"; + auto buildData = applicationUpdater.data()->getBuildData(); + ApplicationVersion latestVersion = buildData.lastKey(); + _updateAvailableDetails = "v" + latestVersion.versionString + " released on " + + QString(buildData[latestVersion]["releaseTime"]).replace(" ", " "); + + _releaseNotes = ""; + + auto it = buildData.end(); + while (it != buildData.begin()) { + --it; + + if (applicationUpdater->getCurrentVersion() < it.key()) { + // grab the release notes for this later version + QString releaseNotes = it.value()["releaseNotes"]; + releaseNotes.remove("<br />"); + releaseNotes.remove(QRegExp("^\n+")); + _releaseNotes += "\n" + it.key().versionString + "\n" + releaseNotes + "\n"; + } else { + break; + } } + + } } @@ -47,5 +59,5 @@ const QString& UpdateDialog::releaseNotes() const { void UpdateDialog::triggerUpgrade() { auto applicationUpdater = DependencyManager::get<AutoUpdater>(); - applicationUpdater.data()->performAutoUpdate(applicationUpdater.data()->getBuildData().lastKey()); + applicationUpdater.data()->openLatestUpdateURL(); } diff --git a/libraries/auto-updater/src/AutoUpdater.cpp b/libraries/auto-updater/src/AutoUpdater.cpp index 6749cd9e10..300a22983a 100644 --- a/libraries/auto-updater/src/AutoUpdater.cpp +++ b/libraries/auto-updater/src/AutoUpdater.cpp @@ -11,13 +11,16 @@ #include "AutoUpdater.h" -#include <BuildInfo.h> - -#include <NetworkAccessManager.h> -#include <SharedUtil.h> #include <unordered_map> -AutoUpdater::AutoUpdater() { +#include <ApplicationVersion.h> +#include <BuildInfo.h> +#include <NetworkAccessManager.h> +#include <SharedUtil.h> + +AutoUpdater::AutoUpdater() : + _currentVersion(BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? BuildInfo::VERSION : BuildInfo::BUILD_NUMBER) +{ #if defined Q_OS_WIN32 _operatingSystem = "windows"; #elif defined Q_OS_MAC @@ -33,9 +36,22 @@ void AutoUpdater::checkForUpdate() { this->getLatestVersionData(); } +const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml"); +const QUrl MASTER_BUILDS_XML_URL("https://highfidelity.com/dev-builds.xml"); + void AutoUpdater::getLatestVersionData() { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest latestVersionRequest(BUILDS_XML_URL); + + QUrl buildsURL; + + if (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable) { + buildsURL = BUILDS_XML_URL; + } else if (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Master) { + buildsURL = MASTER_BUILDS_XML_URL; + } + + QNetworkRequest latestVersionRequest(buildsURL); + latestVersionRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); QNetworkReply* reply = networkAccessManager.get(latestVersionRequest); @@ -52,12 +68,22 @@ void AutoUpdater::parseLatestVersionData() { QString clientOnly; }; - int version { 0 }; + QString version; QString downloadUrl; QString releaseTime; QString releaseNotes; QString commitSha; QString pullRequestNumber; + + QString versionKey; + + // stable builds look at the stable_version node (semantic version) + // master builds look at the version node (build number) + if (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable) { + versionKey = "stable_version"; + } else if (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Master) { + versionKey = "version"; + } while (xml.readNextStartElement()) { if (xml.name() == "projects") { @@ -77,8 +103,8 @@ void AutoUpdater::parseLatestVersionData() { QHash<QString, InstallerURLs> campaignInstallers; while (xml.readNextStartElement()) { - if (xml.name() == "version") { - version = xml.readElementText().toInt(); + if (xml.name() == versionKey) { + version = xml.readElementText(); } else if (xml.name() == "url") { downloadUrl = xml.readElementText(); } else if (xml.name() == "installers") { @@ -159,31 +185,31 @@ void AutoUpdater::parseLatestVersionData() { } void AutoUpdater::checkVersionAndNotify() { - if (BuildInfo::BUILD_TYPE != BuildInfo::BuildType::Stable || _builds.empty()) { - // No version checking is required in nightly/PR/dev builds or when no build - // data was found for the platform + if (_builds.empty()) { + // no build data was found for this platform return; } - int latestVersionAvailable = _builds.lastKey(); - if (QCoreApplication::applicationVersion().toInt() < latestVersionAvailable) { + + qDebug() << "Checking if update version" << _builds.lastKey().versionString + << "is newer than current version" << _currentVersion.versionString; + + if (_builds.lastKey() > _currentVersion) { emit newVersionIsAvailable(); } } -void AutoUpdater::performAutoUpdate(int version) { - // NOTE: This is not yet auto updating - however this is a checkpoint towards that end - // Next PR will handle the automatic download, upgrading and application restart - const QMap<QString, QString>& chosenVersion = _builds.value(version); +void AutoUpdater::openLatestUpdateURL() { + const QMap<QString, QString>& chosenVersion = _builds.last(); const QUrl& downloadUrl = chosenVersion.value("downloadUrl"); QDesktopServices::openUrl(downloadUrl); QCoreApplication::quit(); } -void AutoUpdater::downloadUpdateVersion(int version) { +void AutoUpdater::downloadUpdateVersion(const QString& version) { emit newVersionIsDownloaded(); } -void AutoUpdater::appendBuildData(int versionNumber, +void AutoUpdater::appendBuildData(const QString& versionNumber, const QString& downloadURL, const QString& releaseTime, const QString& releaseNotes, @@ -194,6 +220,6 @@ void AutoUpdater::appendBuildData(int versionNumber, thisBuildDetails.insert("releaseTime", releaseTime); thisBuildDetails.insert("releaseNotes", releaseNotes); thisBuildDetails.insert("pullRequestNumber", pullRequestNumber); - _builds.insert(versionNumber, thisBuildDetails); + _builds.insert(ApplicationVersion(versionNumber), thisBuildDetails); } diff --git a/libraries/auto-updater/src/AutoUpdater.h b/libraries/auto-updater/src/AutoUpdater.h index f56d7993e9..c788ac31d1 100644 --- a/libraries/auto-updater/src/AutoUpdater.h +++ b/libraries/auto-updater/src/AutoUpdater.h @@ -26,10 +26,9 @@ #include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkRequest> +#include <ApplicationVersion.h> #include <DependencyManager.h> -const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml"); - class AutoUpdater : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -43,25 +42,29 @@ public: }; void checkForUpdate(); - const QMap<int, QMap<QString, QString>>& getBuildData() { return _builds; } - void performAutoUpdate(int version); + const QMap<ApplicationVersion, QMap<QString, QString>>& getBuildData() { return _builds; } + void openLatestUpdateURL(); void setInstallerType(InstallerType type) { _installerType = type; } void setInstallerCampaign(QString campaign) { _installerCampaign = campaign; } + const ApplicationVersion& getCurrentVersion() const { return _currentVersion; } + signals: void latestVersionDataParsed(); void newVersionIsAvailable(); void newVersionIsDownloaded(); private: - QMap<int, QMap<QString, QString>> _builds; + QMap<ApplicationVersion, QMap<QString, QString>> _builds; QString _operatingSystem; InstallerType _installerType { InstallerType::FULL }; QString _installerCampaign { "" }; + + ApplicationVersion _currentVersion; void getLatestVersionData(); - void downloadUpdateVersion(int version); - void appendBuildData(int versionNumber, + void downloadUpdateVersion(const QString& version); + void appendBuildData(const QString& versionNumber, const QString& downloadURL, const QString& releaseTime, const QString& releaseNotes, diff --git a/libraries/shared/src/ApplicationVersion.cpp b/libraries/shared/src/ApplicationVersion.cpp new file mode 100644 index 0000000000..5c2d5ad11c --- /dev/null +++ b/libraries/shared/src/ApplicationVersion.cpp @@ -0,0 +1,94 @@ +// +// ApplicationVersion.cpp +// libraries/shared/src +// +// Created by Stephen Birarda on 6/8/18. +// Copyright 2018 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 "ApplicationVersion.h" + +#include <cassert> + +#include <QtCore/QDebug> +#include <QtCore/QRegExp> +#include <QtCore/QStringList> + +ApplicationVersion::ApplicationVersion(const QString& versionString) : + versionString(versionString) +{ + // attempt to regex out a semantic version from the string + // handling both x.y.z and x.y formats + QRegExp semanticRegex("([\\d]+)\\.([\\d]+)(?:\\.([\\d]+))?"); + + int pos = semanticRegex.indexIn(versionString); + if (pos != -1) { + isSemantic = true; + auto captures = semanticRegex.capturedTexts(); + + major = captures[1].toInt(); + minor = captures[2].toInt(); + + if (captures.length() > 3) { + patch = captures[3].toInt(); + } else { + // the patch is implictly 0 if it was not included + patch = 0; + } + } else { + // if we didn't have a sematic style, we assume that we just have a build number + build = versionString.toInt(); + } +} + +bool ApplicationVersion::operator==(const ApplicationVersion& other) const { + if (isSemantic && other.isSemantic) { + return major == other.major && minor == other.minor && patch == other.patch; + } else if (!isSemantic && !other.isSemantic) { + return build == other.build; + } else { + assert(isSemantic == other.isSemantic); + return false; + } +} + +bool ApplicationVersion::operator<(const ApplicationVersion& other) const { + if (isSemantic && other.isSemantic) { + if (major == other.major) { + if (minor == other.minor) { + return patch < other.patch; + } else { + return minor < other.minor; + } + } else { + return major < other.major; + } + } else if (!isSemantic && !other.isSemantic) { + return build < other.build; + } else { + assert(isSemantic == other.isSemantic); + return false; + } +} + +bool ApplicationVersion::operator>(const ApplicationVersion& other) const { + if (isSemantic && other.isSemantic) { + if (major == other.major) { + if (minor == other.minor) { + return patch > other.patch; + } else { + return minor > other.minor; + } + } else { + return major > other.major; + } + } else if (!isSemantic && !other.isSemantic) { + return build > other.build; + } else { + assert(isSemantic == other.isSemantic); + return false; + } +} diff --git a/libraries/shared/src/ApplicationVersion.h b/libraries/shared/src/ApplicationVersion.h new file mode 100644 index 0000000000..5cb0a09a8d --- /dev/null +++ b/libraries/shared/src/ApplicationVersion.h @@ -0,0 +1,41 @@ +// +// ApplicationVersion.h +// libraries/shared/src +// +// Created by Stephen Birarda on 6/8/18. +// Copyright 2018 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_ApplicationVersion_h +#define hifi_ApplicationVersion_h + +#include <QtCore/QString> + +class ApplicationVersion { +public: + ApplicationVersion(const QString& versionString); + + bool operator==(const ApplicationVersion& other) const; + bool operator!=(const ApplicationVersion& other) const { return !(*this == other); } + + bool operator <(const ApplicationVersion& other) const; + bool operator >(const ApplicationVersion& other) const; + + bool operator >=(const ApplicationVersion& other) const { return (*this == other) || (*this > other); } + bool operator <=(const ApplicationVersion& other) const { return (*this == other) || (*this < other); } + + int major = -1; + int minor = -1; + int patch = -1; + + int build = -1; + + bool isSemantic { false }; + + QString versionString; +}; + +#endif // hifi_ApplicationVersion_h From 8dd268addbf4777a53f1d5a525d0437d9c1cfff3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Fri, 8 Jun 2018 17:13:04 -0700 Subject: [PATCH 54/62] handle semantic version updates in sandbox --- cmake/templates/console-build-info.json.in | 4 +- server-console/src/main.js | 55 +++++++++-------- server-console/src/modules/hf-updater.js | 70 ++++++++++++++++++++-- 3 files changed, 94 insertions(+), 35 deletions(-) diff --git a/cmake/templates/console-build-info.json.in b/cmake/templates/console-build-info.json.in index 6b4ee99292..e8cd8eee22 100644 --- a/cmake/templates/console-build-info.json.in +++ b/cmake/templates/console-build-info.json.in @@ -1,5 +1,7 @@ { "releaseType": "@RELEASE_TYPE@", + "buildNumber": "@BUILD_NUMBER@", + "stableBuild": "@STABLE_BUILD@", "buildIdentifier": "@BUILD_VERSION@", - "organization": "@BUILD_ORGANIZATION@" + "organization": "@BUILD_ORGANIZATION@" } diff --git a/server-console/src/main.js b/server-console/src/main.js index 8a92fc8a5d..f9c72ddf8a 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -60,7 +60,14 @@ function getBuildInfo() { } } - const DEFAULT_BUILD_INFO = { releaseType: "", buildIdentifier: "dev" }; + const DEFAULT_BUILD_INFO = { + releaseType: "", + buildIdentifier: "dev", + buildNumber: "0", + stableBuild: "0", + organization: "High Fidelity - dev" + }; + var buildInfo = DEFAULT_BUILD_INFO; if (buildInfoPath) { @@ -858,33 +865,25 @@ function onContentLoaded() { // maybeShowSplash(); if (buildInfo.releaseType == 'PRODUCTION' && !argv.noUpdater) { - var currentVersion = null; - try { - currentVersion = parseInt(buildInfo.buildIdentifier); - } catch (e) { - } - - if (currentVersion !== null) { - const CHECK_FOR_UPDATES_INTERVAL_SECONDS = 60 * 30; - var hasShownUpdateNotification = false; - const updateChecker = new updater.UpdateChecker(currentVersion, CHECK_FOR_UPDATES_INTERVAL_SECONDS); - updateChecker.on('update-available', function(latestVersion, url) { - if (!hasShownUpdateNotification) { - notifier.notify({ - icon: notificationIcon, - title: 'An update is available!', - message: 'High Fidelity version ' + latestVersion + ' is available', - wait: true, - url: url - }); - hasShownUpdateNotification = true; - } - }); - notifier.on('click', function(notifierObject, options) { - log.debug("Got click", options.url); - shell.openExternal(options.url); - }); - } + const CHECK_FOR_UPDATES_INTERVAL_SECONDS = 60 * 30; + var hasShownUpdateNotification = false; + const updateChecker = new updater.UpdateChecker(buildInfo, CHECK_FOR_UPDATES_INTERVAL_SECONDS); + updateChecker.on('update-available', function(latestVersion, url) { + if (!hasShownUpdateNotification) { + notifier.notify({ + icon: notificationIcon, + title: 'An update is available!', + message: 'High Fidelity version ' + latestVersion + ' is available', + wait: true, + url: url + }); + hasShownUpdateNotification = true; + } + }); + notifier.on('click', function(notifierObject, options) { + log.debug("Got click", options.url); + shell.openExternal(options.url); + }); } deleteOldFiles(logPath, DELETE_LOG_FILES_OLDER_THAN_X_SECONDS, LOG_FILE_REGEX); diff --git a/server-console/src/modules/hf-updater.js b/server-console/src/modules/hf-updater.js index 489364f655..d20da3c663 100644 --- a/server-console/src/modules/hf-updater.js +++ b/server-console/src/modules/hf-updater.js @@ -8,10 +8,48 @@ const os = require('os'); const platform = os.type() == 'Windows_NT' ? 'windows' : 'mac'; const BUILDS_URL = 'https://highfidelity.com/builds.xml'; +const DEV_BUILDS_URL = 'https://highfidelity.com/dev-builds.xml'; -function UpdateChecker(currentVersion, checkForUpdatesEveryXSeconds) { - this.currentVersion = currentVersion; - log.debug('cur', currentVersion); +// returns 1 if A is greater, 0 if equal, -1 if A is lesser +function semanticVersionCompare(versionA, versionB) { + var versionAParts = versionA.split('.'); + var versionBParts = versionB.split('.'); + + // make sure each version has 3 parts + var partsLength = versionAParts.length; + while (partsLength < 3) { + partsLength = versionAParts.push(0); + } + + partsLength = versionBParts.length; + while (partsLength < 3) { + partsLength = versionBParts.push(0); + } + + // map all of the parts to numbers + versionAParts = versionAParts.map(Number); + versionBParts = versionBParts.map(Number); + + for (var i = 0; i < 3; ++i) { + if (versionAParts[i] == versionBParts[i]) { + continue; + } else if (versionAParts[i] > versionBParts[i]) { + return 1; + } else { + return -1; + } + } + + return 0; +} + +function UpdateChecker(buildInfo, checkForUpdatesEveryXSeconds) { + this.stableBuild = (buildInfo.stableBuild == "1"); + + this.buildsURL = this.stableBuild ? BUILDS_URL : DEV_BUILDS_URL; + this.currentVersion = this.stableBuild ? buildInfo.buildIdentifier : parseInt(buildInfo.buildNumber); + + log.debug('Current version is', this.currentVersion); setInterval(this.checkForUpdates.bind(this), checkForUpdatesEveryXSeconds * 1000); this.checkForUpdates(); @@ -29,12 +67,32 @@ UpdateChecker.prototype = extend(UpdateChecker.prototype, { try { var $ = cheerio.load(body, { xmlMode: true }); const latestBuild = $('project[name="interface"] platform[name="' + platform + '"]').children().first(); - const latestVersion = parseInt(latestBuild.find('version').text()); - log.debug("Latest version is:", latestVersion, this.currentVersion); - if (latestVersion > this.currentVersion) { + + var latestVersion = 0; + + if (this.stableBuild) { + latestVersion = latestBuild.find('stable_version').text(); + } else { + latestVersion = parseInt(latestBuild.find('version').text()); + } + + log.debug("Latest available update version is:", latestVersion); + + updateAvailable = false; + + if (this.stableBuild) { + // compare the semantic versions to see if the update is newer + updateAvailable = (semanticVersionCompare(latestVersion, this.currentVersion) == 1); + } else { + // for master builds we just compare the versions as integers + updateAvailable = latestVersion > this.currentVersion; + } + + if (updateAvailable) { const url = latestBuild.find('url').text(); this.emit('update-available', latestVersion, url); } + } catch (e) { log.warn("Error when checking for updates", e); } From 7a9d77d0d9fa032c20c62d5b647418ff9278a7a2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Fri, 8 Jun 2018 17:15:27 -0700 Subject: [PATCH 55/62] force git abbreviated SHA to have length of 7 --- cmake/macros/SetPackagingParameters.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 029c829022..ef96e989d8 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -95,7 +95,7 @@ macro(SET_PACKAGING_PARAMETERS) endif () execute_process( - COMMAND git log -1 --format=${_GIT_LOG_FORMAT} + COMMAND git log -1 --abbrev=7 --format=${_GIT_LOG_FORMAT} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE _GIT_LOG_OUTPUT ERROR_VARIABLE _GIT_LOG_ERROR From 015c092e1c08d7d15a342bae3fb6855e17a9cc7e Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Mon, 11 Jun 2018 16:37:40 -0700 Subject: [PATCH 56/62] Update oven to only produce uncompressed ktx for cubemaps --- libraries/baking/src/TextureBaker.cpp | 8 ++++++-- libraries/baking/src/TextureBaker.h | 4 ++++ tools/oven/src/OvenCLIApplication.cpp | 6 ++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index 4f42ad627c..ecfe724441 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -30,6 +30,8 @@ const QString BAKED_TEXTURE_KTX_EXT = ".ktx"; const QString BAKED_TEXTURE_BCN_SUFFIX = "_bcn.ktx"; const QString BAKED_META_TEXTURE_SUFFIX = ".texmeta.json"; +bool TextureBaker::_compressionEnabled = true; + TextureBaker::TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, const QDir& outputDirectory, const QString& metaTexturePathPrefix, const QString& baseFilename, const QByteArray& textureContent) : @@ -146,7 +148,7 @@ void TextureBaker::processTexture() { } // Compressed KTX - { + if (_compressionEnabled) { auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, _abortProcessing); if (!processedTexture) { @@ -186,7 +188,7 @@ void TextureBaker::processTexture() { } // Uncompressed KTX - { + if (_textureType == image::TextureUsage::Type::CUBE_TEXTURE) { buffer->reset(); auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, _abortProcessing); @@ -218,6 +220,8 @@ void TextureBaker::processTexture() { } _outputFiles.push_back(filePath); meta.uncompressed = _metaTexturePathPrefix + fileName; + } else { + buffer.reset(); } { diff --git a/libraries/baking/src/TextureBaker.h b/libraries/baking/src/TextureBaker.h index 54839c001a..c8c4fb73b8 100644 --- a/libraries/baking/src/TextureBaker.h +++ b/libraries/baking/src/TextureBaker.h @@ -41,6 +41,8 @@ public: virtual void setWasAborted(bool wasAborted) override; + static void setCompressionEnabled(bool enabled) { _compressionEnabled = enabled; } + public slots: virtual void bake() override; virtual void abort() override; @@ -65,6 +67,8 @@ private: QString _metaTexturePathPrefix; std::atomic<bool> _abortProcessing { false }; + + static bool _compressionEnabled; }; #endif // hifi_TextureBaker_h diff --git a/tools/oven/src/OvenCLIApplication.cpp b/tools/oven/src/OvenCLIApplication.cpp index 6f87359134..c405c5f4a0 100644 --- a/tools/oven/src/OvenCLIApplication.cpp +++ b/tools/oven/src/OvenCLIApplication.cpp @@ -15,6 +15,7 @@ #include <QtCore/QUrl> #include <image/Image.h> +#include <TextureBaker.h> #include "BakerCLI.h" @@ -47,10 +48,7 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) : if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) { qDebug() << "Disabling texture compression"; - image::setColorTexturesCompressionEnabled(false); - image::setGrayscaleTexturesCompressionEnabled(false); - image::setNormalTexturesCompressionEnabled(false); - image::setCubeTexturesCompressionEnabled(false); + TextureBaker::setCompressionEnabled(false); } QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl), From d31ee52d794b811f193af54583d32afb9b57bc89 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Tue, 12 Jun 2018 03:51:55 -0700 Subject: [PATCH 57/62] revert PR-13162 from RC68 --- interface/src/avatar/AvatarMotionState.cpp | 47 +++++-------------- interface/src/avatar/AvatarMotionState.h | 6 --- .../src/avatars-renderer/Avatar.cpp | 14 +++--- libraries/physics/src/ObjectMotionState.h | 2 +- 4 files changed, 19 insertions(+), 50 deletions(-) diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index beb7e34439..900c1c0a11 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -21,17 +21,6 @@ AvatarMotionState::AvatarMotionState(AvatarSharedPointer avatar, const btCollisi _type = MOTIONSTATE_TYPE_AVATAR; } -void AvatarMotionState::handleEasyChanges(uint32_t& flags) { - ObjectMotionState::handleEasyChanges(flags); - if (flags & Simulation::DIRTY_PHYSICS_ACTIVATION && !_body->isActive()) { - _body->activate(); - } -} - -bool AvatarMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) { - return ObjectMotionState::handleHardAndEasyChanges(flags, engine); -} - AvatarMotionState::~AvatarMotionState() { assert(_avatar); _avatar = nullptr; @@ -57,9 +46,6 @@ PhysicsMotionType AvatarMotionState::computePhysicsMotionType() const { const btCollisionShape* AvatarMotionState::computeNewShape() { ShapeInfo shapeInfo; std::static_pointer_cast<Avatar>(_avatar)->computeShapeInfo(shapeInfo); - glm::vec3 halfExtents = shapeInfo.getHalfExtents(); - halfExtents.y = 0.0f; - _diameter = 2.0f * glm::length(halfExtents); return getShapeManager()->getShape(shapeInfo); } @@ -74,31 +60,25 @@ void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const { worldTrans.setRotation(glmToBullet(getObjectRotation())); if (_body) { _body->setLinearVelocity(glmToBullet(getObjectLinearVelocity())); - _body->setAngularVelocity(glmToBullet(getObjectAngularVelocity())); + _body->setAngularVelocity(glmToBullet(getObjectLinearVelocity())); } } // virtual void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) { + // HACK: The PhysicsEngine does not actually move OTHER avatars -- instead it slaves their local RigidBody to the transform + // as specified by a remote simulation. However, to give the remote simulation time to respond to our own objects we tie + // the other avatar's body to its true position with a simple spring. This is a HACK that will have to be improved later. const float SPRING_TIMESCALE = 0.5f; float tau = PHYSICS_ENGINE_FIXED_SUBSTEP / SPRING_TIMESCALE; btVector3 currentPosition = worldTrans.getOrigin(); - btVector3 offsetToTarget = glmToBullet(getObjectPosition()) - currentPosition; - float distance = offsetToTarget.length(); - if ((1.0f - tau) * distance > _diameter) { - // the avatar body is far from its target --> slam position - btTransform newTransform; - newTransform.setOrigin(currentPosition + offsetToTarget); - newTransform.setRotation(glmToBullet(getObjectRotation())); - _body->setWorldTransform(newTransform); - _body->setLinearVelocity(glmToBullet(getObjectLinearVelocity())); - _body->setAngularVelocity(glmToBullet(getObjectAngularVelocity())); - } else { - // the avatar body is near its target --> slam velocity - btVector3 velocity = glmToBullet(getObjectLinearVelocity()) + (1.0f / SPRING_TIMESCALE) * offsetToTarget; - _body->setLinearVelocity(velocity); - _body->setAngularVelocity(glmToBullet(getObjectAngularVelocity())); - } + btVector3 targetPosition = glmToBullet(getObjectPosition()); + btTransform newTransform; + newTransform.setOrigin((1.0f - tau) * currentPosition + tau * targetPosition); + newTransform.setRotation(glmToBullet(getObjectRotation())); + _body->setWorldTransform(newTransform); + _body->setLinearVelocity(glmToBullet(getObjectLinearVelocity())); + _body->setAngularVelocity(glmToBullet(getObjectLinearVelocity())); } // These pure virtual methods must be implemented for each MotionState type @@ -165,8 +145,3 @@ void AvatarMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma mask = Physics::getDefaultCollisionMask(group); } -// virtual -float AvatarMotionState::getMass() const { - return std::static_pointer_cast<Avatar>(_avatar)->computeMass(); -} - diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 73fb853312..90bd2a60ac 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -23,9 +23,6 @@ class AvatarMotionState : public ObjectMotionState { public: AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape); - virtual void handleEasyChanges(uint32_t& flags) override; - virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override; - virtual PhysicsMotionType getMotionType() const override { return _motionType; } virtual uint32_t getIncomingDirtyFlags() override; @@ -67,8 +64,6 @@ public: virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; - virtual float getMass() const override; - friend class AvatarManager; friend class Avatar; @@ -81,7 +76,6 @@ protected: virtual const btCollisionShape* computeNewShape() override; AvatarSharedPointer _avatar; - float _diameter { 0.0f }; uint32_t _dirtyFlags; }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index da829b23e4..048b8b1633 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -799,6 +799,7 @@ bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const { return true; } +// virtual void Avatar::simulateAttachments(float deltaTime) { assert(_attachmentModels.size() == _attachmentModelsTexturesLoaded.size()); PerformanceTimer perfTimer("attachments"); @@ -1481,14 +1482,12 @@ void Avatar::updateDisplayNameAlpha(bool showDisplayName) { } } +// virtual void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { float uniformScale = getModelScale(); - float radius = uniformScale * _skeletonModel->getBoundingCapsuleRadius(); - float height = uniformScale * _skeletonModel->getBoundingCapsuleHeight(); - shapeInfo.setCapsuleY(radius, 0.5f * height); - - glm::vec3 offset = uniformScale * _skeletonModel->getBoundingCapsuleOffset(); - shapeInfo.setOffset(offset); + shapeInfo.setCapsuleY(uniformScale * _skeletonModel->getBoundingCapsuleRadius(), + 0.5f * uniformScale * _skeletonModel->getBoundingCapsuleHeight()); + shapeInfo.setOffset(uniformScale * _skeletonModel->getBoundingCapsuleOffset()); } void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) { @@ -1511,8 +1510,9 @@ float Avatar::computeMass() { return _density * TWO_PI * radius * radius * (glm::length(end - start) + 2.0f * radius / 3.0f); } +// virtual void Avatar::rebuildCollisionShape() { - addPhysicsFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); + addPhysicsFlags(Simulation::DIRTY_SHAPE); } void Avatar::setPhysicsCallback(AvatarPhysicsCallback cb) { diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index e1cf5a4285..fbda9366fc 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -111,7 +111,7 @@ public: virtual PhysicsMotionType getMotionType() const { return _motionType; } void setMass(float mass); - virtual float getMass() const; + float getMass() const; void setBodyLinearVelocity(const glm::vec3& velocity) const; void setBodyAngularVelocity(const glm::vec3& velocity) const; From 649ffbe259d0563b41bea09ec356b875e1b483cc Mon Sep 17 00:00:00 2001 From: Gabriel <gcalero1984@gmail.com> Date: Tue, 12 Jun 2018 16:15:54 -0300 Subject: [PATCH 58/62] Don't hide jump button while moving --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 09b9b7f8f9..d8b8cbd54a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -151,11 +151,9 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.setModelTransform(stickTransform); batch.draw(gpu::TRIANGLE_STRIP, 4); - if (!virtualPadManager.getLeftVirtualPad()->isBeingTouched()) { - batch.setResourceTexture(0, _virtualPadJumpBtnTexture); - batch.setModelTransform(jumpTransform); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } + batch.setResourceTexture(0, _virtualPadJumpBtnTexture); + batch.setModelTransform(jumpTransform); + batch.draw(gpu::TRIANGLE_STRIP, 4); }); } #endif From 4713d8d44ca7deb534eea0c59fa6e15ab681946d Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Tue, 12 Jun 2018 16:06:17 -0700 Subject: [PATCH 59/62] fix reference to builds URL for sandbox check --- server-console/src/modules/hf-updater.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server-console/src/modules/hf-updater.js b/server-console/src/modules/hf-updater.js index d20da3c663..8362174c5d 100644 --- a/server-console/src/modules/hf-updater.js +++ b/server-console/src/modules/hf-updater.js @@ -58,7 +58,7 @@ util.inherits(UpdateChecker, events.EventEmitter); UpdateChecker.prototype = extend(UpdateChecker.prototype, { checkForUpdates: function() { log.debug("Checking for updates"); - request(BUILDS_URL, (error, response, body) => { + request(this.buildsURL, (error, response, body) => { if (error) { log.debug("Error", error); return; From 395767ed80ae15ce4bc27080b356d4e3da42f254 Mon Sep 17 00:00:00 2001 From: Gabriel Calero <gcalero1984@gmail.com> Date: Tue, 12 Jun 2018 20:11:22 -0300 Subject: [PATCH 60/62] Set android versionCode and versionName through gradle parameter RELEASE_NUMBER --- android/app/build.gradle | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 699008092c..f780abdea0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -4,12 +4,15 @@ android { compileSdkVersion 26 //buildToolsVersion '27.0.3' + def appVersionCode = Integer.valueOf(RELEASE_NUMBER ?: 1) + def appVersionName = RELEASE_NUMBER ?: "1.0" + defaultConfig { applicationId "io.highfidelity.hifiinterface" minSdkVersion 24 targetSdkVersion 26 - versionCode 1 - versionName "1.0" + versionCode appVersionCode + versionName appVersionName ndk { abiFilters 'arm64-v8a' } externalNativeBuild { cmake { From 016a6dcd84be77e284f34f3d8f5a4fb06c936097 Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Tue, 10 Apr 2018 15:42:42 -0700 Subject: [PATCH 61/62] use ref for HDR_FORMAT to avoid static order --- libraries/image/src/image/Image.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 696e311495..584b1f421d 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -37,7 +37,9 @@ bool DEV_DECIMATE_TEXTURES = false; std::atomic<size_t> DECIMATED_TEXTURE_COUNT{ 0 }; std::atomic<size_t> RECTIFIED_TEXTURE_COUNT{ 0 }; -static const auto HDR_FORMAT = gpu::Element::COLOR_R11G11B10; +// we use a ref here to work around static order initialization +// possibly causing the element not to be constructed yet +static const auto& HDR_FORMAT = gpu::Element::COLOR_R11G11B10; static std::atomic<bool> compressColorTextures { false }; static std::atomic<bool> compressNormalTextures { false }; From 569f7dc308957ce0f76dd1176e8f069fcec0b510 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Wed, 13 Jun 2018 08:33:06 -0700 Subject: [PATCH 62/62] Fix crash in image baking due to undefined mip format A recent change caused formatMip to no longer be specified. This causes an issue deeper in the code when generating mips, causing a Q_UNREACHABLE to be hit. --- libraries/image/src/image/Image.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 5ddcfa9fb4..dc45257d2b 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -835,6 +835,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma } else { formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGB; } + formatMip = formatGPU; } else { #ifdef USE_GLES // GLES does not support GL_BGRA