From c739db75621f9f28790ad7cbc3c5d3f743fd8b74 Mon Sep 17 00:00:00 2001 From: trent Date: Wed, 5 Apr 2017 17:39:52 -0400 Subject: [PATCH 01/28] Added quadratic ease-in-and-out smoothing to remote avatars position/orientation updates (through... one path, at least?). --- interface/src/avatar/Avatar.cpp | 57 ++++++++++++++++++++++++++++++--- interface/src/avatar/Avatar.h | 13 ++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ade98c63d8..c1ba0bca65 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -97,7 +97,15 @@ Avatar::Avatar(RigPointer rig) : _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), _initialized(false), - _voiceSphereID(GeometryCache::UNKNOWN_ID) + _voiceSphereID(GeometryCache::UNKNOWN_ID), + _smoothPositionTime(0.15f), + _smoothPositionTimer(std::numeric_limits::max()), + _smoothOrientationTime(0.15f), + _smoothOrientationTimer(std::numeric_limits::max()), + _smoothPositionInitial(), + _smoothPositionTarget(), + _smoothOrientationInitial(), + _smoothOrientationTarget() { // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); @@ -342,6 +350,25 @@ void Avatar::simulate(float deltaTime, bool inView) { _simulationInViewRate.increment(); } + if (!isMyAvatar()) { + if (_smoothPositionTimer < _smoothPositionTime) { + // Smooth the remote avatar movement. + _smoothPositionTimer += deltaTime; + if (_smoothPositionTimer < _smoothPositionTime) { + AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); + updateAttitude(); + } + } + + if (_smoothOrientationTimer < _smoothOrientationTime) { + // Smooth the remote avatar movement. + _smoothOrientationTimer += deltaTime; + if (_smoothOrientationTimer < _smoothOrientationTime) { + AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); + updateAttitude(); + } + } + } PerformanceTimer perfTimer("simulate"); { @@ -1343,13 +1370,33 @@ glm::quat Avatar::getUncachedRightPalmRotation() const { } void Avatar::setPosition(const glm::vec3& position) { - AvatarData::setPosition(position); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setPosition(position); + updateAttitude(); + + return; + } + + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothPositionInitial = getPosition(); + _smoothPositionTarget = position; + _smoothPositionTimer = 0.0f; } void Avatar::setOrientation(const glm::quat& orientation) { - AvatarData::setOrientation(orientation); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setOrientation(orientation); + updateAttitude(); + + return; + } + + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothOrientationInitial = getOrientation(); + _smoothOrientationTarget = orientation; + _smoothOrientationTimer = 0.0f; } void Avatar::updatePalms() { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ba7e1c617e..8d97553039 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -210,6 +210,10 @@ public: bool hasNewJointData() const { return _hasNewJointData; } + inline float easeInOutQuad(float t) { + return((t < 0.5) ? (2*t*t) : (t*(4 - 2*t) - 1)); + } + public slots: // FIXME - these should be migrated to use Pose data instead @@ -292,6 +296,15 @@ protected: RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; + // Smoothing data for blending from one position/orientation to another on remote agents. + float _smoothPositionTime; + float _smoothPositionTimer; + float _smoothOrientationTime; + float _smoothOrientationTimer; + glm::vec3 _smoothPositionInitial; + glm::vec3 _smoothPositionTarget; + glm::quat _smoothOrientationInitial; + glm::quat _smoothOrientationTarget; private: class AvatarEntityDataHash { From 43b3a6c6246a954b81302f6dd0b1d9c67aa253c8 Mon Sep 17 00:00:00 2001 From: trent Date: Wed, 5 Apr 2017 21:31:13 -0400 Subject: [PATCH 02/28] Addressing some style inconsitency issues, as well as making the position/orientation times constants. --- interface/src/avatar/Avatar.cpp | 92 ++++++++++++++++----------------- interface/src/avatar/Avatar.h | 3 ++ 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c1ba0bca65..08f5c856b8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -98,14 +98,14 @@ Avatar::Avatar(RigPointer rig) : _moving(false), _initialized(false), _voiceSphereID(GeometryCache::UNKNOWN_ID), - _smoothPositionTime(0.15f), - _smoothPositionTimer(std::numeric_limits::max()), - _smoothOrientationTime(0.15f), - _smoothOrientationTimer(std::numeric_limits::max()), - _smoothPositionInitial(), - _smoothPositionTarget(), - _smoothOrientationInitial(), - _smoothOrientationTarget() + _smoothPositionTime(SMOOTH_TIME_POSITION), + _smoothPositionTimer(std::numeric_limits::max()), + _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), + _smoothOrientationTimer(std::numeric_limits::max()), + _smoothPositionInitial(), + _smoothPositionTarget(), + _smoothOrientationInitial(), + _smoothOrientationTarget() { // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); @@ -350,25 +350,25 @@ void Avatar::simulate(float deltaTime, bool inView) { _simulationInViewRate.increment(); } - if (!isMyAvatar()) { - if (_smoothPositionTimer < _smoothPositionTime) { - // Smooth the remote avatar movement. - _smoothPositionTimer += deltaTime; - if (_smoothPositionTimer < _smoothPositionTime) { - AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); - updateAttitude(); - } - } + if (!isMyAvatar()) { + if (_smoothPositionTimer < _smoothPositionTime) { + // Smooth the remote avatar movement. + _smoothPositionTimer += deltaTime; + if (_smoothPositionTimer < _smoothPositionTime) { + AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); + updateAttitude(); + } + } - if (_smoothOrientationTimer < _smoothOrientationTime) { - // Smooth the remote avatar movement. - _smoothOrientationTimer += deltaTime; - if (_smoothOrientationTimer < _smoothOrientationTime) { - AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); - updateAttitude(); - } - } - } + if (_smoothOrientationTimer < _smoothOrientationTime) { + // Smooth the remote avatar movement. + _smoothOrientationTimer += deltaTime; + if (_smoothOrientationTimer < _smoothOrientationTime) { + AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); + updateAttitude(); + } + } + } PerformanceTimer perfTimer("simulate"); { @@ -1370,33 +1370,33 @@ glm::quat Avatar::getUncachedRightPalmRotation() const { } void Avatar::setPosition(const glm::vec3& position) { - if (isMyAvatar()) { - // This is the local avatar, no need to handle any position smoothing. - AvatarData::setPosition(position); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setPosition(position); + updateAttitude(); - return; - } + return; + } - // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. - _smoothPositionInitial = getPosition(); - _smoothPositionTarget = position; - _smoothPositionTimer = 0.0f; + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothPositionInitial = getPosition(); + _smoothPositionTarget = position; + _smoothPositionTimer = 0.0f; } void Avatar::setOrientation(const glm::quat& orientation) { - if (isMyAvatar()) { - // This is the local avatar, no need to handle any position smoothing. - AvatarData::setOrientation(orientation); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setOrientation(orientation); + updateAttitude(); - return; - } + return; + } - // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. - _smoothOrientationInitial = getOrientation(); - _smoothOrientationTarget = orientation; - _smoothOrientationTimer = 0.0f; + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothOrientationInitial = getOrientation(); + _smoothOrientationTarget = orientation; + _smoothOrientationTimer = 0.0f; } void Avatar::updatePalms() { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 8d97553039..e0bdeff411 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -228,6 +228,9 @@ public slots: protected: friend class AvatarManager; + const float SMOOTH_TIME_POSITION = 0.125f; + const float SMOOTH_TIME_ORIENTATION = 0.075f; + virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send. QString _empty{}; virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter! From 76d3e6d5983e4e8fc46428b47d3cd26459272b33 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 6 Apr 2017 13:21:59 -0400 Subject: [PATCH 03/28] Added an assert for out-of-bounds values in the smoothing function; also clamped the values that I was sending in on the avatar-side. --- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Avatar.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 08f5c856b8..a4ab999a9c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -355,7 +355,7 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothPositionTimer += deltaTime; if (_smoothPositionTimer < _smoothPositionTime) { - AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); + AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f)))); updateAttitude(); } } @@ -364,7 +364,7 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothOrientationTimer += deltaTime; if (_smoothOrientationTimer < _smoothOrientationTime) { - AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); + AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f)))); updateAttitude(); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index e0bdeff411..ed6bd96a75 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -211,7 +211,9 @@ public: bool hasNewJointData() const { return _hasNewJointData; } inline float easeInOutQuad(float t) { - return((t < 0.5) ? (2*t*t) : (t*(4 - 2*t) - 1)); + assert(!((t < 0.0f) || (t > 1.0f))); + + return((t < 0.5f) ? (2.0f*t*t) : (t*(4.0f - 2.0f*t) - 1.0f)); } public slots: From 21f810e040ac8d0eace476c2223493a7d7791d32 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 6 Apr 2017 14:50:16 -0400 Subject: [PATCH 04/28] Fixed formatting concerns as well as a benign order-of-constructor warning. --- interface/src/avatar/Avatar.cpp | 24 ++++++++++++++--------- interface/src/avatar/Avatar.h | 34 ++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a4ab999a9c..4b427e8221 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -97,15 +97,15 @@ Avatar::Avatar(RigPointer rig) : _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), _initialized(false), - _voiceSphereID(GeometryCache::UNKNOWN_ID), - _smoothPositionTime(SMOOTH_TIME_POSITION), + _smoothPositionTime(SMOOTH_TIME_POSITION), _smoothPositionTimer(std::numeric_limits::max()), - _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), + _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), _smoothOrientationTimer(std::numeric_limits::max()), _smoothPositionInitial(), _smoothPositionTarget(), _smoothOrientationInitial(), - _smoothOrientationTarget() + _smoothOrientationTarget(), + _voiceSphereID(GeometryCache::UNKNOWN_ID) { // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); @@ -355,7 +355,11 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothPositionTimer += deltaTime; if (_smoothPositionTimer < _smoothPositionTime) { - AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f)))); + AvatarData::setPosition( + lerp(_smoothPositionInitial, + _smoothPositionTarget, + easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f))) + ); updateAttitude(); } } @@ -364,8 +368,12 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothOrientationTimer += deltaTime; if (_smoothOrientationTimer < _smoothOrientationTime) { - AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f)))); - updateAttitude(); + AvatarData::setOrientation( + slerp(_smoothOrientationInitial, + _smoothOrientationTarget, + easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f))) + ); + updateAttitude(); } } } @@ -1374,7 +1382,6 @@ void Avatar::setPosition(const glm::vec3& position) { // This is the local avatar, no need to handle any position smoothing. AvatarData::setPosition(position); updateAttitude(); - return; } @@ -1389,7 +1396,6 @@ void Avatar::setOrientation(const glm::quat& orientation) { // This is the local avatar, no need to handle any position smoothing. AvatarData::setOrientation(orientation); updateAttitude(); - return; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ed6bd96a75..2091ab4208 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -210,11 +210,15 @@ public: bool hasNewJointData() const { return _hasNewJointData; } - inline float easeInOutQuad(float t) { - assert(!((t < 0.0f) || (t > 1.0f))); + inline float easeInOutQuad(float lerpValue) { + assert(!((lerpValue < 0.0f) || (lerpValue > 1.0f))); - return((t < 0.5f) ? (2.0f*t*t) : (t*(4.0f - 2.0f*t) - 1.0f)); - } + if (lerpValue < 0.5f) { + return (2.0f * lerpValue * lerpValue); + } + + return (lerpValue*(4.0f - 2.0f * lerpValue) - 1.0f); + } public slots: @@ -230,8 +234,8 @@ public slots: protected: friend class AvatarManager; - const float SMOOTH_TIME_POSITION = 0.125f; - const float SMOOTH_TIME_ORIENTATION = 0.075f; + const float SMOOTH_TIME_POSITION = 0.125f; + const float SMOOTH_TIME_ORIENTATION = 0.075f; virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send. QString _empty{}; @@ -301,15 +305,15 @@ protected: RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; - // Smoothing data for blending from one position/orientation to another on remote agents. - float _smoothPositionTime; - float _smoothPositionTimer; - float _smoothOrientationTime; - float _smoothOrientationTimer; - glm::vec3 _smoothPositionInitial; - glm::vec3 _smoothPositionTarget; - glm::quat _smoothOrientationInitial; - glm::quat _smoothOrientationTarget; + // Smoothing data for blending from one position/orientation to another on remote agents. + float _smoothPositionTime; + float _smoothPositionTimer; + float _smoothOrientationTime; + float _smoothOrientationTimer; + glm::vec3 _smoothPositionInitial; + glm::vec3 _smoothPositionTarget; + glm::quat _smoothOrientationInitial; + glm::quat _smoothOrientationTarget; private: class AvatarEntityDataHash { From 584905a618f0abaaab12b38072b0d2c586ceb27a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Apr 2017 15:41:35 -0700 Subject: [PATCH 05/28] fix warning --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4b427e8221..92b0d40f93 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -96,7 +96,6 @@ Avatar::Avatar(RigPointer rig) : _lastOrientation(), _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), - _initialized(false), _smoothPositionTime(SMOOTH_TIME_POSITION), _smoothPositionTimer(std::numeric_limits::max()), _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), @@ -105,6 +104,7 @@ Avatar::Avatar(RigPointer rig) : _smoothPositionTarget(), _smoothOrientationInitial(), _smoothOrientationTarget(), + _initialized(false), _voiceSphereID(GeometryCache::UNKNOWN_ID) { // we may have been created in the network thread, but we live in the main thread From 01ad010dc9fa597408ca1d4e7c70f1cc7cbfd68d Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Apr 2017 16:07:14 -0700 Subject: [PATCH 06/28] Cherry picking the fix for the new nv driver --- libraries/render-utils/src/LightAmbient.slh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 15e23015cb..a82dfd577e 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -82,13 +82,12 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie <@if supportScattering@> - float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; - float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; - ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); - - obscurance = min(obscurance, ambientOcclusion); - if (scattering * isScatteringEnabled() > 0.0) { + float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; + float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; + ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); + + obscurance = min(obscurance, ambientOcclusion); // Diffuse from ambient diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; From b2f463180df79b9a07a000983968e3f6199c19f7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 12 Apr 2017 03:44:24 +0200 Subject: [PATCH 07/28] fix teleport cool-in, added missing TARGETTING state and some ESLINT style fixes --- scripts/system/controllers/teleport.js | 63 ++++++++++++++------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 33c0b3116e..dcbcaeb621 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -29,13 +29,13 @@ var COLORS_TELEPORT_SEAT = { red: 255, green: 0, blue: 170 -} +}; var COLORS_TELEPORT_CAN_TELEPORT = { red: 97, green: 247, blue: 255 -} +}; var COLORS_TELEPORT_CANNOT_TELEPORT = { red: 0, @@ -52,7 +52,7 @@ var COLORS_TELEPORT_CANCEL = { var TELEPORT_CANCEL_RANGE = 1; var COOL_IN_DURATION = 500; -const handInfo = { +var handInfo = { right: { controllerInput: Controller.Standard.RightHand }, @@ -80,7 +80,7 @@ function Trigger(hand) { this.down = function() { var down = _this.buttonValue === 1 ? 1.0 : 0.0; - return down + return down; }; } @@ -90,8 +90,9 @@ var ignoredEntities = []; var TELEPORTER_STATES = { IDLE: 'idle', COOL_IN: 'cool_in', + TARGETTING: 'targetting', TARGETTING_INVALID: 'targetting_invalid', -} +}; var TARGET = { NONE: 'none', // Not currently targetting anything @@ -99,7 +100,7 @@ var TARGET = { INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.) SURFACE: 'surface', // The current target is a valid surface SEAT: 'seat', // The current target is a seat -} +}; function Teleporter() { var _this = this; @@ -114,8 +115,8 @@ function Teleporter() { this.updateConnected = null; this.activeHand = null; - this.telporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); - this.teleportMappingInternal = Controller.newMapping(this.telporterMappingInternalName); + this.teleporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); + this.teleportMappingInternal = Controller.newMapping(this.teleporterMappingInternalName); // Setup overlays this.cancelOverlay = Overlays.addOverlay("model", { @@ -135,11 +136,11 @@ function Teleporter() { }); this.enableMappings = function() { - Controller.enableMapping(this.telporterMappingInternalName); + Controller.enableMapping(this.teleporterMappingInternalName); }; this.disableMappings = function() { - Controller.disableMapping(teleporter.telporterMappingInternalName); + Controller.disableMapping(teleporter.teleporterMappingInternalName); }; this.cleanup = function() { @@ -179,7 +180,7 @@ function Teleporter() { if (_this.state === TELEPORTER_STATES.COOL_IN) { _this.state = TELEPORTER_STATES.TARGETTING; } - }, COOL_IN_DURATION) + }, COOL_IN_DURATION); this.activeHand = hand; this.enableMappings(); @@ -203,13 +204,13 @@ function Teleporter() { }; this.deleteOverlayBeams = function() { - for (key in this.overlayLines) { + for (var key in this.overlayLines) { if (this.overlayLines[key] !== null) { Overlays.deleteOverlay(this.overlayLines[key]); this.overlayLines[key] = null; } } - } + }; this.update = function() { if (_this.state === TELEPORTER_STATES.IDLE) { @@ -272,7 +273,8 @@ function Teleporter() { this.hideCancelOverlay(); this.hideSeatOverlay(); - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CAN_TELEPORT); + this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, + COLORS_TELEPORT_CAN_TELEPORT); this.updateDestinationOverlay(this.targetOverlay, intersection); } } else if (teleportLocationType === TARGET.SEAT) { @@ -284,13 +286,15 @@ function Teleporter() { } - if (((_this.activeHand == 'left' ? leftPad : rightPad).buttonValue === 0) && inTeleportMode === true) { + if (((_this.activeHand === 'left' ? leftPad : rightPad).buttonValue === 0) && inTeleportMode === true) { + // remember the state before we exit teleport mode and set it back to IDLE + var previousState = this.state; this.exitTeleportMode(); this.hideCancelOverlay(); this.hideTargetOverlay(); this.hideSeatOverlay(); - if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || this.state === TELEPORTER_STATES.COOL_IN) { + if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || previousState === TELEPORTER_STATES.COOL_IN) { // Do nothing } else if (teleportLocationType === TARGET.SEAT) { Entities.callEntityMethod(intersection.entityID, 'sit'); @@ -321,7 +325,7 @@ function Teleporter() { this.overlayLines[hand] = Overlays.addOverlay("line3d", lineProperties); } else { - var success = Overlays.editOverlay(this.overlayLines[hand], { + Overlays.editOverlay(this.overlayLines[hand], { start: closePoint, end: farPoint, color: color @@ -361,7 +365,7 @@ function Teleporter() { }; } -//related to repositioning the avatar after you teleport +// related to repositioning the avatar after you teleport function getAvatarFootOffset() { var data = getJointData(); var upperLeg, lowerLeg, foot, toe, toeTop; @@ -384,14 +388,14 @@ function getAvatarFootOffset() { var offset = upperLeg + lowerLeg + foot + toe + toeTop; offset = offset / 100; return offset; -}; +} function getJointData() { var allJointData = []; var jointNames = MyAvatar.jointNames; jointNames.forEach(function(joint, index) { var translation = MyAvatar.getJointTranslation(index); - var rotation = MyAvatar.getJointRotation(index) + var rotation = MyAvatar.getJointRotation(index); allJointData.push({ joint: joint, index: index, @@ -401,7 +405,7 @@ function getJointData() { }); return allJointData; -}; +} var leftPad = new ThumbPad('left'); var rightPad = new ThumbPad('right'); @@ -420,7 +424,7 @@ function isMoving() { } else { return false; } -}; +} function parseJSON(json) { try { @@ -433,7 +437,7 @@ function parseJSON(json) { // point that is being intersected with is looked at. If this normal is more // than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up), then // you can't teleport there. -const MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; +var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; function getTeleportTargetType(intersection) { if (!intersection.intersects) { return TARGET.NONE; @@ -465,7 +469,7 @@ function getTeleportTargetType(intersection) { } else { return TARGET.SURFACE; } -}; +} function registerMappings() { mappingName = 'Hifi-Teleporter-Dev-' + Math.random(); @@ -487,7 +491,7 @@ function registerMappings() { if (isMoving() === true) { return; } - teleporter.enterTeleportMode('left') + teleporter.enterTeleportMode('left'); return; }); teleportMapping.from(Controller.Standard.RightPrimaryThumb) @@ -502,10 +506,10 @@ function registerMappings() { return; } - teleporter.enterTeleportMode('right') + teleporter.enterTeleportMode('right'); return; }); -}; +} registerMappings(); @@ -521,7 +525,6 @@ Script.scriptEnding.connect(cleanup); var isDisabled = false; var handleTeleportMessages = function(channel, message, sender) { - var data; if (sender === MyAvatar.sessionUUID) { if (channel === 'Hifi-Teleport-Disabler') { if (message === 'both') { @@ -531,7 +534,7 @@ var handleTeleportMessages = function(channel, message, sender) { isDisabled = 'left'; } if (message === 'right') { - isDisabled = 'right' + isDisabled = 'right'; } if (message === 'none') { isDisabled = false; @@ -545,7 +548,7 @@ var handleTeleportMessages = function(channel, message, sender) { } } } -} +}; Messages.subscribe('Hifi-Teleport-Disabler'); Messages.subscribe('Hifi-Teleport-Ignore-Add'); From 2d1d207c9be1bb3f2f06e3581e21d754bf5ba0a0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 12 Apr 2017 10:54:28 -0700 Subject: [PATCH 08/28] lol --- interface/src/avatar/Head.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 4c6aa10d12..282acf6bf5 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -77,7 +77,7 @@ void Head::simulate(float deltaTime, bool isMine) { float audioLoudness = 0.0f; if (_owningAvatar) { - _owningAvatar->getAudioLoudness(); + audioLoudness = _owningAvatar->getAudioLoudness(); } // Update audio trailing average for rendering facial animations From 6cb88c31f35c9557c6ee7a7be3648f21bd31cdcd Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 11 Apr 2017 15:02:27 -0700 Subject: [PATCH 09/28] AvatarMixer sends min updates for out-of-view avatars --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 05de209e81..c4497a1066 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -325,7 +325,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { _stats.overBudgetAvatars++; detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::NoData; } else if (!isInView) { - detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::NoData; + detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::MinimumData; nodeData->incrementAvatarOutOfView(); } else { detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO From e751080f640ed06522283cc9fa7c5dee1edb18ca Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 11 Apr 2017 15:03:11 -0700 Subject: [PATCH 10/28] update model transform even when out of view --- interface/src/avatar/SkeletonModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index d7dd93cedf..0c11fa456d 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -240,8 +240,8 @@ void SkeletonModel::updateAttitude() { // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), // but just before head has been simulated. void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { + updateAttitude(); if (fullUpdate) { - updateAttitude(); setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients()); Model::simulate(deltaTime, fullUpdate); From d9dc8ebc41b9810a09555029348d2e407be0568c Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 13 Apr 2017 15:48:51 -0700 Subject: [PATCH 11/28] More improvements --- .../qml/hifi/tablet/TabletAddressDialog.qml | 162 ++++++------------ interface/src/Menu.cpp | 2 +- .../DialogsManagerScriptingInterface.cpp | 16 ++ .../DialogsManagerScriptingInterface.h | 3 + interface/src/ui/DialogsManager.cpp | 21 ++- interface/src/ui/DialogsManager.h | 1 + interface/src/ui/overlays/Web3DOverlay.cpp | 1 + 7 files changed, 95 insertions(+), 111 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 356ff92664..b84e1ae9d4 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -21,7 +21,7 @@ import "../../styles-uit" as HifiStyles import "../../controls-uit" as HifiControls StackView { - id: root + id: root; HifiConstants { id: hifi } HifiStyles.HifiConstants { id: hifiStyleConstants } initialItem: addressBarDialog @@ -34,24 +34,16 @@ StackView { property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/"; property var tablet: null; - property bool isDesktop: false; Component { id: tabletStoryCard; TabletStoryCard {} } Component.onCompleted: { - root.currentItem.focus = true; - root.currentItem.forceActiveFocus(); - addressLine.focus = true; - addressLine.forceActiveFocus(); fillDestinations(); updateLocationText(false); + fillDestinations(); + addressLine.focus = true; root.parentChanged.connect(center); center(); - isDesktop = (typeof desktop !== "undefined"); tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - - if (desktop) { - root.title = "GOTO"; - } } Component.onDestruction: { root.parentChanged.disconnect(center); @@ -78,8 +70,6 @@ StackView { toggleOrGo(true, targetString); clearAddressLineTimer.start(); } - - property bool isCursorVisible: false // Override default cursor visibility. AddressBarDialog { @@ -102,16 +92,11 @@ StackView { onMetaverseServerUrlChanged: updateLocationTextTimer.start(); Rectangle { id: navBar - width: 480 - height: 70 + width: parent.width + height: 50; color: hifiStyleConstants.colors.white - anchors { - top: parent.top - right: parent.right - rightMargin: 0 - left: parent.left - leftMargin: 0 - } + anchors.top: parent.top; + anchors.left: parent.left; ToolbarButton { id: homeButton @@ -149,85 +134,77 @@ StackView { Rectangle { id: addressBar - width: 480 + width: parent.width height: 70 color: hifiStyleConstants.colors.white anchors { - top: navBar.bottom - right: parent.right - rightMargin: 16 - left: parent.left - leftMargin: 16 + top: navBar.bottom; + left: parent.left; } - property int inputAreaHeight: 70 - property int inputAreaStep: (height - inputAreaHeight) / 2 - HifiStyles.RalewayLight { id: notice; - font.pixelSize: hifi.fonts.pixelSize * 0.50; + font.pixelSize: hifi.fonts.pixelSize * 0.7; anchors { - top: parent.top - topMargin: parent.inputAreaStep + 12 - left: addressLine.left - right: addressLine.right + top: parent.top; + left: addressLineContainer.left; + right: addressLineContainer.right; } } + HifiStyles.FiraSansRegular { id: location; + anchors { + left: addressLineContainer.left; + leftMargin: 8; + verticalCenter: addressLineContainer.verticalCenter; + } font.pixelSize: addressLine.font.pixelSize; color: "gray"; clip: true; - anchors.fill: addressLine; visible: addressLine.text.length === 0 } TextInput { id: addressLine - focus: true + width: addressLineContainer.width - addressLineContainer.anchors.leftMargin - addressLineContainer.anchors.rightMargin; anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - leftMargin: 16 - rightMargin: 16 - topMargin: parent.inputAreaStep + (2 * hifi.layout.spacing) - bottomMargin: parent.inputAreaStep + left: addressLineContainer.left; + leftMargin: 8; + verticalCenter: addressLineContainer.verticalCenter; } font.pixelSize: hifi.fonts.pixelSize * 0.75 - cursorVisible: false onTextChanged: { filterChoicesByText(); updateLocationText(text.length > 0); - if (!isCursorVisible && text.length > 0) { - isCursorVisible = true; - cursorVisible = true; - } } onAccepted: { addressBarDialog.keyboardEnabled = false; - } - onActiveFocusChanged: { - cursorVisible = isCursorVisible && focus; - } - MouseArea { - // If user clicks in address bar show cursor to indicate ability to enter address. - anchors.fill: parent - onClicked: { - isCursorVisible = true; - parent.cursorVisible = true; - parent.focus = true; - parent.forceActiveFocus(); - addressBarDialog.keyboardEnabled = HMD.active - tabletRoot.playButtonClickSound(); - } + toggleOrGo(); } } Rectangle { - anchors.fill: addressLine + id: addressLineContainer; + height: 40; + anchors { + top: notice.bottom; + topMargin: 2; + left: parent.left; + leftMargin: 16; + right: parent.right; + rightMargin: 16; + } color: hifiStyleConstants.colors.lightGray opacity: 0.1 + MouseArea { + anchors.fill: parent + onClicked: { + addressLine.focus = true; + addressBarDialog.keyboardEnabled = HMD.active; + tabletRoot.playButtonClickSound(); + } + } } } Rectangle { @@ -347,13 +324,12 @@ StackView { Timer { // Delay clearing address line so as to avoid flicker of "not connected" being displayed after entering an address. - id: clearAddressLineTimer - running: false - interval: 100 // ms - repeat: false + id: clearAddressLineTimer; + running: false; + interval: 100; // ms + repeat: false; onTriggered: { addressLine.text = ""; - isCursorVisible = false; } } @@ -545,46 +521,14 @@ StackView { } } - onVisibleChanged: { - updateLocationText(false); - if (visible) { - addressLine.forceActiveFocus(); - fillDestinations(); - } - } - function toggleOrGo(fromSuggestions, address) { if (address !== undefined && address !== "") { - addressBarDialog.loadAddress(address, fromSuggestions) - } - - if (addressLine.text !== "") { - addressBarDialog.loadAddress(addressLine.text, fromSuggestions) - } - - if (isDesktop) { - tablet.gotoHomeScreen(); - } else { - HMD.closeTablet(); - } - - tabletRoot.shown = false; - } - - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Escape: - case Qt.Key_Back: - tabletRoot.shown = false - clearAddressLineTimer.start(); - event.accepted = true - break - case Qt.Key_Enter: - case Qt.Key_Return: - toggleOrGo() - clearAddressLineTimer.start(); - event.accepted = true - break + addressBarDialog.loadAddress(address, fromSuggestions); + clearAddressLineTimer.start(); + } else if (addressLine.text !== "") { + addressBarDialog.loadAddress(addressLine.text, fromSuggestions); + clearAddressLineTimer.start(); } + DialogsManager.hideAddressBar(); } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 23d689e339..2451f42bca 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -254,7 +254,7 @@ Menu::Menu() { // Navigate > Show Address Bar addActionToQMenuAndActionHash(navigateMenu, MenuOption::AddressBar, Qt::CTRL | Qt::Key_L, - dialogsManager.data(), SLOT(toggleAddressBar())); + dialogsManager.data(), SLOT(showAddressBar())); // Navigate > Bookmark related menus -- Note: the Bookmark class adds its own submenus here. qApp->getBookmarks()->setupMenus(this, navigateMenu); diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.cpp b/interface/src/scripting/DialogsManagerScriptingInterface.cpp index 1604c45593..f1c96b4309 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.cpp +++ b/interface/src/scripting/DialogsManagerScriptingInterface.cpp @@ -22,11 +22,27 @@ DialogsManagerScriptingInterface::DialogsManagerScriptingInterface() { this, &DialogsManagerScriptingInterface::addressBarShown); } + +DialogsManagerScriptingInterface* DialogsManagerScriptingInterface::getInstance() { + static DialogsManagerScriptingInterface sharedInstance; + return &sharedInstance; +} + void DialogsManagerScriptingInterface::toggleAddressBar() { QMetaObject::invokeMethod(DependencyManager::get().data(), "toggleAddressBar", Qt::QueuedConnection); } +void DialogsManagerScriptingInterface::showAddressBar() { + QMetaObject::invokeMethod(DependencyManager::get().data(), + "showAddressBar", Qt::QueuedConnection); +} + +void DialogsManagerScriptingInterface::hideAddressBar() { + QMetaObject::invokeMethod(DependencyManager::get().data(), + "hideAddressBar", Qt::QueuedConnection); +} + void DialogsManagerScriptingInterface::showFeed() { QMetaObject::invokeMethod(DependencyManager::get().data(), "showFeed", Qt::QueuedConnection); diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.h b/interface/src/scripting/DialogsManagerScriptingInterface.h index 86cd22af1c..aa231afb4a 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.h +++ b/interface/src/scripting/DialogsManagerScriptingInterface.h @@ -18,10 +18,13 @@ class DialogsManagerScriptingInterface : public QObject { Q_OBJECT public: DialogsManagerScriptingInterface(); + static DialogsManagerScriptingInterface* getInstance(); Q_INVOKABLE void showFeed(); public slots: void toggleAddressBar(); + void showAddressBar(); + void hideAddressBar(); signals: void addressBarToggled(); diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index a95ac8d91f..c5932aae07 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -67,12 +67,14 @@ void DialogsManager::toggleAddressBar() { emit addressBarToggled(); } else { tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID()); _closeAddressBar = true; emit addressBarToggled(); } } else { tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); hmd->openTablet(); + qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID()); _closeAddressBar = true; emit addressBarToggled(); } @@ -84,11 +86,28 @@ void DialogsManager::showAddressBar() { auto hmd = DependencyManager::get(); auto tabletScriptingInterface = DependencyManager::get(); auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); - tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + if (!tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + } if (!hmd->getShouldShowTablet()) { hmd->openTablet(); } + qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID()); + emit addressBarShown(true); +} + +void DialogsManager::hideAddressBar() { + auto hmd = DependencyManager::get(); + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + + if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) { + tablet->gotoHomeScreen(); + hmd->closeTablet(); + } + qApp->setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + emit addressBarShown(false); } void DialogsManager::showFeed() { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 24b9078baf..76c4f083d2 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -43,6 +43,7 @@ public: public slots: void toggleAddressBar(); void showAddressBar(); + void hideAddressBar(); void showFeed(); void setDomainConnectionFailureVisibility(bool visible); void toggleLoginDialog(); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 502006c862..f80589e5a1 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -198,6 +198,7 @@ void Web3DOverlay::loadSourceURL() { _webSurface->getRootContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); _webSurface->getRootContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); _webSurface->getRootContext()->setContextProperty("AvatarList", DependencyManager::get().data()); + _webSurface->getRootContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance()); _webSurface->getRootContext()->setContextProperty("pathToFonts", "../../"); tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data()); From 520ceebf5b9622befe6739aa7379c1ddf7a61249 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 13 Apr 2017 15:52:59 -0700 Subject: [PATCH 12/28] Small HMD tweaks --- .../resources/qml/hifi/tablet/TabletAddressDialog.qml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index b84e1ae9d4..620b1ace1c 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -40,7 +40,7 @@ StackView { fillDestinations(); updateLocationText(false); fillDestinations(); - addressLine.focus = true; + addressLine.focus = !HMD.active; root.parentChanged.connect(center); center(); tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); @@ -200,8 +200,13 @@ StackView { MouseArea { anchors.fill: parent onClicked: { - addressLine.focus = true; - addressBarDialog.keyboardEnabled = HMD.active; + if (!addressLine.focus || !HMD.active) { + addressLine.focus = true; + addressBarDialog.keyboardEnabled = HMD.active; + } else { + addressLine.focus = false; + addressBarDialog.keyboardEnabled = false; + } tabletRoot.playButtonClickSound(); } } From 054370908130562edd617978fdf71a7338da0f3d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 13 Apr 2017 16:10:36 -0700 Subject: [PATCH 13/28] Focus fix --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 620b1ace1c..801b279591 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -198,10 +198,11 @@ StackView { color: hifiStyleConstants.colors.lightGray opacity: 0.1 MouseArea { - anchors.fill: parent + anchors.fill: parent; onClicked: { if (!addressLine.focus || !HMD.active) { addressLine.focus = true; + addressLine.forceActiveFocus(); addressBarDialog.keyboardEnabled = HMD.active; } else { addressLine.focus = false; @@ -516,7 +517,7 @@ StackView { function updateLocationText(enteringAddress) { if (enteringAddress) { - notice.text = "Go to a place, @user, path or network address"; + notice.text = "Go To a place, @user, path, or network address:"; notice.color = hifiStyleConstants.colors.baseGrayHighlight; } else { notice.text = AddressManager.isConnected ? "Your location:" : "Not Connected"; From 7189d4d7fafc77536661623c70ee657c1d1af7bd Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 14 Apr 2017 17:01:23 +0100 Subject: [PATCH 14/28] daving web work --- .../qml/controls/TabletWebButton.qml | 53 ++++ .../resources/qml/controls/TabletWebView.qml | 272 +++++++++++------- .../qml/hifi/tablet/TabletAddressDialog.qml | 10 +- .../HFTabletWebEngineRequestInterceptor.cpp | 12 +- 4 files changed, 236 insertions(+), 111 deletions(-) create mode 100644 interface/resources/qml/controls/TabletWebButton.qml diff --git a/interface/resources/qml/controls/TabletWebButton.qml b/interface/resources/qml/controls/TabletWebButton.qml new file mode 100644 index 0000000000..a5876d08dd --- /dev/null +++ b/interface/resources/qml/controls/TabletWebButton.qml @@ -0,0 +1,53 @@ +// +// TabletWebButton.qml +// +// Created by Dante Ruiz on 2017/4/13 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 +import "../styles-uit" + +Rectangle { + property alias text: label.text + property alias pixelSize: label.font.pixelSize; + property bool selected: false + property bool hovered: false + property bool enabled: false + property int spacing: 2 + property var action: function () {} + property string enabledColor: hifi.colors.blueHighlight + property string disabledColor: hifi.colors.blueHighlight + property string highlightColor: hifi.colors.blueHighlight; + width: label.width + 64 + height: 32 + color: hifi.colors.white + HifiConstants { id: hifi } + RalewaySemiBold { + id: label; + color: enabledColor + font.pixelSize: 15; + anchors { + horizontalCenter: parent.horizontalCenter; + verticalCenter: parent.verticalCenter; + } + } + + + Rectangle { + id: indicator + width: parent.width + height: selected ? 3 : 1 + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + color: hifi.colors.blueHighlight + visible: parent.selected || hovered + } +} diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 93e693ab2f..7e2e6d0a26 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -2,97 +2,81 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.2 import QtWebChannel 1.0 +import HFTabletWebEngineProfile 1.0 import "../controls-uit" as HiFiControls import "../styles" as HifiStyles import "../styles-uit" -import HFWebEngineProfile 1.0 -import HFTabletWebEngineProfile 1.0 import "../" +import "." Item { id: web + HifiConstants { id: hifi } width: parent.width height: parent.height property var parentStackItem: null - property int headerHeight: 38 + property int headerHeight: 70 property string url - property string address: url //for compatibility + property alias address: displayUrl.text //for compatibility property string scriptURL property alias eventBridge: eventBridgeWrapper.eventBridge property bool keyboardEnabled: HMD.active property bool keyboardRaised: false property bool punctuationMode: false property bool isDesktop: false - property WebEngineView view: loader.currentView property int currentPage: -1 // used as a model for repeater property alias pagesModel: pagesModel - Row { + Rectangle { id: buttons - HifiConstants { id: hifi } - HifiStyles.HifiConstants { id: hifistyles } - height: headerHeight - spacing: 4 - anchors.top: parent.top - anchors.topMargin: 8 - anchors.left: parent.left - anchors.leftMargin: 8 - HiFiGlyphs { - id: back; - enabled: currentPage >= 0 - text: hifi.glyphs.backward - color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: goBack() } - } - - HiFiGlyphs { - id: forward; - enabled: currentPage < pagesModel.count - 1 - text: hifi.glyphs.forward - color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: goForward() } - } - - HiFiGlyphs { - id: reload; - enabled: view != null; - text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload - color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: reloadPage(); } - } - - } + width: parent.width + height: parent.headerHeight + color: hifi.colors.white - TextField { - id: addressBar - height: 30 - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.left: buttons.right - anchors.leftMargin: 0 - anchors.verticalCenter: buttons.verticalCenter - focus: true - text: address - Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i") + Row { + id: nav + anchors { + top: parent.top + topMargin: 10 + horizontalCenter: parent.horizontalCenter + } + spacing: 120 + + TabletWebButton { + id: back + enabledColor: hifi.colors.baseGray + enabled: false + text: "BACK" - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Enter: - case Qt.Key_Return: - event.accepted = true; - if (text.indexOf("http") != 0) { - text = "http://" + text; - } - //root.hidePermissionsBar(); - web.keyboardRaised = false; - gotoPage(text); - break; + MouseArea { + anchors.fill: parent + onClicked: goBack() + hoverEnabled: true + + } + } - + TabletWebButton { + id: close + enabledColor: hifi.colors.darkGray + text: "CLOSE" + + MouseArea { + anchors.fill: parent + onClicked: closeWebEngine() + } + } + } + + + RalewaySemiBold { + id: displayUrl + color: hifi.colors.baseGray + font.pixelSize: 12 + anchors { + top: nav.bottom + horizontalCenter: parent.horizontalCenter; } } } @@ -100,15 +84,30 @@ Item { ListModel { id: pagesModel onCountChanged: { - currentPage = count - 1 + currentPage = count - 1; + if (currentPage > 0) { + back.enabledColor = hifi.colors.darkGray; + } else { + back.enabledColor = hifi.colors.baseGray; + } } } function goBack() { - if (currentPage > 0) { - currentPage--; - } else if (parentStackItem) { + if (webview.canGoBack) { + pagesModel.remove(currentPage); + webview.goBack(); + } else if (currentPage > 0) { + pagesModel.remove(currentPage); + } + } + + + function closeWebEngine() { + if (parentStackItem) { parentStackItem.pop(); + } else { + web.visible = false; } } @@ -130,18 +129,22 @@ Item { function urlAppend(url) { var lurl = decodeURIComponent(url) - if (lurl[lurl.length - 1] !== "/") + if (lurl[lurl.length - 1] !== "/") { lurl = lurl + "/" - if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== lurl) { - pagesModel.append({webUrl: lurl}) + } + console.log("-------------> is time running " + timer.running + " <--------------"); + if (currentPage === -1 || (pagesModel.get(currentPage).webUrl !== lurl && !timer.running)) { + console.log("---------> appending the url ----------> " + lurl); + timer.start(); + pagesModel.append({webUrl: lurl}); } } onCurrentPageChanged: { - if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) { - loader.item.url = pagesModel.get(currentPage).webUrl - web.url = loader.item.url - web.address = loader.item.url + if (currentPage >= 0 && currentPage < pagesModel.count) { + webview.url = pagesModel.get(currentPage).webUrl; + web.url = webview.url; + web.address = webview.url; } } @@ -155,45 +158,110 @@ Item { property var eventBridge; } - Loader { - id: loader + Timer { + id: timer + interval: 100 + running: false + repeat: false + onTriggered: timer.stop(); + } - property WebEngineView currentView: null + + + WebEngineView { + id: webview + objectName: "webEngineView" + x: 0 + y: 0 width: parent.width - height: parent.height - web.headerHeight - asynchronous: true + height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight anchors.top: buttons.bottom - active: false - source: "../TabletBrowser.qml" - onStatusChanged: { - if (loader.status === Loader.Ready) { - currentView = item.webView - item.webView.userScriptUrl = web.scriptURL - if (currentPage >= 0) { - //we got something to load already - item.url = pagesModel.get(currentPage).webUrl - web.address = loader.item.url + profile: HFTabletWebEngineProfile { + id: webviewTabletProfile + storageName: "qmlTabletWebEngine" + } + + property string userScriptUrl: "" + + // creates a global EventBridge object. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } + + // detects when to raise and lower virtual keyboard + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + // User script. + WebEngineScript { + id: userScript + sourceUrl: webview.userScriptUrl + injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] + + property string newUrl: "" + + webChannel.registeredObjects: [eventBridgeWrapper] + + Component.onCompleted: { + // Ensure the JS from the web-engine makes it to our logging + webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { + console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); + }); + + webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + web.address = url; + } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } + + onLoadingChanged: { + keyboardRaised = false; + punctuationMode = false; + keyboard.resetShiftMode(false); + + // Required to support clicking on "hifi://" links + if (WebEngineView.LoadStartedStatus == loadRequest.status) { + urlAppend(loadRequest.url.toString()) + var url = loadRequest.url.toString(); + if (urlHandler.canHandleUrl(url)) { + if (urlHandler.handleUrl(url)) { + root.stop(); + } } } } - } + onNewViewRequested: { + request.openIn(webview); + } + } + Component.onCompleted: { web.isDesktop = (typeof desktop !== "undefined"); address = url; - loader.active = true } - Keys.onPressed: { + Keys.onPressed: { switch(event.key) { - case Qt.Key_L: - if (event.modifiers == Qt.ControlModifier) { - event.accepted = true - addressBar.selectAll() - addressBar.forceActiveFocus() - } - break; + case Qt.Key_L: + if (event.modifiers == Qt.ControlModifier) { + event.accepted = true + } + break; } } } diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 356ff92664..ab28b84a3d 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -35,8 +35,8 @@ StackView { property var tablet: null; property bool isDesktop: false; - - Component { id: tabletStoryCard; TabletStoryCard {} } + + Component { id: tabletWebView; TabletWebView {} } Component.onCompleted: { root.currentItem.focus = true; root.currentItem.forceActiveFocus(); @@ -68,9 +68,9 @@ StackView { } function goCard(targetString) { if (0 !== targetString.indexOf('hifi://')) { - var card = tabletStoryCard.createObject(); - card.setUrl(addressBarDialog.metaverseServerUrl + targetString); - card.eventBridge = root.eventBridge; + var card = tabletWebView.createObject(); + card.url = addressBarDialog.metaverseServerUrl + targetString; + card.parentStackItem = root; root.push(card); return; } diff --git a/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp b/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp index 7282fb5e3d..fd79fc1cb6 100644 --- a/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp @@ -34,9 +34,13 @@ void HFTabletWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestI QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token; info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); } - } - static const QString USER_AGENT = "User-Agent"; - QString tokenString = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; - info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); + static const QString USER_AGENT = "User-Agent"; + QString tokenString = "Chrome/48.0 (HighFidelityInterface)"; + info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); + } else { + static const QString USER_AGENT = "User-Agent"; + QString tokenString = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); + } } From 863d64b2fd915d2a9ff51ca99bd7020ebb8714e2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 14 Apr 2017 18:06:44 +0100 Subject: [PATCH 15/28] removed comments and non-needed files --- .../resources/qml/controls/TabletWebView.qml | 2 - .../qml/hifi/tablet/TabletStoryCard.qml | 46 ------------------- 2 files changed, 48 deletions(-) delete mode 100644 interface/resources/qml/hifi/tablet/TabletStoryCard.qml diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 7e2e6d0a26..9a08e8b866 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -132,9 +132,7 @@ Item { if (lurl[lurl.length - 1] !== "/") { lurl = lurl + "/" } - console.log("-------------> is time running " + timer.running + " <--------------"); if (currentPage === -1 || (pagesModel.get(currentPage).webUrl !== lurl && !timer.running)) { - console.log("---------> appending the url ----------> " + lurl); timer.start(); pagesModel.append({webUrl: lurl}); } diff --git a/interface/resources/qml/hifi/tablet/TabletStoryCard.qml b/interface/resources/qml/hifi/tablet/TabletStoryCard.qml deleted file mode 100644 index 1d57c8a083..0000000000 --- a/interface/resources/qml/hifi/tablet/TabletStoryCard.qml +++ /dev/null @@ -1,46 +0,0 @@ -// -// TabletAddressDialog.qml -// -// Created by Dante Ruiz on 2017/04/24 -// Copyright 2015 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 -// - -import Hifi 1.0 -import QtQuick 2.4 -import QtGraphicalEffects 1.0 -import "../../controls" -import "../../styles" -import "../../windows" -import "../" -import "../toolbars" -import "../../styles-uit" as HifiStyles -import "../../controls-uit" as HifiControlsUit -import "../../controls" as HifiControls - - -Rectangle { - id: cardRoot - HifiStyles.HifiConstants { id: hifi } - width: parent.width - height: parent.height - property string address: "" - property alias eventBridge: webview.eventBridge - function setUrl(url) { - cardRoot.address = url; - webview.url = url; - } - - HifiControls.TabletWebView { - id: webview - parentStackItem: root - anchors { - top: parent.top - right: parent.right - left: parent.left - bottom: parent.bottom - } - } -} From a623ced64ea8f76dbde1465bdd2e2f8bdbbec271 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 14 Apr 2017 12:43:07 -0700 Subject: [PATCH 16/28] Fix hover states on back/forward buttons --- .../qml/hifi/tablet/TabletAddressDialog.qml | 18 +++++++++++-- .../qml/hifi/toolbars/ToolbarButton.qml | 27 ++++++++++++------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 801b279591..fec55d0594 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -20,6 +20,8 @@ import "../toolbars" import "../../styles-uit" as HifiStyles import "../../controls-uit" as HifiControls +// references HMD, AddressManager, AddressBarDialog from root context + StackView { id: root; HifiConstants { id: hifi } @@ -114,8 +116,14 @@ StackView { } ToolbarButton { id: backArrow; + buttonState: addressBarDialog.backEnabled; imageURL: "../../../images/backward.svg"; - onClicked: addressBarDialog.loadBack(); + buttonEnabled: addressBarDialog.backEnabled; + onClicked: { + if (buttonEnabled) { + addressBarDialog.loadBack(); + } + } anchors { left: homeButton.right verticalCenter: parent.verticalCenter @@ -123,8 +131,14 @@ StackView { } ToolbarButton { id: forwardArrow; + buttonState: addressBarDialog.forwardEnabled; imageURL: "../../../images/forward.svg"; - onClicked: addressBarDialog.loadForward(); + buttonEnabled: addressBarDialog.forwardEnabled; + onClicked: { + if (buttonEnabled) { + addressBarDialog.loadForward(); + } + } anchors { left: backArrow.right verticalCenter: parent.verticalCenter diff --git a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml index cab5b14d5c..3d4231ced7 100644 --- a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml +++ b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml @@ -3,6 +3,8 @@ import QtQuick.Controls 1.4 StateImage { id: button + + property bool buttonEnabled: true property bool isActive: false property bool isEntered: false @@ -39,30 +41,37 @@ StateImage { } function updateState() { - if (!button.isEntered && !button.isActive) { - buttonState = imageOffOut; - } else if (!button.isEntered && button.isActive) { - buttonState = imageOnOut; - } else if (button.isEntered && !button.isActive) { - buttonState = imageOffIn; + if (buttonEnabled) { + if (!button.isEntered && !button.isActive) { + buttonState = imageOffOut; + } else if (!button.isEntered && button.isActive) { + buttonState = imageOnOut; + } else if (button.isEntered && !button.isActive) { + buttonState = imageOffIn; + } else { + buttonState = imageOnIn; + } } else { - buttonState = imageOnIn; + buttonState = 0; } } onIsActiveChanged: updateState(); + onButtonEnabledChanged: updateState(); Timer { id: asyncClickSender interval: 10 repeat: false running: false - onTriggered: button.clicked(); + onTriggered: { + button.clicked(); + } } MouseArea { id: mouseArea - hoverEnabled: true + hoverEnabled: buttonEnabled anchors.fill: parent onClicked: asyncClickSender.start(); onEntered: { From a4587e33f331d9fa2112acba0b860efae85f8a83 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 14 Apr 2017 13:19:33 -0700 Subject: [PATCH 17/28] Tiny forward/backward icon updates --- interface/resources/images/backward.svg | 27 ++++++++++--------------- interface/resources/images/forward.svg | 27 ++++++++++--------------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/interface/resources/images/backward.svg b/interface/resources/images/backward.svg index e4502fa80e..a913ad9cd0 100644 --- a/interface/resources/images/backward.svg +++ b/interface/resources/images/backward.svg @@ -1,6 +1,6 @@ - - - - - - - + + + + diff --git a/interface/resources/images/forward.svg b/interface/resources/images/forward.svg index 0c5cbe3d0c..dde9322b9e 100644 --- a/interface/resources/images/forward.svg +++ b/interface/resources/images/forward.svg @@ -1,6 +1,6 @@ - - - - - - - + + + + From eaefa3d3f28ef260b7fe89ffd212cf1dee956d91 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 13:35:59 -0700 Subject: [PATCH 18/28] avatar-mixer resends to avoid stale avatar --- .../src/avatars/AvatarMixerSlave.cpp | 21 ++++++++++++++----- libraries/avatars/src/AvatarData.h | 7 +++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index c4497a1066..a4e9b608de 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -175,6 +175,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { } }); + const uint64_t MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR = (AVATAR_UPDATE_TIMEOUT - 1) * USECS_PER_SECOND; AvatarSharedPointer thisAvatar = nodeData->getAvatarSharedPointer(); ViewFrustum cameraView = nodeData->getViewFrustom(); std::priority_queue sortedAvatars; @@ -262,11 +263,17 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // have 15 (45hz-30hz) duplicate frames. In this case, the stat // avg_other_av_skips_per_second does report 15. // - // make sure we haven't already sent this data from this sender to this receiver + // make sure we haven't already sent this data from this sender to that receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - ++numAvatarsHeldBack; - shouldIgnore = true; + // don't ignore this avatar if we haven't sent any update for a long while + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); + const AvatarMixerClientData* otherNodeData = reinterpret_cast(avatarNode->getLinkedData()); + if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && + lastBroadcastTime > startIgnoreCalculation - MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { + ++numAvatarsHeldBack; + shouldIgnore = true; + } } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; @@ -302,8 +309,12 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO - // the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A. - if (nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) { + // the time that Avatar B flagged an IDENTITY DATA change + // or if no packet of any type has been sent for some time + // send IDENTITY DATA about Avatar B to Avatar A + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(otherNode->getUUID()); + if (lastBroadcastTime <= otherNodeData->getIdentityChangeTimestamp() || + startAvatarDataPacking > lastBroadcastTime + MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5ade0c448e..8319eb5249 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -110,6 +110,8 @@ const char LEFT_HAND_POINTING_FLAG = 1; const char RIGHT_HAND_POINTING_FLAG = 2; const char IS_FINGER_POINTING_FLAG = 4; +const qint64 AVATAR_UPDATE_TIMEOUT = 5 * USECS_PER_SECOND; + // AvatarData state flags - we store the details about the packet encoding in the first byte, // before the "header" structure const char AVATARDATA_FLAGS_MINIMUM = 0; @@ -599,10 +601,7 @@ public: } - bool shouldDie() const { - const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND; - return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; - } + bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_UPDATE_TIMEOUT; } static const float OUT_OF_VIEW_PENALTY; From d72f6cf45e9f8f2c8a0d11190453b7901e434763 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 13:37:18 -0700 Subject: [PATCH 19/28] avatar-mixer to send identity packets as 'reliable' --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index a4e9b608de..56c15f7793 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -69,7 +69,7 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) { int bytesSent = 0; QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); - auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size()); + auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size(), true, true); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious bytesSent += individualData.size(); identityPacket->write(individualData); From 06b9fd6a7e14ca3dd4d87ca2bedc2fbc9fb10321 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 14:55:08 -0700 Subject: [PATCH 20/28] don't keep stale avatars alive --- .../src/avatars/AvatarMixerSlave.cpp | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 56c15f7793..ee3282f82b 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -67,15 +67,13 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) { - int bytesSent = 0; QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); - auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size(), true, true); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious - bytesSent += individualData.size(); - identityPacket->write(individualData); - DependencyManager::get()->sendPacket(std::move(identityPacket), *destinationNode); + auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true); + identityPackets->write(individualData); + DependencyManager::get()->sendPacketList(std::move(identityPackets), *destinationNode); _stats.numIdentityPackets++; - return bytesSent; + return individualData.size(); } static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45; @@ -175,7 +173,6 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { } }); - const uint64_t MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR = (AVATAR_UPDATE_TIMEOUT - 1) * USECS_PER_SECOND; AvatarSharedPointer thisAvatar = nodeData->getAvatarSharedPointer(); ViewFrustum cameraView = nodeData->getViewFrustom(); std::priority_queue sortedAvatars; @@ -263,17 +260,11 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // have 15 (45hz-30hz) duplicate frames. In this case, the stat // avg_other_av_skips_per_second does report 15. // - // make sure we haven't already sent this data from this sender to that receiver + // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - // don't ignore this avatar if we haven't sent any update for a long while - uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); - const AvatarMixerClientData* otherNodeData = reinterpret_cast(avatarNode->getLinkedData()); - if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && - lastBroadcastTime > startIgnoreCalculation - MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { - ++numAvatarsHeldBack; - shouldIgnore = true; - } + ++numAvatarsHeldBack; + shouldIgnore = true; } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; @@ -312,9 +303,10 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // the time that Avatar B flagged an IDENTITY DATA change // or if no packet of any type has been sent for some time // send IDENTITY DATA about Avatar B to Avatar A + const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(otherNode->getUUID()); if (lastBroadcastTime <= otherNodeData->getIdentityChangeTimestamp() || - startAvatarDataPacking > lastBroadcastTime + MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { + startAvatarDataPacking > lastBroadcastTime + AVATAR_UPDATE_STALE) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } From 6a8ddee8784a7b84280d41baaa33b464542cf76a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 16:00:11 -0700 Subject: [PATCH 21/28] send keep-alive packets but don't resend identity --- .../src/avatars/AvatarMixerSlave.cpp | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index ee3282f82b..6e3dd150a4 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -263,8 +263,16 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - ++numAvatarsHeldBack; - shouldIgnore = true; + // don't ignore this avatar if we haven't sent any update for a long while + // in an effort to prevent other interfaces from deleting a stale avatar instance + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); + const AvatarMixerClientData* otherNodeData = reinterpret_cast(avatarNode->getLinkedData()); + const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; + if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && + lastBroadcastTime + AVATAR_UPDATE_STALE > startIgnoreCalculation) { + ++numAvatarsHeldBack; + shouldIgnore = true; + } } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; @@ -300,13 +308,8 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO - // the time that Avatar B flagged an IDENTITY DATA change - // or if no packet of any type has been sent for some time - // send IDENTITY DATA about Avatar B to Avatar A - const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; - uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(otherNode->getUUID()); - if (lastBroadcastTime <= otherNodeData->getIdentityChangeTimestamp() || - startAvatarDataPacking > lastBroadcastTime + AVATAR_UPDATE_STALE) { + // the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A. + if (nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } From 66137e78a2d4de4094e5001e734fe6cd366aa4d2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 14:20:04 -0700 Subject: [PATCH 22/28] grab script checks for touch devices continually, rather than just when the script starts --- scripts/system/controllers/handControllerGrab.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d1c00a9d81..e5271b0e62 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1051,8 +1051,6 @@ function MyController(hand) { this.homeButtonTouched = false; this.editTriggered = false; - this.controllerJointIndex = getControllerJointIndex(this.hand); - // Until there is some reliable way to keep track of a "stack" of parentIDs, we'll have problems // when more than one avatar does parenting grabs on things. This script tries to work // around this with two associative arrays: previousParentID and previousParentJointIndex. If @@ -1736,6 +1734,7 @@ function MyController(hand) { this.off = function(deltaTime, timestamp) { + this.controllerJointIndex = getControllerJointIndex(this.hand); this.checkForUnexpectedChildren(); if (this.editTriggered) { From 3e268fbf68f1e0a5d3eb9ebadd7ba9faa01d8113 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 17 Apr 2017 07:38:24 -0700 Subject: [PATCH 23/28] put shareable_url in UserStory details when creating --- interface/src/ui/SnapshotUploader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/ui/SnapshotUploader.cpp b/interface/src/ui/SnapshotUploader.cpp index 5826c8bd38..411e892de5 100644 --- a/interface/src/ui/SnapshotUploader.cpp +++ b/interface/src/ui/SnapshotUploader.cpp @@ -40,6 +40,9 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QJsonObject userStoryObject; QJsonObject detailsObject; detailsObject.insert("image_url", imageUrl); + if (dataObject.contains("shareable_url")) { + detailsObject.insert("shareable_url", dataObject.value("shareable_url").toString()); + } QString pickledDetails = QJsonDocument(detailsObject).toJson(); userStoryObject.insert("details", pickledDetails); userStoryObject.insert("thumbnail_url", thumbnailUrl); From 7a7cfb84e57e6d364a38f3502b879592d84e2ab0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 17 Apr 2017 10:08:40 -0700 Subject: [PATCH 24/28] Remove HMD keyboard focus toggle on AddressBar input --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index fec55d0594..d164100654 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -218,9 +218,6 @@ StackView { addressLine.focus = true; addressLine.forceActiveFocus(); addressBarDialog.keyboardEnabled = HMD.active; - } else { - addressLine.focus = false; - addressBarDialog.keyboardEnabled = false; } tabletRoot.playButtonClickSound(); } From e13000410e064494589210499abfc4d301302be4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 17 Apr 2017 11:02:27 -0700 Subject: [PATCH 25/28] Whoops --- libraries/avatars/src/AvatarHashMap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 87bedf8d51..e944c7c887 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -41,7 +41,7 @@ public: Q_INVOKABLE QVector getAvatarIdentifiers(); // Null/Default-constructed QUuids will return MyAvatar - virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } + Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const { return findAvatar(sessionID); } int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); From e6edce53524577b9e89cf972684eabcef7b3d8ac Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 17 Apr 2017 12:13:01 -0700 Subject: [PATCH 26/28] Entirely remove addressBarToggle() --- interface/src/Application.cpp | 4 +-- .../DialogsManagerScriptingInterface.cpp | 7 ---- .../DialogsManagerScriptingInterface.h | 2 -- interface/src/ui/DialogsManager.cpp | 36 ------------------- interface/src/ui/DialogsManager.h | 2 -- 5 files changed, 2 insertions(+), 49 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9c523f53e8..441db9b7b3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1418,11 +1418,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(DependencyManager::get().data(), &AudioClient::mutedByMixer, this, onMutedByMixer); // Track when the address bar is opened - auto onAddressBarToggled = [this]() { + auto onAddressBarShown = [this]() { // Record time UserActivityLogger::getInstance().logAction("opened_address_bar", { { "uptime_ms", _sessionRunTimer.elapsed() } }); }; - connect(DependencyManager::get().data(), &DialogsManager::addressBarToggled, this, onAddressBarToggled); + connect(DependencyManager::get().data(), &DialogsManager::addressBarShown, this, onAddressBarShown); // Make sure we don't time out during slow operations at startup updateHeartbeat(); diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.cpp b/interface/src/scripting/DialogsManagerScriptingInterface.cpp index f1c96b4309..0fb6078290 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.cpp +++ b/interface/src/scripting/DialogsManagerScriptingInterface.cpp @@ -16,8 +16,6 @@ #include "ui/DialogsManager.h" DialogsManagerScriptingInterface::DialogsManagerScriptingInterface() { - connect(DependencyManager::get().data(), &DialogsManager::addressBarToggled, - this, &DialogsManagerScriptingInterface::addressBarToggled); connect(DependencyManager::get().data(), &DialogsManager::addressBarShown, this, &DialogsManagerScriptingInterface::addressBarShown); } @@ -28,11 +26,6 @@ DialogsManagerScriptingInterface* DialogsManagerScriptingInterface::getInstance( return &sharedInstance; } -void DialogsManagerScriptingInterface::toggleAddressBar() { - QMetaObject::invokeMethod(DependencyManager::get().data(), - "toggleAddressBar", Qt::QueuedConnection); -} - void DialogsManagerScriptingInterface::showAddressBar() { QMetaObject::invokeMethod(DependencyManager::get().data(), "showAddressBar", Qt::QueuedConnection); diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.h b/interface/src/scripting/DialogsManagerScriptingInterface.h index aa231afb4a..e4dd18aedf 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.h +++ b/interface/src/scripting/DialogsManagerScriptingInterface.h @@ -22,12 +22,10 @@ public: Q_INVOKABLE void showFeed(); public slots: - void toggleAddressBar(); void showAddressBar(); void hideAddressBar(); signals: - void addressBarToggled(); void addressBarShown(bool visible); }; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index c5932aae07..96b5da3a55 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -46,42 +46,6 @@ void DialogsManager::maybeCreateDialog(QPointer& member) { } } -void DialogsManager::toggleAddressBar() { - auto hmd = DependencyManager::get(); - auto tabletScriptingInterface = DependencyManager::get(); - auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); - if (tablet->getToolbarMode()) { - if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) { - tablet->gotoHomeScreen(); - emit addressBarToggled(); - } else { - tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); - emit addressBarToggled(); - } - } else { - if (hmd->getShouldShowTablet()) { - if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG) && _closeAddressBar) { - tablet->gotoHomeScreen(); - hmd->closeTablet(); - _closeAddressBar = false; - emit addressBarToggled(); - } else { - tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); - qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID()); - _closeAddressBar = true; - emit addressBarToggled(); - } - } else { - tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); - hmd->openTablet(); - qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID()); - _closeAddressBar = true; - emit addressBarToggled(); - } - - } -} - void DialogsManager::showAddressBar() { auto hmd = DependencyManager::get(); auto tabletScriptingInterface = DependencyManager::get(); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 76c4f083d2..3a40b15a3b 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -41,7 +41,6 @@ public: void emitAddressBarShown(bool visible) { emit addressBarShown(visible); } public slots: - void toggleAddressBar(); void showAddressBar(); void hideAddressBar(); void showFeed(); @@ -58,7 +57,6 @@ public slots: void showUpdateDialog(); signals: - void addressBarToggled(); void addressBarShown(bool visible); void setUseFeed(bool useFeed); From d1a11740f07f23ec4b8243ab49b4c543268c949d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 17 Apr 2017 11:02:27 -0700 Subject: [PATCH 27/28] Whoops --- libraries/avatars/src/AvatarHashMap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 87bedf8d51..e944c7c887 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -41,7 +41,7 @@ public: Q_INVOKABLE QVector getAvatarIdentifiers(); // Null/Default-constructed QUuids will return MyAvatar - virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } + Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const { return findAvatar(sessionID); } int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); From 31b61c3225ed4609fc4abfdc385b68df046ce902 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 18 Apr 2017 00:24:34 +0100 Subject: [PATCH 28/28] removed white space --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index ece00bd0dd..bed1f82ac2 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -36,7 +36,7 @@ StackView { property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/"; property var tablet: null; - + Component { id: tabletWebView; TabletWebView {} } Component.onCompleted: { fillDestinations();