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