From b1690b31899b70401d8a64c3fa54c64363d3f898 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 16 Mar 2018 00:27:36 +0300 Subject: [PATCH 01/56] fix malformed urls on windows (like file:///Users/ai/AppData....) note: the issue happened because drive letter on Windows is treated by QUrl as 'scheme', so replacing it with 'file' results in broken url. --- tools/oven/src/BakerCLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/oven/src/BakerCLI.cpp b/tools/oven/src/BakerCLI.cpp index f5af5455fb..aac028e8cf 100644 --- a/tools/oven/src/BakerCLI.cpp +++ b/tools/oven/src/BakerCLI.cpp @@ -28,7 +28,7 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString& // if the URL doesn't have a scheme, assume it is a local file if (inputUrl.scheme() != "http" && inputUrl.scheme() != "https" && inputUrl.scheme() != "ftp") { - inputUrl.setScheme("file"); + inputUrl = QUrl::fromLocalFile(inputUrl.toString()); } qDebug() << "Baking file type: " << type; From 2439c045281b9c9d47c3b002dba8d0d9821d4d8b Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Wed, 25 Apr 2018 11:04:31 +0300 Subject: [PATCH 02/56] skip url conversion to 'file:///' for the urls which schema is already 'file' --- tools/oven/src/BakerCLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/oven/src/BakerCLI.cpp b/tools/oven/src/BakerCLI.cpp index aac028e8cf..a908b69f77 100644 --- a/tools/oven/src/BakerCLI.cpp +++ b/tools/oven/src/BakerCLI.cpp @@ -27,7 +27,7 @@ BakerCLI::BakerCLI(OvenCLIApplication* parent) : QObject(parent) { void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type) { // if the URL doesn't have a scheme, assume it is a local file - if (inputUrl.scheme() != "http" && inputUrl.scheme() != "https" && inputUrl.scheme() != "ftp") { + if (inputUrl.scheme() != "http" && inputUrl.scheme() != "https" && inputUrl.scheme() != "ftp" && inputUrl.scheme() != "file") { inputUrl = QUrl::fromLocalFile(inputUrl.toString()); } From 23a279434ca0b15883aab2dd6086974559614679 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 3 Jul 2018 10:33:25 -0700 Subject: [PATCH 03/56] Fix potential map.json corruption in Asset Server --- assignment-client/src/assets/AssetServer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index e0c35b7148..e79473783a 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1042,7 +1043,7 @@ bool AssetServer::loadMappingsFromFile() { bool AssetServer::writeMappingsToFile() { auto mapFilePath = _resourcesDirectory.absoluteFilePath(MAP_FILE_NAME); - QFile mapFile { mapFilePath }; + QSaveFile mapFile { mapFilePath }; if (mapFile.open(QIODevice::WriteOnly)) { QJsonObject root; @@ -1053,8 +1054,12 @@ bool AssetServer::writeMappingsToFile() { QJsonDocument jsonDocument { root }; if (mapFile.write(jsonDocument.toJson()) != -1) { - qCDebug(asset_server) << "Wrote JSON mappings to file at" << mapFilePath; - return true; + if (mapFile.commit()) { + qCDebug(asset_server) << "Wrote JSON mappings to file at" << mapFilePath; + return true; + } else { + qCWarning(asset_server) << "Failed to commit JSON mappings to file at" << mapFilePath; + } } else { qCWarning(asset_server) << "Failed to write JSON mappings to file at" << mapFilePath; } From ae03dcb57a41684b14417f7373d3b9a4f5a835a9 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 6 Jul 2018 15:42:21 -0700 Subject: [PATCH 04/56] fix parent grab dropping and cullig flickering --- .../src/RenderableEntityItem.cpp | 18 ++++++++---------- .../src/RenderableEntityItem.h | 2 +- .../src/RenderableParticleEffectEntityItem.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 6 ++---- .../src/RenderableTextEntityItem.cpp | 2 +- .../src/RenderableWebEntityItem.cpp | 2 +- .../controllerModules/nearParentGrabEntity.js | 6 +----- .../libraries/controllerDispatcherUtils.js | 4 +++- 8 files changed, 18 insertions(+), 24 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index e8f57ea834..78801df715 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -363,12 +363,18 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity return false; } -void EntityRenderer::updateModelTransform() { +void EntityRenderer::updateModelTransformAndBound() { bool success = false; auto newModelTransform = _entity->getTransformToCenter(success); if (success) { _modelTransform = newModelTransform; } + + success = false; + auto bound = _entity->getAABox(success); + if (success) { + _bound = bound; + } } void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { @@ -380,15 +386,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa } _prevIsTransparent = transparent; - bool success = false; - auto bound = entity->getAABox(success); - if (success) { - _bound = bound; - } - auto newModelTransform = entity->getTransformToCenter(success); - if (success) { - _modelTransform = newModelTransform; - } + updateModelTransformAndBound(); _moving = entity->isMovingRelativeToParent(); _visible = entity->getVisible(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 40966c4f41..496649eb5f 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -97,7 +97,7 @@ protected: virtual void doRender(RenderArgs* args) = 0; bool isFading() const { return _isFading; } - void updateModelTransform(); + void updateModelTransformAndBound(); virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; } inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index a6a6dc05f2..309671f49e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -126,7 +126,7 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi void* key = (void*)this; AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () { withWriteLock([&] { - updateModelTransform(); + updateModelTransformAndBound(); _renderTransform = getModelTransform(); }); }); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 2e0656ab81..c50b3bd760 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -106,10 +106,8 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _position = entity->getWorldPosition(); _dimensions = entity->getScaledDimensions(); _orientation = entity->getWorldOrientation(); - bool success = false; - auto newModelTransform = entity->getTransformToCenter(success); - _renderTransform = success ? newModelTransform : getModelTransform(); - + updateModelTransformAndBound(); + _renderTransform = getModelTransform(); if (_shape == entity::Sphere) { _renderTransform.postScale(SPHERE_ENTITY_SCALE); } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index ce4b6d9175..08a3b585e4 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -70,7 +70,7 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () { withWriteLock([&] { _dimensions = entity->getScaledDimensions(); - updateModelTransform(); + updateModelTransformAndBound(); _renderTransform = getModelTransform(); }); }); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 17d6d58781..793b4aa158 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -206,7 +206,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene glm::vec2 windowSize = getWindowSize(entity); _webSurface->resize(QSize(windowSize.x, windowSize.y)); - updateModelTransform(); + updateModelTransformAndBound(); _renderTransform = getModelTransform(); _renderTransform.postScale(entity->getScaledDimensions()); }); diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 00d7ad0491..580132a648 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -173,11 +173,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.lastUnequipCheckTime = now; if (props.parentID === MyAvatar.SELF_ID) { var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var handPosition = controllerData.controllerLocations[this.hand].position; - var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); - var distance = Vec3.distance(props.position, handPosition); - if ((dist > TEAR_AWAY_DISTANCE) || - (distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + if ((props.localPosition > TEAR_AWAY_DISTANCE * sensorScaleFactor)) { this.autoUnequipCounter++; } else { this.autoUnequipCounter = 0; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 5dfb0d5b69..9a886372b8 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -130,7 +130,9 @@ DISPATCHER_PROPERTIES = [ "type", "href", "cloneable", - "cloneDynamic" + "cloneDynamic", + "localPosition", + "localRotation" ]; // priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step From 7a7b9730eeef1d1fff51e5a47f51f687d24f8f6c Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 9 Jul 2018 15:36:22 -0700 Subject: [PATCH 05/56] only clamp handles in hmd outside bounding box --- scripts/system/libraries/entitySelectionTool.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 4ff139ee75..c9a15875f1 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1186,10 +1186,17 @@ SelectionDisplay = (function() { var localRotationZ = Quat.fromPitchYawRollDegrees(rotationDegrees, 0, 0); var rotationZ = Quat.multiply(rotation, localRotationZ); worldRotationZ = rotationZ; + + var selectionBoxGeometry = { + position: position, + rotation: rotation, + dimensions: dimensions + }; + var isCameraInsideBox = isPointInsideBox(Camera.position, selectionBoxGeometry); - // in HMD we clamp the overlays to the bounding box for now so lasers can hit them + // in HMD if outside the bounding box clamp the overlays to the bounding box for now so lasers can hit them var maxHandleDimension = 0; - if (HMD.active) { + if (HMD.active && !isCameraInsideBox) { maxHandleDimension = Math.max(dimensions.x, dimensions.y, dimensions.z); } @@ -1438,12 +1445,6 @@ SelectionDisplay = (function() { var inModeRotate = isActiveTool(handleRotatePitchRing) || isActiveTool(handleRotateYawRing) || isActiveTool(handleRotateRollRing); - var selectionBoxGeometry = { - position: position, - rotation: rotation, - dimensions: dimensions - }; - var isCameraInsideBox = isPointInsideBox(Camera.position, selectionBoxGeometry); selectionBoxGeometry.visible = !inModeRotate && !isCameraInsideBox; Overlays.editOverlay(selectionBox, selectionBoxGeometry); From 7a3118543824e53251782e24e14e0438672cca25 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 12 Jul 2018 11:31:21 -0700 Subject: [PATCH 06/56] Clear the frame buffer in all cases. --- .../render-utils/src/RenderCommonTask.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 24715f0afb..c2181b7613 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -51,19 +51,19 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& config->setNumDrawn((int)inItems.size()); emit config->numDrawnChanged(); + RenderArgs* args = renderContext->args; + + // Clear the framebuffer without stereo + // Needs to be distinct from the other batch because using the clear call + // while stereo is enabled triggers a warning + if (_opaquePass) { + gpu::doInBatch("DrawOverlay3D::run::clear", args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, false); + }); + } + if (!inItems.empty()) { - RenderArgs* args = renderContext->args; - - // Clear the framebuffer without stereo - // Needs to be distinct from the other batch because using the clear call - // while stereo is enabled triggers a warning - if (_opaquePass) { - gpu::doInBatch("DrawOverlay3D::run::clear", args->_context, [&](gpu::Batch& batch){ - batch.enableStereo(false); - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, false); - }); - } - // Render the items gpu::doInBatch("DrawOverlay3D::main", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; From 306a77c0399fee4055c6d0722d1e34642d603ee8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jul 2018 12:46:18 -0700 Subject: [PATCH 07/56] fix delete event --- scripts/system/edit.js | 8 ++------ scripts/system/libraries/entityList.js | 12 +++++++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 73088560d9..c40f97a606 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1573,15 +1573,11 @@ function deleteSelectedEntities() { Entities.deleteEntity(entityID); } } - + if (savedProperties.length > 0) { SelectionManager.clearSelections(); pushCommandForSelections([], savedProperties); - - entityListTool.webView.emitScriptEvent(JSON.stringify({ - type: "deleted", - ids: deletedIDs - })); + entityListTool.deleteEntities(deletedIDs); } } } diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index de8e5d9c06..ae89b63ea6 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -93,12 +93,18 @@ EntityListTool = function() { }; that.removeEntities = function (deletedIDs, selectedIDs) { - var data = { + emitJSONScriptEvent({ type: 'removeEntities', deletedIDs: deletedIDs, selectedIDs: selectedIDs - }; - webView.emitScriptEvent(JSON.stringify(data)); + }); + }; + + that.deleteEntities = function (deletedIDs) { + emitJSONScriptEvent({ + type: "deleted", + ids: deletedIDs + }); }; function valueIfDefined(value) { From 1c64ebc3caf1568bd4edd0fa1753926e9a4be2cb Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 12 Jul 2018 13:57:48 -0700 Subject: [PATCH 08/56] fixing combo boxes --- interface/resources/qml/controls-uit/ComboBox.qml | 1 - interface/resources/qml/hifi/avatarapp/AdjustWearables.qml | 1 - 2 files changed, 2 deletions(-) diff --git a/interface/resources/qml/controls-uit/ComboBox.qml b/interface/resources/qml/controls-uit/ComboBox.qml index 9ec5ed19ba..be8c9f6740 100644 --- a/interface/resources/qml/controls-uit/ComboBox.qml +++ b/interface/resources/qml/controls-uit/ComboBox.qml @@ -46,7 +46,6 @@ FocusScope { hoverEnabled: true visible: true height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control. - textRole: "text" function previousItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count - 1) % comboBox.count; } function nextItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count + 1) % comboBox.count; } diff --git a/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml b/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml index a501185853..10613a9ec1 100644 --- a/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml +++ b/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml @@ -125,7 +125,6 @@ Rectangle { id: wearablesCombobox anchors.left: parent.left anchors.right: parent.right - comboBox.textRole: "text" model: ListModel { function findIndexById(id) { From 089831b6ee3ccab29721250819033656fa5670d9 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Thu, 12 Jul 2018 14:15:16 -0700 Subject: [PATCH 09/56] Adding potential fix --- interface/resources/qml/Browser.qml | 1 + interface/resources/qml/LoginDialog/LinkAccountBody.qml | 8 ++++++-- interface/src/ui/LoginDialog.cpp | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index f0475dfebd..4474cfb2cd 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -26,6 +26,7 @@ ScrollingWindow { y: 100 Component.onCompleted: { + focus = true shown = true addressBar.text = webview.url } diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 814778a4b1..fe971b31ee 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -140,7 +140,9 @@ Item { horizontalAlignment: Text.AlignHCenter linkColor: hifi.colors.blueAccent - onLinkActivated: loginDialog.openUrl(link) + onLinkActivated: { + loginDialog.openUrl(link); + } } onFocusChanged: { root.text = ""; @@ -170,7 +172,9 @@ Item { horizontalAlignment: Text.AlignHCenter linkColor: hifi.colors.blueAccent - onLinkActivated: loginDialog.openUrl(link) + onLinkActivated: { + loginDialog.openUrl(link); + } } onFocusChanged: { diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 4d8592a9d3..9804c6712a 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -172,11 +172,13 @@ void LoginDialog::openUrl(const QString& url) const { offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) { newObject->setProperty("url", url); }); + LoginDialog::hide(); } else { if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) { offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) { newObject->setProperty("url", url); }); + LoginDialog::hide(); } else { tablet->gotoWebScreen(url); } From 92756d81ad8296b1c6caa3b4bcdaa16080e53877 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 12 Jul 2018 15:03:01 -0700 Subject: [PATCH 10/56] Implement MS16562: Massive PAL speedup! --- interface/resources/qml/hifi/Pal.qml | 4 +- interface/src/avatar/AvatarManager.cpp | 39 +++++++ interface/src/avatar/AvatarManager.h | 2 + scripts/system/pal.js | 148 ++++++++++++------------- 4 files changed, 112 insertions(+), 81 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 3059707313..06ad57139d 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -1108,7 +1108,7 @@ Rectangle { function findNearbySessionIndex(sessionId, optionalData) { // no findIndex in .qml var data = optionalData || nearbyUserModelData, length = data.length; for (var i = 0; i < length; i++) { - if (data[i].sessionId === sessionId) { + if (data[i].sessionId === sessionId.toString()) { return i; } } @@ -1120,7 +1120,7 @@ Rectangle { var data = message.params; var index = -1; iAmAdmin = Users.canKick; - index = findNearbySessionIndex('', data); + index = findNearbySessionIndex(MyAvatar.sessionUUID, data); if (index !== -1) { myData = data[index]; data.splice(index, 1); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 29ad71ead6..a7ee5f4869 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "AvatarLogging.h" @@ -668,3 +669,41 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV DependencyManager::get()->broadcastToNodes(std::move(packet), NodeSet() << NodeType::AvatarMixer); } } + +QString AvatarManager::getPalData(const QList specificAvatarIdentifiers) { + QJsonArray palData; + + auto avatarMap = getHashCopy(); + AvatarHash::iterator itr = avatarMap.begin(); + while (itr != avatarMap.end()) { + std::shared_ptr avatar = std::static_pointer_cast(*itr); + QString currentSessionUUID = avatar->getSessionUUID().toString(); + if (specificAvatarIdentifiers.isEmpty() || specificAvatarIdentifiers.contains(currentSessionUUID)) { + QJsonObject thisAvatarPalData; + thisAvatarPalData.insert("sessionUUID", currentSessionUUID); + thisAvatarPalData.insert("sessionDisplayName", avatar->getSessionDisplayName()); + thisAvatarPalData.insert("audioLoudness", avatar->getAudioLoudness()); + thisAvatarPalData.insert("isReplicated", avatar->getIsReplicated()); + + glm::vec3 position = avatar->getWorldPosition(); + QJsonObject jsonPosition; + jsonPosition.insert("x", position.x); + jsonPosition.insert("y", position.y); + jsonPosition.insert("z", position.z); + thisAvatarPalData.insert("position", jsonPosition); + + float palOrbOffset = 0.2f; + int headIndex = avatar->getJointIndex("Head"); + if (headIndex > 0) { + glm::vec3 jointTranslation = avatar->getAbsoluteJointTranslationInObjectFrame(headIndex); + palOrbOffset = jointTranslation.y / 2; + } + thisAvatarPalData.insert("palOrbOffset", palOrbOffset); + + palData.append(thisAvatarPalData); + } + ++itr; + } + QJsonDocument doc(palData); + return doc.toJson(QJsonDocument::Compact); +} diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index ff29c1b381..507767866b 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -157,6 +157,8 @@ public: */ Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value); + Q_INVOKABLE QString getPalData(const QList specificAvatarIdentifiers = QList()); + float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } int getIdentityRequestsSent() const { return _identityRequestsSent; } diff --git a/scripts/system/pal.js b/scripts/system/pal.js index e967ee6469..4a0d866d66 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -19,7 +19,7 @@ var populateNearbyUserList, color, textures, removeOverlays, controllerComputePickRay, onTabletButtonClicked, onTabletScreenChanged, receiveMessage, avatarDisconnected, clearLocalQMLDataAndClosePAL, - createAudioInterval, tablet, CHANNEL, getConnectionData, findableByChanged, + tablet, CHANNEL, getConnectionData, findableByChanged, avatarAdded, avatarRemoved, avatarSessionChanged; // forward references; // hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed @@ -447,21 +447,24 @@ function populateNearbyUserList(selectData, oldAudioData) { verticalAngleNormal = filter && Quat.getRight(orientation), horizontalAngleNormal = filter && Quat.getUp(orientation); avatarsOfInterest = {}; - avatars.forEach(function (id) { - var avatar = AvatarList.getAvatar(id); - var name = avatar.sessionDisplayName; + + var avatarData = JSON.parse(AvatarList.getPalData()); + + avatarData.forEach(function (currentAvatarData) { + var id = currentAvatarData.sessionUUID; + var name = currentAvatarData.sessionDisplayName; if (!name) { // Either we got a data packet but no identity yet, or something is really messed up. In any case, // we won't be able to do anything with this user, so don't include them. // In normal circumstances, a refresh will bring in the new user, but if we're very heavily loaded, // we could be losing and gaining people randomly. - print('No avatar identity data for', id); + print('No avatar identity data for', currentAvatarData.sessionUUID); return; } - if (id && myPosition && (Vec3.distance(avatar.position, myPosition) > filter.distance)) { + if (id && myPosition && (Vec3.distance(currentAvatarData.position, myPosition) > filter.distance)) { return; } - var normal = id && filter && Vec3.normalize(Vec3.subtract(avatar.position, myPosition)); + var normal = id && filter && Vec3.normalize(Vec3.subtract(currentAvatarData.position, myPosition)); var horizontal = normal && angleBetweenVectorsInPlane(normal, forward, horizontalAngleNormal); var vertical = normal && angleBetweenVectorsInPlane(normal, forward, verticalAngleNormal); if (id && filter && ((Math.abs(horizontal) > horizontalHalfAngle) || (Math.abs(vertical) > verticalHalfAngle))) { @@ -480,11 +483,11 @@ function populateNearbyUserList(selectData, oldAudioData) { personalMute: !!id && Users.getPersonalMuteStatus(id), // expects proper boolean, not null ignore: !!id && Users.getIgnoreStatus(id), // ditto isPresent: true, - isReplicated: avatar.isReplicated + isReplicated: currentAvatarData.isReplicated }; // Everyone needs to see admin status. Username and fingerprint returns default constructor output if the requesting user isn't an admin. Users.requestUsernameFromID(id); - if (id) { + if (id !== MyAvatar.sessionUUID) { addAvatarNode(id); // No overlay for ourselves avatarsOfInterest[id] = true; } else { @@ -515,30 +518,60 @@ function usernameFromIDReply(id, username, machineFingerprint, isAdmin) { updateUser(data); } +function updateAudioLevel(overlay, avatarData) { + // the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged + // But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency + // of updating (the latter for efficiency too). + var audioLevel = 0.0; + var avgAudioLevel = 0.0; + + // we will do exponential moving average by taking some the last loudness and averaging + overlay.accumulatedLevel = AVERAGING_RATIO * (overlay.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatarData.audioLoudness); + + // add 1 to insure we don't go log() and hit -infinity. Math.log is + // natural log, so to get log base 2, just divide by ln(2). + audioLevel = scaleAudio(Math.log(overlay.accumulatedLevel + 1) / LOG2); + + // decay avgAudioLevel + avgAudioLevel = Math.max((1 - AUDIO_PEAK_DECAY) * (overlay.avgAudioLevel || 0), audioLevel); + + overlay.avgAudioLevel = avgAudioLevel; + overlay.audioLevel = audioLevel; + + // now scale for the gain. Also, asked to boost the low end, so one simple way is + // to take sqrt of the value. Lets try that, see how it feels. + avgAudioLevel = Math.min(1.0, Math.sqrt(avgAudioLevel * (sessionGains[avatarData.sessionUUID] || 0.75))); + + + var param = {}; + var level = [audioLevel, avgAudioLevel]; + var userId = avatarData.sessionUUID || 0; + param[userId] = level; + sendToQml({ method: 'updateAudioLevel', params: param }); +} + var pingPong = true; function updateOverlays() { var eye = Camera.position; - AvatarList.getAvatarIdentifiers().forEach(function (id) { - if (!id || !avatarsOfInterest[id]) { + + var avatarData = JSON.parse(AvatarList.getPalData()); + + avatarData.forEach(function (currentAvatarData) { + if (currentAvatarData.sessionUUID === MyAvatar.sessionUUID || !avatarsOfInterest[currentAvatarData.sessionUUID]) { return; // don't update ourself, or avatars we're not interested in } - var avatar = AvatarList.getAvatar(id); - if (!avatar) { - return; // will be deleted below if there had been an overlay. - } - var overlay = ExtendedOverlay.get(id); + var overlay = ExtendedOverlay.get(currentAvatarData.sessionUUID); if (!overlay) { // For now, we're treating this as a temporary loss, as from the personal space bubble. Add it back. - print('Adding non-PAL avatar node', id); - overlay = addAvatarNode(id); + print('Adding non-PAL avatar node', currentAvatarData.sessionUUID); + overlay = addAvatarNode(currentAvatarData.sessionUUID); } - var target = avatar.position; + + updateAudioLevel(overlay, currentAvatarData); + + var target = currentAvatarData.position; var distance = Vec3.distance(target, eye); - var offset = 0.2; + var offset = currentAvatarData.palOrbOffset; var diff = Vec3.subtract(target, eye); // get diff between target and eye (a vector pointing to the eye from avatar position) - var headIndex = avatar.getJointIndex("Head"); // base offset on 1/2 distance from hips to head if we can - if (headIndex > 0) { - offset = avatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y / 2; - } // move a bit in front, towards the camera target = Vec3.subtract(target, Vec3.multiply(Vec3.normalize(diff), offset)); @@ -548,7 +581,7 @@ function updateOverlays() { overlay.ping = pingPong; overlay.editOverlay({ - color: color(ExtendedOverlay.isSelected(id), overlay.hovering, overlay.audioLevel), + color: color(ExtendedOverlay.isSelected(currentAvatarData.sessionUUID), overlay.hovering, overlay.audioLevel), position: target, dimensions: 0.032 * distance }); @@ -704,6 +737,13 @@ function wireEventBridge(on) { hasEventBridge = false; } } + } + +var UPDATE_INTERVAL_MS = 100; +function createUpdateInterval() { + return Script.setInterval(function () { + updateOverlays(); + }, UPDATE_INTERVAL_MS); } function onTabletScreenChanged(type, url) { @@ -719,10 +759,8 @@ function onTabletScreenChanged(type, url) { ContextOverlay.enabled = false; Users.requestsDomainListData = true; - audioTimer = createAudioInterval(AUDIO_LEVEL_UPDATE_INTERVAL_MS); - tablet.tabletShownChanged.connect(tabletVisibilityChanged); - Script.update.connect(updateOverlays); + updateInterval = createUpdateInterval(); Controller.mousePressEvent.connect(handleMouseEvent); Controller.mouseMoveEvent.connect(handleMouseMoveEvent); Users.usernameFromIDReply.connect(usernameFromIDReply); @@ -778,50 +816,6 @@ function scaleAudio(val) { return audioLevel; } -function getAudioLevel(id) { - // the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged - // But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency - // of updating (the latter for efficiency too). - var avatar = AvatarList.getAvatar(id); - var audioLevel = 0.0; - var avgAudioLevel = 0.0; - var data = id ? ExtendedOverlay.get(id) : myData; - if (data) { - - // we will do exponential moving average by taking some the last loudness and averaging - data.accumulatedLevel = AVERAGING_RATIO * (data.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatar.audioLoudness); - - // add 1 to insure we don't go log() and hit -infinity. Math.log is - // natural log, so to get log base 2, just divide by ln(2). - audioLevel = scaleAudio(Math.log(data.accumulatedLevel + 1) / LOG2); - - // decay avgAudioLevel - avgAudioLevel = Math.max((1 - AUDIO_PEAK_DECAY) * (data.avgAudioLevel || 0), audioLevel); - - data.avgAudioLevel = avgAudioLevel; - data.audioLevel = audioLevel; - - // now scale for the gain. Also, asked to boost the low end, so one simple way is - // to take sqrt of the value. Lets try that, see how it feels. - avgAudioLevel = Math.min(1.0, Math.sqrt(avgAudioLevel * (sessionGains[id] || 0.75))); - } - return [audioLevel, avgAudioLevel]; -} - -function createAudioInterval(interval) { - // we will update the audioLevels periodically - // TODO: tune for efficiency - expecially with large numbers of avatars - return Script.setInterval(function () { - var param = {}; - AvatarList.getAvatarIdentifiers().forEach(function (id) { - var level = getAudioLevel(id), - userId = id || 0; // qml didn't like an object with null/empty string for a key, so... - param[userId] = level; - }); - sendToQml({method: 'updateAudioLevel', params: param}); - }, interval); -} - function avatarDisconnected(nodeID) { // remove from the pal list sendToQml({method: 'avatarDisconnected', params: [nodeID]}); @@ -874,11 +868,11 @@ startup(); var isWired = false; -var audioTimer; -var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too) function off() { if (isWired) { - Script.update.disconnect(updateOverlays); + if (updateInterval) { + Script.clearInterval(updateInterval); + } Controller.mousePressEvent.disconnect(handleMouseEvent); Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent); tablet.tabletShownChanged.disconnect(tabletVisibilityChanged); @@ -889,10 +883,6 @@ function off() { Users.requestsDomainListData = false; isWired = false; - - if (audioTimer) { - Script.clearInterval(audioTimer); - } } removeOverlays(); From fa518b995aad602c4c483f6470a5880d46b4f151 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 12 Jul 2018 15:16:54 -0700 Subject: [PATCH 11/56] Fix my audio level --- scripts/system/pal.js | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 4a0d866d66..b811f5e95a 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -525,27 +525,30 @@ function updateAudioLevel(overlay, avatarData) { var audioLevel = 0.0; var avgAudioLevel = 0.0; - // we will do exponential moving average by taking some the last loudness and averaging - overlay.accumulatedLevel = AVERAGING_RATIO * (overlay.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatarData.audioLoudness); + if (overlay) { + // we will do exponential moving average by taking some the last loudness and averaging + overlay.accumulatedLevel = AVERAGING_RATIO * (overlay.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatarData.audioLoudness); - // add 1 to insure we don't go log() and hit -infinity. Math.log is - // natural log, so to get log base 2, just divide by ln(2). - audioLevel = scaleAudio(Math.log(overlay.accumulatedLevel + 1) / LOG2); + // add 1 to insure we don't go log() and hit -infinity. Math.log is + // natural log, so to get log base 2, just divide by ln(2). + audioLevel = scaleAudio(Math.log(overlay.accumulatedLevel + 1) / LOG2); - // decay avgAudioLevel - avgAudioLevel = Math.max((1 - AUDIO_PEAK_DECAY) * (overlay.avgAudioLevel || 0), audioLevel); + // decay avgAudioLevel + avgAudioLevel = Math.max((1 - AUDIO_PEAK_DECAY) * (overlay.avgAudioLevel || 0), audioLevel); - overlay.avgAudioLevel = avgAudioLevel; - overlay.audioLevel = audioLevel; - - // now scale for the gain. Also, asked to boost the low end, so one simple way is - // to take sqrt of the value. Lets try that, see how it feels. - avgAudioLevel = Math.min(1.0, Math.sqrt(avgAudioLevel * (sessionGains[avatarData.sessionUUID] || 0.75))); + overlay.avgAudioLevel = avgAudioLevel; + overlay.audioLevel = audioLevel; + // now scale for the gain. Also, asked to boost the low end, so one simple way is + // to take sqrt of the value. Lets try that, see how it feels. + avgAudioLevel = Math.min(1.0, Math.sqrt(avgAudioLevel * (sessionGains[avatarData.sessionUUID] || 0.75))); + } else { + audioLevel = scaleAudio(Math.log(((1 - AVERAGING_RATIO) * (avatarData.audioLoudness)) + 1) / LOG2); + } var param = {}; var level = [audioLevel, avgAudioLevel]; - var userId = avatarData.sessionUUID || 0; + var userId = avatarData.sessionUUID === MyAvatar.sessionUUID ? 0 : avatarData.sessionUUID; param[userId] = level; sendToQml({ method: 'updateAudioLevel', params: param }); } @@ -557,6 +560,8 @@ function updateOverlays() { var avatarData = JSON.parse(AvatarList.getPalData()); avatarData.forEach(function (currentAvatarData) { + updateAudioLevel(overlay, currentAvatarData); + if (currentAvatarData.sessionUUID === MyAvatar.sessionUUID || !avatarsOfInterest[currentAvatarData.sessionUUID]) { return; // don't update ourself, or avatars we're not interested in } @@ -566,8 +571,6 @@ function updateOverlays() { overlay = addAvatarNode(currentAvatarData.sessionUUID); } - updateAudioLevel(overlay, currentAvatarData); - var target = currentAvatarData.position; var distance = Vec3.distance(target, eye); var offset = currentAvatarData.palOrbOffset; From 04f856019d1fb6c96486402ef3d2013d369878ed Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 12 Jul 2018 16:27:19 -0700 Subject: [PATCH 12/56] Fix MS16701: Uninstall installed app before updating --- .../hifi/commerce/purchases/PurchasedItem.qml | 10 +++++++++- .../qml/hifi/commerce/purchases/Purchases.qml | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 0a69b8b3b5..13dc3cb37f 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -328,7 +328,15 @@ Item { item.buttonColor = "#E2334D"; item.buttonClicked = function() { sendToPurchases({ method: 'flipCard', closeAll: true }); - sendToPurchases({method: 'updateItemClicked', itemId: root.itemId, itemEdition: root.itemEdition, upgradeUrl: root.upgradeUrl}); + sendToPurchases({ + method: 'updateItemClicked', + itemId: root.itemId, + itemEdition: root.itemEdition, + upgradeUrl: root.upgradeUrl, + itemHref: root.itemHref, + itemType: root.itemType, + isInstalled: root.isInstalled + }); } } } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 16ad01a56d..91993d0fa3 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -706,7 +706,23 @@ Rectangle { } } } else if (msg.method === "updateItemClicked") { - sendToScript(msg); + if (msg.itemType === "app" && msg.isInstalled) { + lightboxPopup.titleText = "Uninstall App"; + lightboxPopup.bodyText = "The app that you are trying to update is installed.

" + + "If you proceed, the current version of the app will be uninstalled."; + lightboxPopup.button1text = "CANCEL"; + lightboxPopup.button1method = function() { + lightboxPopup.visible = false; + } + lightboxPopup.button2text = "CONFIRM"; + lightboxPopup.button2method = function() { + Commerce.uninstallApp(msg.itemHref); + sendToScript(msg); + }; + lightboxPopup.visible = true; + } else { + sendToScript(msg); + } } else if (msg.method === "giftAsset") { sendAsset.assetName = msg.itemName; sendAsset.assetCertID = msg.certId; From 437f49ac22ad9644e88a81bbd98bd75a6bac728a Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 13 Jul 2018 03:01:02 +0300 Subject: [PATCH 13/56] 16683 Avatar App - Add to Favorites Button Not Working --- scripts/system/avatarapp.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/system/avatarapp.js b/scripts/system/avatarapp.js index de84782471..f692128fa3 100644 --- a/scripts/system/avatarapp.js +++ b/scripts/system/avatarapp.js @@ -159,6 +159,9 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See for(var bookmarkName in message.data.bookmarks) { var bookmark = message.data.bookmarks[bookmarkName]; + if (!bookmark.avatarEntites) { // ensure avatarEntites always exist + bookmark.avatarEntites = []; + } bookmark.avatarEntites.forEach(function(avatarEntity) { avatarEntity.properties.localRotationAngles = Quat.safeEulerAngles(avatarEntity.properties.localRotation) From e35cb374ae976d47723a82923211bd4443956427 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 12 Jul 2018 18:04:10 -0700 Subject: [PATCH 14/56] Re-host dependencies and update URLs to hifi.com --- cmake/externals/GifCreator/CMakeLists.txt | 2 +- cmake/externals/LibOVR/CMakeLists.txt | 4 ++-- cmake/externals/LibOVRPlatform/CMakeLists.txt | 2 +- cmake/externals/boostconfig/CMakeLists.txt | 2 +- cmake/externals/bullet/CMakeLists.txt | 4 ++-- cmake/externals/crashpad/CMakeLists.txt | 4 ++-- cmake/externals/draco/CMakeLists.txt | 2 +- cmake/externals/etc2comp/CMakeLists.txt | 2 +- cmake/externals/gli/CMakeLists.txt | 2 +- cmake/externals/glm/CMakeLists.txt | 2 +- cmake/externals/hifiAudioCodec/CMakeLists.txt | 8 ++++---- cmake/externals/neuron/CMakeLists.txt | 2 +- cmake/externals/nvtt/CMakeLists.txt | 4 ++-- cmake/externals/openvr/CMakeLists.txt | 2 +- cmake/externals/polyvox/CMakeLists.txt | 2 +- cmake/externals/quazip/CMakeLists.txt | 2 +- cmake/externals/sdl2/CMakeLists.txt | 6 +++--- cmake/externals/sixense/CMakeLists.txt | 6 +++--- cmake/externals/steamworks/CMakeLists.txt | 2 +- cmake/externals/tbb/CMakeLists.txt | 6 +++--- cmake/externals/vhacd/CMakeLists.txt | 2 +- cmake/externals/wasapi/CMakeLists.txt | 2 +- cmake/externals/zlib/CMakeLists.txt | 2 +- 23 files changed, 36 insertions(+), 36 deletions(-) diff --git a/cmake/externals/GifCreator/CMakeLists.txt b/cmake/externals/GifCreator/CMakeLists.txt index 127bdf28f5..094f5612a9 100644 --- a/cmake/externals/GifCreator/CMakeLists.txt +++ b/cmake/externals/GifCreator/CMakeLists.txt @@ -3,7 +3,7 @@ set(EXTERNAL_NAME GifCreator) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/dependencies/GifCreator.zip + URL https://public.highfidelity.com/dependencies/GifCreator.zip URL_MD5 8ac8ef5196f47c658dce784df5ecdb70 CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index ed76f181e7..ae4cf6320e 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -17,7 +17,7 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.26.0_public.zip + URL https://public.highfidelity.com/dependencies/ovr_sdk_win_1.26.0_public.zip URL_MD5 06804ff9727b910dcd04a37c800053b5 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" /CMakeLists.txt @@ -38,7 +38,7 @@ elseif(APPLE) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://static.oculus.com/sdk-downloads/ovr_sdk_macos_0.5.0.1.tar.gz + URL https://public.highfidelity.com/dependencies/ovr_sdk_macos_0.5.0.1.tar.gz URL_MD5 0a0785a04fb285f64f62267388344ad6 CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/LibOVRPlatform/CMakeLists.txt b/cmake/externals/LibOVRPlatform/CMakeLists.txt index 3622972a13..895efa9357 100644 --- a/cmake/externals/LibOVRPlatform/CMakeLists.txt +++ b/cmake/externals/LibOVRPlatform/CMakeLists.txt @@ -9,7 +9,7 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/OVRPlatformSDK_v1.10.0.zip + URL https://public.highfidelity.com/dependencies/OVRPlatformSDK_v1.10.0.zip URL_MD5 e6c8264af16d904e6506acd5172fa0a9 CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/boostconfig/CMakeLists.txt b/cmake/externals/boostconfig/CMakeLists.txt index 0adb349589..e33167b0ba 100644 --- a/cmake/externals/boostconfig/CMakeLists.txt +++ b/cmake/externals/boostconfig/CMakeLists.txt @@ -5,7 +5,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} #URL https://github.com/boostorg/config/archive/boost-1.58.0.zip - URL http://hifi-public.s3.amazonaws.com/dependencies/config-boost-1.58.0.zip + URL https://public.highfidelity.com/dependencies/config-boost-1.58.0.zip URL_MD5 42fa673bae2b7645a22736445e80eb8d CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 91860a7470..ffa1c67ce3 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -17,7 +17,7 @@ include(ExternalProject) if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz + URL https://public.highfidelity.com/dependencies/bullet-2.88.tgz URL_MD5 0a6876607ebe83e227427215f15946fd CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0 LOG_DOWNLOAD 1 @@ -28,7 +28,7 @@ if (WIN32) else () ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz + URL https://public.highfidelity.com/dependencies/bullet-2.88.tgz URL_MD5 0a6876607ebe83e227427215f15946fd CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 diff --git a/cmake/externals/crashpad/CMakeLists.txt b/cmake/externals/crashpad/CMakeLists.txt index 648ec83280..34348b6418 100644 --- a/cmake/externals/crashpad/CMakeLists.txt +++ b/cmake/externals/crashpad/CMakeLists.txt @@ -6,7 +6,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://public.highfidelity.com/dependencies/crashpad_062317.1.zip + URL https://public.highfidelity.com/dependencies/crashpad_062317.1.zip URL_MD5 9c84b77f5f23daf939da1371825ed2b1 CONFIGURE_COMMAND "" BUILD_COMMAND "" @@ -25,7 +25,7 @@ if (WIN32) elseif (APPLE) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://public.highfidelity.com/dependencies/crashpad_mac_070318.zip + URL https://public.highfidelity.com/dependencies/crashpad_mac_070318.zip URL_MD5 ba1501dc163591ac2d1be74946967e2a CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/draco/CMakeLists.txt b/cmake/externals/draco/CMakeLists.txt index 6a894e76b6..28a2177cbb 100644 --- a/cmake/externals/draco/CMakeLists.txt +++ b/cmake/externals/draco/CMakeLists.txt @@ -11,7 +11,7 @@ endif () include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/draco-1.1.0.zip + URL https://public.highfidelity.com/dependencies/draco-1.1.0.zip URL_MD5 208f8b04c91d5f1c73d731a3ea37c5bb CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=-$ ${EXTRA_CMAKE_FLAGS} LOG_DOWNLOAD 1 diff --git a/cmake/externals/etc2comp/CMakeLists.txt b/cmake/externals/etc2comp/CMakeLists.txt index b497212625..88ed988873 100644 --- a/cmake/externals/etc2comp/CMakeLists.txt +++ b/cmake/externals/etc2comp/CMakeLists.txt @@ -15,7 +15,7 @@ include(ExternalProject) # that would override CMAKE_CXX_FLAGS ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/dependencies/etc2comp-patched.zip + URL https://public.highfidelity.com/dependencies/etc2comp-patched.zip URL_MD5 4c96153eb179acbe619e3d99d3330595 CMAKE_ARGS ${ANDROID_CMAKE_ARGS} ${EXTRA_CMAKE_FLAGS} BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build diff --git a/cmake/externals/gli/CMakeLists.txt b/cmake/externals/gli/CMakeLists.txt index 2ef4d2b3af..bde31cbede 100644 --- a/cmake/externals/gli/CMakeLists.txt +++ b/cmake/externals/gli/CMakeLists.txt @@ -3,7 +3,7 @@ set(EXTERNAL_NAME gli) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/dependencies/gli-0.8.1.0.zip + URL https://public.highfidelity.com/dependencies/gli-0.8.1.0.zip URL_MD5 00c990f59c12bbf367956ef399d6f798 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CONFIGURE_COMMAND "" diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index 0a83004438..a52ddde9f5 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -3,7 +3,7 @@ set(EXTERNAL_NAME glm) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.5-patched.zip + URL https://public.highfidelity.com/dependencies/glm-0.9.8.5-patched.zip URL_MD5 7d39ecc1cea275427534c3cfd6dd63f0 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= ${EXTERNAL_ARGS} diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt index e3ba36a440..8a8e2573d5 100644 --- a/cmake/externals/hifiAudioCodec/CMakeLists.txt +++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt @@ -6,16 +6,16 @@ set(EXTERNAL_NAME hifiAudioCodec) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (WIN32) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-win-2.0.zip) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-win-2.0.zip) set(DOWNLOAD_MD5 9199d4dbd6b16bed736b235efe980e67) elseif (APPLE) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-mac-2.0.zip) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-mac-2.0.zip) set(DOWNLOAD_MD5 21649881e7d5dc94f922179be96f76ba) elseif (ANDROID) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-android-2.0.zip) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-android-2.0.zip) set(DOWNLOAD_MD5 aef2a852600d498d58aa586668191683) elseif (UNIX) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-linux-2.0.zip) set(DOWNLOAD_MD5 67fb7755f9bcafb98a9fceea53bc7481) else() return() diff --git a/cmake/externals/neuron/CMakeLists.txt b/cmake/externals/neuron/CMakeLists.txt index 76dda8f8c5..5ac38bc442 100644 --- a/cmake/externals/neuron/CMakeLists.txt +++ b/cmake/externals/neuron/CMakeLists.txt @@ -4,7 +4,7 @@ set(EXTERNAL_NAME neuron) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(NEURON_URL "https://s3.amazonaws.com/hifi-public/dependencies/neuron_datareader_b.12.2.zip") +set(NEURON_URL "https://public.highfidelity.com/dependencies/neuron_datareader_b.12.2.zip") set(NEURON_URL_MD5 "84273ad2200bf86a9279d1f412a822ca") ExternalProject_Add(${EXTERNAL_NAME} diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index 3076217c33..2db8335cd7 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -8,7 +8,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.hifi.zip + URL https://public.highfidelity.com/dependencies/nvtt-win-2.1.0.hifi.zip URL_MD5 10da01cf601f88f6dc12a6bc13c89136 CONFIGURE_COMMAND "" BUILD_COMMAND "" @@ -29,7 +29,7 @@ else () ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.hifi-83462e4.zip + URL https://public.highfidelity.com/dependencies/nvidia-texture-tools-2.1.0.hifi-83462e4.zip URL_MD5 602776e08515b54bfa1b8dc455003f0f CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_POSITION_INDEPENDENT_CODE=ON LOG_DOWNLOAD 1 diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index cb4aafcf8b..a04dbcf3e6 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -7,7 +7,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://github.com/ValveSoftware/openvr/archive/v1.0.6.zip + URL https://public.highfidelity.com/dependencies/v1.0.6.zip URL_MD5 f6892cd3a3078f505d03b4297f5a1951 CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/polyvox/CMakeLists.txt b/cmake/externals/polyvox/CMakeLists.txt index c799b45e78..a92c07da86 100644 --- a/cmake/externals/polyvox/CMakeLists.txt +++ b/cmake/externals/polyvox/CMakeLists.txt @@ -3,7 +3,7 @@ set(EXTERNAL_NAME polyvox) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox-master-2015-7-15.zip + URL https://public.highfidelity.com/dependencies/polyvox-master-2015-7-15.zip URL_MD5 9ec6323b87e849ae36e562ae1c7494a9 CMAKE_ARGS -DENABLE_EXAMPLES=OFF -DENABLE_BINDINGS=OFF -DCMAKE_INSTALL_PREFIX:PATH= BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index 7bf6f05d9f..6960f7682a 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -13,7 +13,7 @@ endif () ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/dependencies/quazip-0.7.3.zip + URL https://public.highfidelity.com/dependencies/quazip-0.7.3.zip URL_MD5 ed03754d39b9da1775771819b8001d45 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index cb61516b9a..635a1cb5bb 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -7,7 +7,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/SDL2-devel-2.0.3-VC.zip + URL https://public.highfidelity.com/dependencies/SDL2-devel-2.0.3-VC.zip URL_MD5 30a333bcbe94bc5016e8799c73e86233 CONFIGURE_COMMAND "" BUILD_COMMAND "" @@ -18,7 +18,7 @@ elseif (APPLE) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/SDL2-2.0.3.zip + URL https://public.highfidelity.com/dependencies/SDL2-2.0.3.zip CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DVIDEO_OPENGL=OFF BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build LOG_DOWNLOAD 1 @@ -49,7 +49,7 @@ else () ExternalProject_Add( ${EXTERNAL_NAME} - URL http://www.libsdl.org/release/SDL2-2.0.3.tar.gz + URL https://public.highfidelity.com/dependencies/SDL2-2.0.3.tar.gz URL_MD5 fe6c61d2e9df9ef570e7e80c6e822537 CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD 1 diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index bd0d042c0b..17d2f98e2d 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -4,15 +4,15 @@ set(EXTERNAL_NAME sixense) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_062612.zip") +#set(SIXENSE_URL "https://public.highfidelity.com/dependencies/SixenseSDK_062612.zip") #set(SIXENSE_URL_MD5 "10cc8dc470d2ac1244a88cf04bc549cc") #set(SIXENSE_NEW_LAYOUT 0) -set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip") +set(SIXENSE_URL "https://public.highfidelity.com/dependencies/SixenseSDK_071615.zip") set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d") set(SIXENSE_NEW_LAYOUT 1) -#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip") +#set(SIXENSE_URL "https://public.highfidelity.com/dependencies/SixenseSDK_102215.zip") #set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1") #set(SIXENSE_NEW_LAYOUT 1) diff --git a/cmake/externals/steamworks/CMakeLists.txt b/cmake/externals/steamworks/CMakeLists.txt index 152e95cdcf..30b3926436 100644 --- a/cmake/externals/steamworks/CMakeLists.txt +++ b/cmake/externals/steamworks/CMakeLists.txt @@ -4,7 +4,7 @@ set(EXTERNAL_NAME steamworks) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(STEAMWORKS_URL "https://s3.amazonaws.com/hifi-public/dependencies/steamworks_sdk_137.zip") +set(STEAMWORKS_URL "https://public.highfidelity.com/dependencies/steamworks_sdk_137.zip") set(STEAMWORKS_URL_MD5 "95ba9d0e3ddc04f8a8be17d2da806cbb") ExternalProject_Add( diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 9664fe7250..436cae79a1 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -3,13 +3,13 @@ set(EXTERNAL_NAME tbb) include(ExternalProject) if (WIN32) - set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_win_slim.zip) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/tbb2017_20170604oss_win_slim.zip) set(DOWNLOAD_MD5 065934458e3db88397f3d10e7eea536c) elseif (APPLE) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb2017_20170604oss_mac_slim.tar.gz) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/tbb2017_20170604oss_mac_slim.tar.gz) set(DOWNLOAD_MD5 62bde626b396f8e1a85c6a8ded1d8105) else () - set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_lin_slim.tar.gz) + set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/tbb2017_20170604oss_lin_slim.tar.gz) set(DOWNLOAD_MD5 2a5c721f40fa3503ffc12c18dd00011c) endif () diff --git a/cmake/externals/vhacd/CMakeLists.txt b/cmake/externals/vhacd/CMakeLists.txt index 11afa255f1..fe19f7ac7a 100644 --- a/cmake/externals/vhacd/CMakeLists.txt +++ b/cmake/externals/vhacd/CMakeLists.txt @@ -7,7 +7,7 @@ endif () include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/v-hacd-master.zip + URL https://public.highfidelity.com/dependencies/v-hacd-master.zip URL_MD5 3bfc94f8dd3dfbfe8f4dc088f4820b3e CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt index 4c0ffaf88f..8b3408e3fa 100644 --- a/cmake/externals/wasapi/CMakeLists.txt +++ b/cmake/externals/wasapi/CMakeLists.txt @@ -6,7 +6,7 @@ if (WIN32) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi10.zip + URL https://public.highfidelity.com/dependencies/qtaudio_wasapi10.zip URL_MD5 4f40e49715a420fb67b45b9cee19052c CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/cmake/externals/zlib/CMakeLists.txt b/cmake/externals/zlib/CMakeLists.txt index 3bbda322a1..987ca1fd18 100644 --- a/cmake/externals/zlib/CMakeLists.txt +++ b/cmake/externals/zlib/CMakeLists.txt @@ -5,7 +5,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/zlib128.zip + URL https://public.highfidelity.com/dependencies/zlib128.zip CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build LOG_DOWNLOAD 1 From 284329209bff3d3f209ce0f32cd1629b6c86f8c0 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 12 Jul 2018 18:14:06 -0700 Subject: [PATCH 15/56] Added missing MD5 --- cmake/externals/sdl2/CMakeLists.txt | 1 + cmake/externals/zlib/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index 635a1cb5bb..1e8e690743 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -19,6 +19,7 @@ elseif (APPLE) ExternalProject_Add( ${EXTERNAL_NAME} URL https://public.highfidelity.com/dependencies/SDL2-2.0.3.zip + URL_MD5 55f1eae5142d20db11c844d8d4d6deed CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DVIDEO_OPENGL=OFF BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build LOG_DOWNLOAD 1 diff --git a/cmake/externals/zlib/CMakeLists.txt b/cmake/externals/zlib/CMakeLists.txt index 987ca1fd18..85506ba0e1 100644 --- a/cmake/externals/zlib/CMakeLists.txt +++ b/cmake/externals/zlib/CMakeLists.txt @@ -6,6 +6,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} URL https://public.highfidelity.com/dependencies/zlib128.zip + URL_MD5 126f8676442ffbd97884eb4d6f32afb4 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build LOG_DOWNLOAD 1 From acae4df3c344f6ede99c13da8012c3b86756da89 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jul 2018 19:23:06 -0700 Subject: [PATCH 16/56] fix align to selection to grid --- scripts/system/edit.js | 8 +------- scripts/system/libraries/gridTool.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 73088560d9..092b7334f1 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1853,13 +1853,7 @@ var keyReleaseEvent = function (event) { } } else if (event.text === 'g') { if (isActive && selectionManager.hasSelection()) { - var newPosition = selectionManager.worldPosition; - newPosition = Vec3.subtract(newPosition, { - x: 0, - y: selectionManager.worldDimensions.y * 0.5, - z: 0 - }); - grid.setPosition(newPosition); + grid.moveToSelection(); } } else if (event.key === KEY_P && event.isControl && !event.isAutoRepeat ) { if (event.isShifted) { diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 690b4eb4b9..1268117d93 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -154,6 +154,12 @@ Grid = function(opts) { that.emitUpdate(); } }; + + that.moveToSelection = function() { + var newPosition = SelectionManager.worldPosition; + newPosition = Vec3.subtract(newPosition, { x: 0, y: SelectionManager.worldDimensions.y * 0.5, z: 0 }); + that.setPosition(newPosition); + }; that.emitUpdate = function() { if (that.onUpdate) { @@ -263,6 +269,8 @@ GridTool = function(opts) { print("gridTool.js: Error parsing JSON: " + e.name + " data " + data); return; } + + print("DBACKTEST webEventReceived " + data.type); if (data.type == "init") { horizontalGrid.emitUpdate(); @@ -272,6 +280,7 @@ GridTool = function(opts) { listeners[i] && listeners[i](data); } } else if (data.type == "action") { + print("DBACKTEST webEventReceived action " + data.action); var action = data.action; if (action == "moveToAvatar") { var position = MyAvatar.getJointPosition("LeftFoot"); @@ -280,9 +289,7 @@ GridTool = function(opts) { } horizontalGrid.setPosition(position); } else if (action == "moveToSelection") { - var newPosition = selectionManager.worldPosition; - newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 }); - grid.setPosition(newPosition); + horizontalGrid.moveToSelection(); } } }; From 151f948b267faf867be23cdb723527789ae5c9cd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jul 2018 19:26:20 -0700 Subject: [PATCH 17/56] prints --- scripts/system/libraries/gridTool.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 1268117d93..669083a545 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -269,8 +269,6 @@ GridTool = function(opts) { print("gridTool.js: Error parsing JSON: " + e.name + " data " + data); return; } - - print("DBACKTEST webEventReceived " + data.type); if (data.type == "init") { horizontalGrid.emitUpdate(); @@ -280,7 +278,6 @@ GridTool = function(opts) { listeners[i] && listeners[i](data); } } else if (data.type == "action") { - print("DBACKTEST webEventReceived action " + data.action); var action = data.action; if (action == "moveToAvatar") { var position = MyAvatar.getJointPosition("LeftFoot"); From bdd6f3c5c5f86c83798c1a2f4212cbdc690fdfe7 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Fri, 13 Jul 2018 12:39:31 -0300 Subject: [PATCH 18/56] Android - Refresh domains list with swipe --- .../hifiinterface/fragment/HomeFragment.java | 14 +++++++++++++- .../hifiinterface/provider/DomainProvider.java | 2 +- .../provider/UserStoryDomainProvider.java | 5 +++-- .../hifiinterface/view/DomainAdapter.java | 6 +++--- android/app/src/main/res/layout/fragment_home.xml | 13 +++++++++---- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/HomeFragment.java b/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/HomeFragment.java index b98849d051..9ca6c7c4cc 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/HomeFragment.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/HomeFragment.java @@ -4,6 +4,7 @@ import android.app.Fragment; import android.content.Context; import android.os.Bundle; import android.os.Handler; +import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.Editable; @@ -32,6 +33,7 @@ public class HomeFragment extends Fragment { private OnHomeInteractionListener mListener; + private SwipeRefreshLayout mSwipeRefreshLayout; public native String nativeGetLastLocation(); @@ -57,6 +59,7 @@ public class HomeFragment extends Fragment { View rootView = inflater.inflate(R.layout.fragment_home, container, false); searchNoResultsView = rootView.findViewById(R.id.searchNoResultsView); + mSwipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout); mDomainsView = rootView.findViewById(R.id.rvDomains); int numberOfColumns = 1; @@ -76,12 +79,14 @@ public class HomeFragment extends Fragment { searchNoResultsView.setText(R.string.search_no_results); searchNoResultsView.setVisibility(View.VISIBLE); mDomainsView.setVisibility(View.GONE); + mSwipeRefreshLayout.setRefreshing(false); } @Override public void onNonEmptyAdapter() { searchNoResultsView.setVisibility(View.GONE); mDomainsView.setVisibility(View.VISIBLE); + mSwipeRefreshLayout.setRefreshing(false); } @Override @@ -104,7 +109,7 @@ public class HomeFragment extends Fragment { @Override public void afterTextChanged(Editable editable) { - mDomainAdapter.loadDomains(editable.toString()); + mDomainAdapter.loadDomains(editable.toString(), false); if (editable.length() > 0) { mSearchIconView.setVisibility(View.GONE); mClearSearch.setVisibility(View.VISIBLE); @@ -130,6 +135,13 @@ public class HomeFragment extends Fragment { mClearSearch.setOnClickListener(view -> onSearchClear(view)); + mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mDomainAdapter.loadDomains(mSearchView.getText().toString(), true); + } + }); + getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); return rootView; diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/provider/DomainProvider.java b/android/app/src/main/java/io/highfidelity/hifiinterface/provider/DomainProvider.java index 7a2101a229..602fadc37e 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/provider/DomainProvider.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/provider/DomainProvider.java @@ -10,7 +10,7 @@ import io.highfidelity.hifiinterface.view.DomainAdapter; public interface DomainProvider { - void retrieve(String filterText, DomainCallback domainCallback); + void retrieve(String filterText, DomainCallback domainCallback, boolean forceRefresh); interface DomainCallback { void retrieveOk(List domain); diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/provider/UserStoryDomainProvider.java b/android/app/src/main/java/io/highfidelity/hifiinterface/provider/UserStoryDomainProvider.java index ca5e0c17bd..e3b631bd69 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/provider/UserStoryDomainProvider.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/provider/UserStoryDomainProvider.java @@ -49,8 +49,8 @@ public class UserStoryDomainProvider implements DomainProvider { } @Override - public synchronized void retrieve(String filterText, DomainCallback domainCallback) { - if (!startedToGetFromAPI) { + public synchronized void retrieve(String filterText, DomainCallback domainCallback, boolean forceRefresh) { + if (!startedToGetFromAPI || forceRefresh) { startedToGetFromAPI = true; fillDestinations(filterText, domainCallback); } else { @@ -72,6 +72,7 @@ public class UserStoryDomainProvider implements DomainProvider { allStories.clear(); getUserStoryPage(1, allStories, null, ex -> { + suggestions.clear(); allStories.forEach(userStory -> { if (taggedStoriesIds.contains(userStory.id)) { userStory.tagFound = true; diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/view/DomainAdapter.java b/android/app/src/main/java/io/highfidelity/hifiinterface/view/DomainAdapter.java index 4f8b33b481..71d634e9ea 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/view/DomainAdapter.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/view/DomainAdapter.java @@ -42,14 +42,14 @@ public class DomainAdapter extends RecyclerView.Adapter domain) { @@ -76,7 +76,7 @@ public class DomainAdapter extends RecyclerView.Adapter domain) { diff --git a/android/app/src/main/res/layout/fragment_home.xml b/android/app/src/main/res/layout/fragment_home.xml index cb39b8f69e..0f8f437c04 100644 --- a/android/app/src/main/res/layout/fragment_home.xml +++ b/android/app/src/main/res/layout/fragment_home.xml @@ -63,13 +63,18 @@ android:visibility="gone" /> - - + android:layout_height="0dp"> + + From 5a80eb646ac2d18f6a5edd3867d2f18f0a72c441 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 13 Jul 2018 10:36:01 -0700 Subject: [PATCH 19/56] Fix bad URL --- cmake/externals/openvr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index a04dbcf3e6..05dfe70ed7 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -7,7 +7,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://public.highfidelity.com/dependencies/v1.0.6.zip + URL https://public.highfidelity.com/dependencies/openvr-1.0.6.zip URL_MD5 f6892cd3a3078f505d03b4297f5a1951 CONFIGURE_COMMAND "" BUILD_COMMAND "" From f038ba96b5a1a20bc50a06114ecf5b148ae42e01 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 13 Jul 2018 10:52:32 -0700 Subject: [PATCH 20/56] Move a couple dependency archives to dependencies --- cmake/externals/glad32es/CMakeLists.txt | 2 +- cmake/externals/glad41/CMakeLists.txt | 2 +- cmake/externals/glad45/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/externals/glad32es/CMakeLists.txt b/cmake/externals/glad32es/CMakeLists.txt index 8ca4d44021..04000b4cfe 100644 --- a/cmake/externals/glad32es/CMakeLists.txt +++ b/cmake/externals/glad32es/CMakeLists.txt @@ -5,7 +5,7 @@ include(SelectLibraryConfigurations) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/austin/glad/glad32es.zip + URL https://public.highfidelity.com/dependencies/glad/glad32es.zip URL_MD5 6a641d8c49dee4c895fa59315f5682a6 CONFIGURE_COMMAND CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_POSITION_INDEPENDENT_CODE=ON LOG_DOWNLOAD 1 diff --git a/cmake/externals/glad41/CMakeLists.txt b/cmake/externals/glad41/CMakeLists.txt index 2371044362..0c99a03025 100644 --- a/cmake/externals/glad41/CMakeLists.txt +++ b/cmake/externals/glad41/CMakeLists.txt @@ -5,7 +5,7 @@ include(SelectLibraryConfigurations) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/austin/glad/glad41.zip + URL https://public.highfidelity.com/dependencies/glad/glad41.zip URL_MD5 1324eeec33abe91e67d19ae551ba624d CONFIGURE_COMMAND CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_POSITION_INDEPENDENT_CODE=ON LOG_DOWNLOAD 1 diff --git a/cmake/externals/glad45/CMakeLists.txt b/cmake/externals/glad45/CMakeLists.txt index 8ad455fa7e..112f6f3592 100644 --- a/cmake/externals/glad45/CMakeLists.txt +++ b/cmake/externals/glad45/CMakeLists.txt @@ -5,7 +5,7 @@ include(SelectLibraryConfigurations) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/austin/glad/glad45.zip + URL https://public.highfidelity.com/dependencies/glad/glad45.zip URL_MD5 cfb19b3cb5b2f8f1d1669fb3150e5f05 CONFIGURE_COMMAND CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_POSITION_INDEPENDENT_CODE=ON LOG_DOWNLOAD 1 From 4daa0c65378c25ff8bb3bfbcd55cb5fdae8e4126 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 13 Jul 2018 12:47:45 -0700 Subject: [PATCH 21/56] CR feedback --- interface/resources/qml/hifi/Pal.qml | 6 +++--- interface/src/avatar/AvatarManager.cpp | 14 +++++++++++--- interface/src/avatar/AvatarManager.h | 11 ++++++++++- scripts/system/pal.js | 10 +++++----- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 06ad57139d..c66ed1fe18 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -1120,7 +1120,7 @@ Rectangle { var data = message.params; var index = -1; iAmAdmin = Users.canKick; - index = findNearbySessionIndex(MyAvatar.sessionUUID, data); + index = findNearbySessionIndex("", data); if (index !== -1) { myData = data[index]; data.splice(index, 1); @@ -1197,8 +1197,8 @@ Rectangle { for (var userId in message.params) { var audioLevel = message.params[userId][0]; var avgAudioLevel = message.params[userId][1]; - // If the userId is 0, we're updating "myData". - if (userId == 0) { + // If the userId is "", we're updating "myData". + if (userId === "") { myData.audioLevel = audioLevel; myCard.audioLevel = audioLevel; // Defensive programming myData.avgAudioLevel = avgAudioLevel; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index a7ee5f4869..bb9a78d546 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -670,7 +670,7 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV } } -QString AvatarManager::getPalData(const QList specificAvatarIdentifiers) { + QVariantMap AvatarManager::getPalData(const QList specificAvatarIdentifiers) { QJsonArray palData; auto avatarMap = getHashCopy(); @@ -680,6 +680,13 @@ QString AvatarManager::getPalData(const QList specificAvatarIdentifiers QString currentSessionUUID = avatar->getSessionUUID().toString(); if (specificAvatarIdentifiers.isEmpty() || specificAvatarIdentifiers.contains(currentSessionUUID)) { QJsonObject thisAvatarPalData; + + auto myAvatar = DependencyManager::get()->getMyAvatar(); + + if (currentSessionUUID == myAvatar->getSessionUUID().toString()) { + currentSessionUUID = ""; + } + thisAvatarPalData.insert("sessionUUID", currentSessionUUID); thisAvatarPalData.insert("sessionDisplayName", avatar->getSessionDisplayName()); thisAvatarPalData.insert("audioLoudness", avatar->getAudioLoudness()); @@ -704,6 +711,7 @@ QString AvatarManager::getPalData(const QList specificAvatarIdentifiers } ++itr; } - QJsonDocument doc(palData); - return doc.toJson(QJsonDocument::Compact); + QJsonObject doc; + doc.insert("data", palData); + return doc.toVariantMap(); } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 507767866b..c6f71b498d 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -157,7 +157,16 @@ public: */ Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value); - Q_INVOKABLE QString getPalData(const QList specificAvatarIdentifiers = QList()); + /**jsdoc + * Used in the PAL for getting PAL-related data about avatars nearby. Using this method is faster + * than iterating over each avatar and obtaining data about them in JavaScript, as that method + * locks and unlocks each avatar's data structure potentially hundreds of times per update tick. + * @function AvatarManager.getPalData + * @param {string list} specificAvatarIdentifiers - A list of specific Avatar Identifiers about which + * you want to get PAL data + * @returns {string} + */ + Q_INVOKABLE QVariantMap getPalData(const QList specificAvatarIdentifiers = QList()); float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } int getIdentityRequestsSent() const { return _identityRequestsSent; } diff --git a/scripts/system/pal.js b/scripts/system/pal.js index b811f5e95a..d8dae80b85 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -448,7 +448,7 @@ function populateNearbyUserList(selectData, oldAudioData) { horizontalAngleNormal = filter && Quat.getUp(orientation); avatarsOfInterest = {}; - var avatarData = JSON.parse(AvatarList.getPalData()); + var avatarData = AvatarList.getPalData().data; avatarData.forEach(function (currentAvatarData) { var id = currentAvatarData.sessionUUID; @@ -487,7 +487,7 @@ function populateNearbyUserList(selectData, oldAudioData) { }; // Everyone needs to see admin status. Username and fingerprint returns default constructor output if the requesting user isn't an admin. Users.requestUsernameFromID(id); - if (id !== MyAvatar.sessionUUID) { + if (id !== "") { addAvatarNode(id); // No overlay for ourselves avatarsOfInterest[id] = true; } else { @@ -548,7 +548,7 @@ function updateAudioLevel(overlay, avatarData) { var param = {}; var level = [audioLevel, avgAudioLevel]; - var userId = avatarData.sessionUUID === MyAvatar.sessionUUID ? 0 : avatarData.sessionUUID; + var userId = avatarData.sessionUUID; param[userId] = level; sendToQml({ method: 'updateAudioLevel', params: param }); } @@ -557,12 +557,12 @@ var pingPong = true; function updateOverlays() { var eye = Camera.position; - var avatarData = JSON.parse(AvatarList.getPalData()); + var avatarData = AvatarList.getPalData().data; avatarData.forEach(function (currentAvatarData) { updateAudioLevel(overlay, currentAvatarData); - if (currentAvatarData.sessionUUID === MyAvatar.sessionUUID || !avatarsOfInterest[currentAvatarData.sessionUUID]) { + if (currentAvatarData.sessionUUID === "" || !avatarsOfInterest[currentAvatarData.sessionUUID]) { return; // don't update ourself, or avatars we're not interested in } var overlay = ExtendedOverlay.get(currentAvatarData.sessionUUID); From c3ffe7eb97f26f2c4073932cd83faa645d0b81dc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 13 Jul 2018 13:55:32 -0700 Subject: [PATCH 22/56] Fix bubble shading; fix audio loudness calculation --- scripts/system/pal.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index d8dae80b85..fcff83a3d3 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -518,32 +518,32 @@ function usernameFromIDReply(id, username, machineFingerprint, isAdmin) { updateUser(data); } -function updateAudioLevel(overlay, avatarData) { +function updateAudioLevel(avatarData) { // the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged // But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency // of updating (the latter for efficiency too). var audioLevel = 0.0; var avgAudioLevel = 0.0; - if (overlay) { + var data = avatarData.sessionUUID === "" ? myData : ExtendedOverlay.get(avatarData.sessionUUID); + + if (data) { // we will do exponential moving average by taking some the last loudness and averaging - overlay.accumulatedLevel = AVERAGING_RATIO * (overlay.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatarData.audioLoudness); + data.accumulatedLevel = AVERAGING_RATIO * (data.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatarData.audioLoudness); // add 1 to insure we don't go log() and hit -infinity. Math.log is // natural log, so to get log base 2, just divide by ln(2). - audioLevel = scaleAudio(Math.log(overlay.accumulatedLevel + 1) / LOG2); + audioLevel = scaleAudio(Math.log(data.accumulatedLevel + 1) / LOG2); // decay avgAudioLevel - avgAudioLevel = Math.max((1 - AUDIO_PEAK_DECAY) * (overlay.avgAudioLevel || 0), audioLevel); + avgAudioLevel = Math.max((1 - AUDIO_PEAK_DECAY) * (data.avgAudioLevel || 0), audioLevel); - overlay.avgAudioLevel = avgAudioLevel; - overlay.audioLevel = audioLevel; + data.avgAudioLevel = avgAudioLevel; + data.audioLevel = audioLevel; // now scale for the gain. Also, asked to boost the low end, so one simple way is // to take sqrt of the value. Lets try that, see how it feels. avgAudioLevel = Math.min(1.0, Math.sqrt(avgAudioLevel * (sessionGains[avatarData.sessionUUID] || 0.75))); - } else { - audioLevel = scaleAudio(Math.log(((1 - AVERAGING_RATIO) * (avatarData.audioLoudness)) + 1) / LOG2); } var param = {}; @@ -560,11 +560,11 @@ function updateOverlays() { var avatarData = AvatarList.getPalData().data; avatarData.forEach(function (currentAvatarData) { - updateAudioLevel(overlay, currentAvatarData); if (currentAvatarData.sessionUUID === "" || !avatarsOfInterest[currentAvatarData.sessionUUID]) { return; // don't update ourself, or avatars we're not interested in } + updateAudioLevel(currentAvatarData); var overlay = ExtendedOverlay.get(currentAvatarData.sessionUUID); if (!overlay) { // For now, we're treating this as a temporary loss, as from the personal space bubble. Add it back. print('Adding non-PAL avatar node', currentAvatarData.sessionUUID); From 46a9521939c41e2cff636268dc75af895bf2f23f Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 13 Jul 2018 17:40:24 -0700 Subject: [PATCH 23/56] fix selecting an edit handle causing selected entity change --- scripts/system/edit.js | 22 +++++++++++-------- .../system/libraries/entitySelectionTool.js | 7 ++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 73088560d9..20a84bfa62 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1075,15 +1075,19 @@ function mouseReleaseEvent(event) { } } -function wasTabletClicked(event) { +function wasTabletOrEditHandleClicked(event) { var rayPick = Camera.computePickRay(event.x, event.y); - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.length === 0) { - return false; - } else { - var result = Overlays.findRayIntersection(rayPick, true, getMainTabletIDs()); - return result.intersects; + var result = Overlays.findRayIntersection(rayPick, true); + if (result.intersects) { + var overlayID = result.overlayID; + var tabletIDs = getMainTabletIDs(); + if (tabletIDs.indexOf(overlayID) >= 0) { + return true; + } else if (selectionDisplay.isEditHandle(overlayID)) { + return true; + } } + return false; } function mouseClickEvent(event) { @@ -1091,8 +1095,8 @@ function mouseClickEvent(event) { var result, properties, tabletClicked; if (isActive && event.isLeftButton) { result = findClickedEntity(event); - tabletClicked = wasTabletClicked(event); - if (tabletClicked) { + tabletOrEditHandleClicked = wasTabletOrEditHandleClicked(event); + if (tabletOrEditHandleClicked) { return; } diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 4ff139ee75..215d19be18 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -658,6 +658,7 @@ SelectionDisplay = (function() { selectionBox, iconSelectionBox ]; + var maximumHandleInAllOverlays = handleCloner; overlayNames[handleTranslateXCone] = "handleTranslateXCone"; overlayNames[handleTranslateXCylinder] = "handleTranslateXCylinder"; @@ -781,6 +782,12 @@ SelectionDisplay = (function() { return Math.abs(position.x) <= box.dimensions.x / 2 && Math.abs(position.y) <= box.dimensions.y / 2 && Math.abs(position.z) <= box.dimensions.z / 2; } + + that.isEditHandle = function(overlayID) { + var overlayIndex = allOverlays.indexOf(overlayID); + var maxHandleIndex = allOverlays.indexOf(maximumHandleInAllOverlays); + return overlayIndex >= 0 && overlayIndex <= maxHandleIndex; + }; // FUNCTION: MOUSE PRESS EVENT that.mousePressEvent = function (event) { From e4f13c97f79463b57bb97637fadef5f8abc80934 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 14 Jul 2018 14:01:08 +1200 Subject: [PATCH 24/56] Fix JSDoc for MyAvatar.getLeftPalmRotation and getRightPalmRotation --- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index fe9a347c20..157f7b2ec6 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -381,7 +381,7 @@ public slots: /**jsdoc * Get the rotation of the left palm in world coordinates. * @function MyAvatar.getLeftPalmRotation - * @returns {Vec3} The rotation of the left palm in world coordinates. + * @returns {Quat} The rotation of the left palm in world coordinates. * @example Report the rotation of your avatar's left palm. * print(JSON.stringify(MyAvatar.getLeftPalmRotation())); */ @@ -398,7 +398,7 @@ public slots: /**jsdoc * Get the rotation of the right palm in world coordinates. * @function MyAvatar.getRightPalmRotation - * @returns {Vec3} The rotation of the right palm in world coordinates. + * @returns {Quat} The rotation of the right palm in world coordinates. * @example Report the rotation of your avatar's right palm. * print(JSON.stringify(MyAvatar.getRightPalmRotation())); */ From c574305ddc863c706f94ab7dda43e90ed7d5531c Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 16 Jul 2018 10:19:38 -0700 Subject: [PATCH 25/56] gltf importer accept local files and binary read fix --- libraries/fbx/src/GLTFReader.cpp | 219 +++++++++++++------------------ libraries/fbx/src/GLTFReader.h | 4 +- 2 files changed, 95 insertions(+), 128 deletions(-) diff --git a/libraries/fbx/src/GLTFReader.cpp b/libraries/fbx/src/GLTFReader.cpp index 1fa4b3873e..300e6f4846 100644 --- a/libraries/fbx/src/GLTFReader.cpp +++ b/libraries/fbx/src/GLTFReader.cpp @@ -21,14 +21,17 @@ #include #include + #include #include #include +#include #include #include #include +#include #include "FBXReader.h" @@ -786,13 +789,18 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) { QVector raw_vertices; QVector raw_normals; - addArrayOfType(indicesBuffer.blob, + bool success = addArrayOfType(indicesBuffer.blob, indicesBufferview.byteOffset + indicesAccBoffset, - indicesBufferview.byteLength, + indicesAccessor.count, part.triangleIndices, indicesAccessor.type, indicesAccessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF INDICES data for model " << _url; + continue; + } + QList keys = primitive.attributes.values.keys(); foreach(auto &key, keys) { @@ -805,44 +813,60 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) { int accBoffset = accessor.defined["byteOffset"] ? accessor.byteOffset : 0; if (key == "POSITION") { QVector vertices; - addArrayOfType(buffer.blob, + success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, - bufferview.byteLength, vertices, + accessor.count, vertices, accessor.type, accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF POSITION data for model " << _url; + continue; + } for (int n = 0; n < vertices.size(); n = n + 3) { mesh.vertices.push_back(glm::vec3(vertices[n], vertices[n + 1], vertices[n + 2])); } } else if (key == "NORMAL") { QVector normals; - addArrayOfType(buffer.blob, + success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, - bufferview.byteLength, + accessor.count, normals, accessor.type, accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF NORMAL data for model " << _url; + continue; + } for (int n = 0; n < normals.size(); n = n + 3) { mesh.normals.push_back(glm::vec3(normals[n], normals[n + 1], normals[n + 2])); } } else if (key == "TEXCOORD_0") { QVector texcoords; - addArrayOfType(buffer.blob, + success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, - bufferview.byteLength, + accessor.count, texcoords, accessor.type, accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF TEXCOORD_0 data for model " << _url; + continue; + } for (int n = 0; n < texcoords.size(); n = n + 2) { mesh.texCoords.push_back(glm::vec2(texcoords[n], texcoords[n + 1])); } } else if (key == "TEXCOORD_1") { QVector texcoords; - addArrayOfType(buffer.blob, + success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, - bufferview.byteLength, + accessor.count, texcoords, accessor.type, accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF TEXCOORD_1 data for model " << _url; + continue; + } for (int n = 0; n < texcoords.size(); n = n + 2) { mesh.texCoords1.push_back(glm::vec2(texcoords[n], texcoords[n + 1])); } @@ -888,8 +912,16 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) { FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping, const QUrl& url, bool loadLightmaps, float lightmapLevel) { + _url = url; + // Normalize url for local files + QUrl normalizeUrl = DependencyManager::get()->normalizeURL(url); + if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) { + QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile(); + _url = QUrl(QFileInfo(localFileName).absoluteFilePath()); + } + parseGLTF(model); //_file.dump(); FBXGeometry* geometryPtr = new FBXGeometry(); @@ -904,6 +936,7 @@ FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) { QUrl binaryUrl = _url.resolved(QUrl(url).fileName()); + qCDebug(modelformat) << "binaryUrl: " << binaryUrl << " OriginalUrl: " << _url; bool success; std::tie(success, outdata) = requestData(binaryUrl); @@ -1018,13 +1051,12 @@ void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& materia fbxmat.opacityTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); fbxmat.albedoTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); fbxmat.useAlbedoMap = true; - fbxmat.metallicTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); - fbxmat.useMetallicMap = true; } if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) { fbxmat.roughnessTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); fbxmat.useRoughnessMap = true; - + fbxmat.metallicTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); + fbxmat.useMetallicMap = true; } if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { fbxmat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor); @@ -1043,7 +1075,7 @@ void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& materia } template -bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int byteLength, +bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int count, QVector& outarray, int accessorType) { QDataStream blobstream(bin); @@ -1051,142 +1083,77 @@ bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int byteLength blobstream.setVersion(QDataStream::Qt_5_9); blobstream.setFloatingPointPrecision(QDataStream::FloatingPointPrecision::SinglePrecision); - int vsize = byteLength / sizeof(T); - - qCDebug(modelformat) << "size1: " << vsize; + qCDebug(modelformat) << "size1: " << count; int dataskipped = blobstream.skipRawData(byteOffset); qCDebug(modelformat) << "dataskipped: " << dataskipped; - - while (outarray.size() < vsize) { - - T value1, value2, value3, value4, - value5, value6, value7, value8, - value9, value10, value11, value12, - value13, value14, value15, value16; - - if (accessorType == GLTFAccessorType::SCALAR) { - - blobstream >> value1; - - outarray.push_back(value1); - } else if (accessorType == GLTFAccessorType::VEC2) { - - blobstream >> value1; - blobstream >> value2; - - outarray.push_back(value1); - outarray.push_back(value2); - } else if (accessorType == GLTFAccessorType::VEC3) { - - blobstream >> value1; - blobstream >> value2; - blobstream >> value3; - - outarray.push_back(value1); - outarray.push_back(value2); - outarray.push_back(value3); - } else if (accessorType == GLTFAccessorType::VEC4 || accessorType == GLTFAccessorType::MAT2) { - - blobstream >> value1; - blobstream >> value2; - blobstream >> value3; - blobstream >> value4; - - outarray.push_back(value1); - outarray.push_back(value2); - outarray.push_back(value3); - outarray.push_back(value4); - } else if (accessorType == GLTFAccessorType::MAT3) { - - blobstream >> value1; - blobstream >> value2; - blobstream >> value3; - blobstream >> value4; - blobstream >> value5; - blobstream >> value6; - blobstream >> value7; - blobstream >> value8; - blobstream >> value9; - - outarray.push_back(value1); - outarray.push_back(value2); - outarray.push_back(value3); - outarray.push_back(value4); - outarray.push_back(value5); - outarray.push_back(value6); - outarray.push_back(value7); - outarray.push_back(value8); - outarray.push_back(value9); - } else if (accessorType == GLTFAccessorType::MAT4) { - - blobstream >> value1; - blobstream >> value2; - blobstream >> value3; - blobstream >> value4; - blobstream >> value5; - blobstream >> value6; - blobstream >> value7; - blobstream >> value8; - blobstream >> value9; - blobstream >> value10; - blobstream >> value11; - blobstream >> value12; - blobstream >> value13; - blobstream >> value14; - blobstream >> value15; - blobstream >> value16; - - outarray.push_back(value1); - outarray.push_back(value2); - outarray.push_back(value3); - outarray.push_back(value4); - outarray.push_back(value5); - outarray.push_back(value6); - outarray.push_back(value7); - outarray.push_back(value8); - outarray.push_back(value9); - outarray.push_back(value10); - outarray.push_back(value11); - outarray.push_back(value12); - outarray.push_back(value13); - outarray.push_back(value14); - outarray.push_back(value15); - outarray.push_back(value16); - + int bufferCount = 0; + switch (accessorType) { + case GLTFAccessorType::SCALAR: + bufferCount = 1; + break; + case GLTFAccessorType::VEC2: + bufferCount = 2; + break; + case GLTFAccessorType::VEC3: + bufferCount = 3; + break; + case GLTFAccessorType::VEC4: + bufferCount = 4; + break; + case GLTFAccessorType::MAT2: + bufferCount = 4; + break; + case GLTFAccessorType::MAT3: + bufferCount = 9; + break; + case GLTFAccessorType::MAT4: + bufferCount = 16; + break; + default: + qWarning(modelformat) << "Unknown accessorType: " << accessorType; + blobstream.unsetDevice(); + return false; + } + for (int i = 0; i < count; i++) { + for (int j = 0; j < bufferCount; j++) { + if (!blobstream.atEnd()) { + T value; + blobstream >> value; + outarray.push_back(value); + } else { + blobstream.unsetDevice(); + return false; + } } } + blobstream.unsetDevice(); return true; } template -bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int byteLength, +bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int count, QVector& outarray, int accessorType, int componentType) { switch (componentType) { case GLTFAccessorComponentType::BYTE: {} case GLTFAccessorComponentType::UNSIGNED_BYTE: { - readArray(bin, byteOffset, byteLength, outarray, accessorType); - break; + return readArray(bin, byteOffset, count, outarray, accessorType); } case GLTFAccessorComponentType::SHORT: { - readArray(bin, byteOffset, byteLength, outarray, accessorType); - break; + return readArray(bin, byteOffset, count, outarray, accessorType); } case GLTFAccessorComponentType::UNSIGNED_INT: { - readArray(bin, byteOffset, byteLength, outarray, accessorType); - break; + return readArray(bin, byteOffset, count, outarray, accessorType); } case GLTFAccessorComponentType::UNSIGNED_SHORT: { - readArray(bin, byteOffset, byteLength, outarray, accessorType); - break; + return readArray(bin, byteOffset, count, outarray, accessorType); } case GLTFAccessorComponentType::FLOAT: { - readArray(bin, byteOffset, byteLength, outarray, accessorType); - break; + return readArray(bin, byteOffset, count, outarray, accessorType); } } - return true; + return false; } void GLTFReader::retriangulate(const QVector& inIndices, const QVector& in_vertices, diff --git a/libraries/fbx/src/GLTFReader.h b/libraries/fbx/src/GLTFReader.h index 28c1d8282f..2183256b87 100644 --- a/libraries/fbx/src/GLTFReader.h +++ b/libraries/fbx/src/GLTFReader.h @@ -762,11 +762,11 @@ private: bool readBinary(const QString& url, QByteArray& outdata); template - bool readArray(const QByteArray& bin, int byteOffset, int byteLength, + bool readArray(const QByteArray& bin, int byteOffset, int count, QVector& outarray, int accessorType); template - bool addArrayOfType(const QByteArray& bin, int byteOffset, int byteLength, + bool addArrayOfType(const QByteArray& bin, int byteOffset, int count, QVector& outarray, int accessorType, int componentType); void retriangulate(const QVector& in_indices, const QVector& in_vertices, From d81420542ccca3dbe87a8902c1e749caa6feb973 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 16 Jul 2018 11:00:27 -0700 Subject: [PATCH 26/56] making PR requests --- .../controllerModules/nearParentGrabEntity.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 580132a648..a9f3fbd668 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -172,8 +172,12 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (now - this.lastUnequipCheckTime > MSECS_PER_SEC * TEAR_AWAY_CHECK_TIME) { this.lastUnequipCheckTime = now; if (props.parentID === MyAvatar.SELF_ID) { - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - if ((props.localPosition > TEAR_AWAY_DISTANCE * sensorScaleFactor)) { + var tearAwayDistance = TEAR_AWAY_DISTANCE; + var localX = props.localPosition.x; + var localZ = props.localPosition.z; + var localY = props.localPosition.y; + if ((localX > tearAwayDistance) || (localY > tearAwayDistance) || + (localZ > tearAwayDistance)) { this.autoUnequipCounter++; } else { this.autoUnequipCounter = 0; @@ -237,10 +241,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var handPosition = controllerData.controllerLocations[this.hand].position; - var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); var distance = Vec3.distance(handPosition, props.position); - if ((dist > TEAR_AWAY_DISTANCE) || - (distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + if ((distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { From ac2351e49f9466a7cc2760233ec8db7ce0f95f73 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 16 Jul 2018 09:33:36 -0700 Subject: [PATCH 27/56] Make JSDoc happy --- interface/src/avatar/AvatarManager.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index c6f71b498d..53461146e5 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -162,9 +162,9 @@ public: * than iterating over each avatar and obtaining data about them in JavaScript, as that method * locks and unlocks each avatar's data structure potentially hundreds of times per update tick. * @function AvatarManager.getPalData - * @param {string list} specificAvatarIdentifiers - A list of specific Avatar Identifiers about which - * you want to get PAL data - * @returns {string} + * @param {string[]} specificAvatarIdentifiers - A list of specific Avatar Identifiers about + * which you want to get PAL data + * @returns {object} */ Q_INVOKABLE QVariantMap getPalData(const QList specificAvatarIdentifiers = QList()); From abb2c7ef14608ebed80d053c23571a1e27370d3e Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 16 Jul 2018 11:29:49 -0700 Subject: [PATCH 28/56] Added reset of the _headControllerFacingMovingAverage in MyAvatar.cpp prePhysicsUpdate(). This stops some of the flipping back and forth that has been happening with rotational recenter. --- interface/src/avatar/MyAvatar.cpp | 2 ++ interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 3 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index dbb1d8a56c..d084ca69f9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3551,6 +3551,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat qApp->getCamera().getMode() != CAMERA_MODE_MIRROR) { if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { activate(Rotation); + myAvatar.setHeadControllerFacingMovingAverage(myAvatar._headControllerFacing); } if (myAvatar.getCenterOfGravityModelEnabled()) { if (!isActive(Horizontal) && (shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) { @@ -3568,6 +3569,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat } else { if (!isActive(Rotation) && getForceActivateRotation()) { activate(Rotation); + myAvatar.setHeadControllerFacingMovingAverage(myAvatar._headControllerFacing); setForceActivateRotation(false); } if (!isActive(Horizontal) && getForceActivateHorizontal()) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e795d9356d..819d5b0066 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -883,6 +883,7 @@ public: virtual void rebuildCollisionShape() override; const glm::vec2& getHeadControllerFacingMovingAverage() const { return _headControllerFacingMovingAverage; } + void setHeadControllerFacingMovingAverage(glm::vec2 currentHeadControllerFacing) { _headControllerFacingMovingAverage = currentHeadControllerFacing; } float getCurrentStandingHeight() const { return _currentStandingHeight; } void setCurrentStandingHeight(float newMode) { _currentStandingHeight = newMode; } const glm::quat getAverageHeadRotation() const { return _averageHeadRotation; } From 0fa2a71d0f48760e203e5ef8fc3412aaba1076a1 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 16 Jul 2018 11:35:53 -0700 Subject: [PATCH 29/56] actually fix requested changes --- .../controllerModules/nearParentGrabEntity.js | 12 +++++------ .../libraries/controllerDispatcherUtils.js | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index a9f3fbd668..75f8d28c85 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -11,7 +11,8 @@ TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME, - TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity + TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity, + distanceBetweenEntityLocalPositionAndBoundingBox */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -172,12 +173,9 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (now - this.lastUnequipCheckTime > MSECS_PER_SEC * TEAR_AWAY_CHECK_TIME) { this.lastUnequipCheckTime = now; if (props.parentID === MyAvatar.SELF_ID) { - var tearAwayDistance = TEAR_AWAY_DISTANCE; - var localX = props.localPosition.x; - var localZ = props.localPosition.z; - var localY = props.localPosition.y; - if ((localX > tearAwayDistance) || (localY > tearAwayDistance) || - (localZ > tearAwayDistance)) { + var tearAwayDistance = TEAR_AWAY_DISTANCE * MyAvatar.sensorToWorldScale; + var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props); + if (distance > tearAwayDistance) { this.autoUnequipCounter++; } else { this.autoUnequipCounter = 0; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 9a886372b8..e817bb4ee1 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -59,6 +59,7 @@ highlightTargetEntity:true, clearHighlightedEntities:true, unhighlightTargetEntity:true + distanceBetweenEntityLocalPositionAndBoundingBox: true */ MSECS_PER_SEC = 1000.0; @@ -415,6 +416,25 @@ findHandChildEntities = function(hand) { }); }; +distanceBetweenEntityLocalPositionAndBoundingBox = function(entityProps) { + var localPoint = entityProps.localPosition; + var entityXform = new Xform(entityProps.rotation, entityProps.position); + var minOffset = Vec3.multiplyVbyV(entityProps.registrationPoint, entityProps.dimensions); + var maxOffset = Vec3.multiplyVbyV(Vec3.subtract(ONE_VEC, entityProps.registrationPoint), entityProps.dimensions); + var localMin = Vec3.subtract(entityXform.trans, minOffset); + var localMax = Vec3.sum(entityXform.trans, maxOffset); + + var v = {x: localPoint.x, y: localPoint.y, z: localPoint.z}; + v.x = Math.max(v.x, localMin.x); + v.x = Math.min(v.x, localMax.x); + v.y = Math.max(v.y, localMin.y); + v.y = Math.min(v.y, localMax.y); + v.z = Math.max(v.z, localMin.z); + v.z = Math.min(v.z, localMax.z); + + return Vec3.distance(v, localPoint); +}; + distanceBetweenPointAndEntityBoundingBox = function(point, entityProps) { var entityXform = new Xform(entityProps.rotation, entityProps.position); var localPoint = entityXform.inv().xformPoint(point); From fa2b975e8f262a96b61ac30685c7a9af1e3febf0 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 16 Jul 2018 11:42:38 -0700 Subject: [PATCH 30/56] undo some wrong changes --- .../controllers/controllerModules/nearParentGrabEntity.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 75f8d28c85..59c2520c01 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -239,8 +239,10 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var handPosition = controllerData.controllerLocations[this.hand].position; + var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); var distance = Vec3.distance(handPosition, props.position); - if ((distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + if ((dist > TEAR_AWAY_DISTANCE || + distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { From 20a82753436066d767f87e5e01167d2c22459a52 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 16 Jul 2018 11:43:29 -0700 Subject: [PATCH 31/56] min diff --- .../controllers/controllerModules/nearParentGrabEntity.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 59c2520c01..38334f5523 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -241,8 +241,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var handPosition = controllerData.controllerLocations[this.hand].position; var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); var distance = Vec3.distance(handPosition, props.position); - if ((dist > TEAR_AWAY_DISTANCE || - distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + if ((dist > TEAR_AWAY_DISTANCE) || + (distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { From 46061a2a15bf49c2da631480e5189e28eff2902a Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 16 Jul 2018 11:54:05 -0700 Subject: [PATCH 32/56] initial with pal --- scripts/modules/appUi.js | 161 +++++++++++++++++++++++++++++++++++++++ scripts/system/pal.js | 101 ++++++++++-------------- 2 files changed, 201 insertions(+), 61 deletions(-) create mode 100644 scripts/modules/appUi.js diff --git a/scripts/modules/appUi.js b/scripts/modules/appUi.js new file mode 100644 index 0000000000..636affb94a --- /dev/null +++ b/scripts/modules/appUi.js @@ -0,0 +1,161 @@ +// +// libraries/appUi.js +// +// Created by Howard Stearns on 3/20/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 +// + +function AppUi(properties) { + /* Example development order: + 1. var AppUi = Script.require('appUi'); + 2. Put appname-i.svg, appname-a.svg in graphicsDirectory (where non-default graphicsDirectory can be added in #3). + 3. ui = new AppUi({buttonName: "APPNAME", home: "qml-or-html-path"}); + (and if converting an existing app, + define var tablet = ui.tablet, button = ui.button; as needed. + remove button.clicked.[dis]connect and tablet.remove(button).) + 4. Define onOpened and onClosed behavior in #3, if any. + (and if converting an existing app, remove screenChanged.[dis]connect.) + 5. Define onMessage in #3, if any. + (and if converting an existing app, remove code that [un]wires that message handling.) + x. lint! + */ + + var that = this; + function defaultButton(name, suffix) { + var base = that[name] || (that.buttonPrefix + suffix); + that[name] = (base.indexOf('/') >= 0) ? base : (that.graphicsDirectory + base); //poor man's merge + } + + // Defaults: + that.tabletName = "com.highfidelity.interface.tablet.system"; + that.inject = ""; + that.graphicsDirectory = "icons/tablet-icons/"; // Where to look for button svgs. See below. + that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen. + return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix. + } + that.toOpen = function toOpen() { // How to open the app. + if (that.isQML()) { + that.tablet.loadQMLSource(that.home); + } else { + that.tablet.gotoWebScreen(that.home, that.inject); + } + }; + that.toClose = function toClose() { // How to close the app. + // for toolbar-mode: go back to home screen, this will close the window. + that.tablet.gotoHomeScreen(); + }; + that.buttonActive = function buttonActive(isActive) { // How to make the button active (white). + that.button.editProperties({isActive: isActive}); + }; + that.messagesWaiting = function messagesWaiting(isWaiting) { // How to indicate a message light on button. + // Note that waitingButton doesn't have to exist unless someone explicitly calls this with isWaiting true. + that.button.editProperties({ + icon: isWaiting ? that.normalMessagesButton : that.normalButton, + activeIcon: isWaiting ? that.activeMessagesButton : that.activeButton + }); + }; + that.isQML = function isQML() { // We set type property in onClick. + return that.type === 'QML'; + } + that.eventSignal = function eventSignal() { // What signal to hook onMessage to. + return that.isQML() ? that.tablet.fromQml : that.tablet.webEventReceived; + }; + + // Overwrite with the given properties: + Object.keys(properties).forEach(function (key) { that[key] = properties[key]; }); + + // Properties: + that.tablet = Tablet.getTablet(that.tabletName); + // Must be after we gather properties. + that.buttonPrefix = that.buttonPrefix || that.buttonName.toLowerCase() + "-"; + defaultButton('normalButton', 'i.svg'); + defaultButton('activeButton', 'a.svg'); + defaultButton('normalMessagesButton', 'i-msg.svg'); + defaultButton('activeMessagesButton', 'a-msg.svg'); + that.button = that.tablet.addButton({ + icon: that.normalButton, + activeIcon: that.activeButton, + text: that.buttonName, + sortOrder: that.sortOrder + }); + that.ignore = function ignore() { }; + + // Handlers + that.onScreenChanged = function onScreenChanged(type, url) { + // Set isOpen, wireEventBridge, set buttonActive as appropriate, + // and finally call onOpened() or onClosed() IFF defined. + print('hrs fixme onScreenChanged', type, url, that.isOpen); + if (that.checkIsOpen(type, url)) { + if (!that.isOpen) { + that.isOpen = true; + that.wireEventBridge(true); + that.buttonActive(true); + if (that.onOpened) { + that.onOpened(); + } + } + + } else { // Not us. Should we do something for type Home, Menu, and particularly Closed (meaning tablet hidden? + if (that.isOpen) { + that.isOpen = false; + that.wireEventBridge(false); + that.buttonActive(false); + if (that.onClosed) { + that.onClosed(); + } + } + } + }; + that.hasEventBridge = false; + that.wireEventBridge = function wireEventBridge(on) { + // Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined. + print('hrs fixme wireEventBridge', on, that.hasEventBridge); + if (!that.onMessage) { return; } + if (on) { + if (!that.hasEventBridge) { + print('hrs fixme connecting', that.eventSignal()); + that.eventSignal().connect(that.onMessage); + that.hasEventBridge = true; + } + } else { + if (that.hasEventBridge) { + print('hrs fixme connecting', that.eventSignal()); + that.eventSignal().disconnect(that.onMessage); + that.hasEventBridge = false; + } + } + }; + that.isOpen = false; + // To facilitate incremental development, only wire onClicked to do something when "home" is defined in properties. + that.onClicked = that.home + ? function onClicked() { + // Call toOpen() or toClose(), and reset type based on current home property. + if (that.isOpen) { + that.toClose(); + } else { + that.type = /.qml$/.test(that.home) ? 'QML' : 'Web' + that.toOpen(); + } + } : that.ignore; + that.onScriptEnding = function onScriptEnding() { + // Close if necessary, clean up any remaining handlers, and remove the button. + if (that.isOpen) { + that.toClose(); + } + that.tablet.screenChanged.disconnect(that.onScreenChanged); + if (that.button) { + if (that.onClicked) { + that.button.clicked.disconnect(that.onClicked); + } + that.tablet.removeButton(that.button); + } + }; + // Set up the handlers. + that.tablet.screenChanged.connect(that.onScreenChanged); + that.button.clicked.connect(that.onClicked); + Script.scriptEnding.connect(that.onScriptEnding); +}; +module.exports = AppUi; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index e967ee6469..cc12b7798f 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -15,9 +15,10 @@ (function() { // BEGIN LOCAL_SCOPE var request = Script.require('request').request; + var AppUi = Script.require('appUi'); var populateNearbyUserList, color, textures, removeOverlays, - controllerComputePickRay, onTabletButtonClicked, onTabletScreenChanged, + controllerComputePickRay, off, receiveMessage, avatarDisconnected, clearLocalQMLDataAndClosePAL, createAudioInterval, tablet, CHANNEL, getConnectionData, findableByChanged, avatarAdded, avatarRemoved, avatarSessionChanged; // forward references; @@ -678,20 +679,7 @@ function tabletVisibilityChanged() { var wasOnPalScreen = false; var onPalScreen = false; -var PAL_QML_SOURCE = "hifi/Pal.qml"; -function onTabletButtonClicked() { - if (!tablet) { - print("Warning in onTabletButtonClicked(): 'tablet' undefined!"); - return; - } - if (onPalScreen) { - // In Toolbar Mode, `gotoHomeScreen` will close the app window. - tablet.gotoHomeScreen(); - } else { - tablet.loadQMLSource(PAL_QML_SOURCE); - } -} -var hasEventBridge = false; +/*var hasEventBridge = false; function wireEventBridge(on) { if (on) { if (!hasEventBridge) { @@ -704,38 +692,31 @@ function wireEventBridge(on) { hasEventBridge = false; } } -} - -function onTabletScreenChanged(type, url) { +}*/ +function captureState() { wasOnPalScreen = onPalScreen; - onPalScreen = (type === "QML" && url === PAL_QML_SOURCE); - wireEventBridge(onPalScreen); - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: onPalScreen}); - - if (onPalScreen) { - isWired = true; - - ContextOverlay.enabled = false; - Users.requestsDomainListData = true; - - audioTimer = createAudioInterval(AUDIO_LEVEL_UPDATE_INTERVAL_MS); - - tablet.tabletShownChanged.connect(tabletVisibilityChanged); - Script.update.connect(updateOverlays); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - Users.usernameFromIDReply.connect(usernameFromIDReply); - triggerMapping.enable(); - triggerPressMapping.enable(); - populateNearbyUserList(); - } else { - off(); - if (wasOnPalScreen) { - ContextOverlay.enabled = true; - } - } + onPalScreen = ui.isOpen; + //wireEventBridge(onPalScreen); } +function on() { + captureState(); + isWired = true; + + ContextOverlay.enabled = false; + Users.requestsDomainListData = true; + + audioTimer = createAudioInterval(AUDIO_LEVEL_UPDATE_INTERVAL_MS); + + tablet.tabletShownChanged.connect(tabletVisibilityChanged); + Script.update.connect(updateOverlays); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + Users.usernameFromIDReply.connect(usernameFromIDReply); + triggerMapping.enable(); + triggerPressMapping.enable(); + populateNearbyUserList(); +} +var button, ui, tablet; // // Message from other scripts, such as edit.js @@ -749,7 +730,7 @@ function receiveMessage(channel, messageString, senderID) { switch (message.method) { case 'select': if (!onPalScreen) { - tablet.loadQMLSource(PAL_QML_SOURCE); + tablet.loadQMLSource(ui.home); Script.setTimeout(function () { sendToQml(message); }, 1000); } else { sendToQml(message); // Accepts objects, not just strings. @@ -847,20 +828,17 @@ function avatarSessionChanged(avatarID) { sendToQml({ method: 'palIsStale', params: [avatarID, 'avatarSessionChanged'] }); } - -var button; -var buttonName = "PEOPLE"; -var tablet = null; function startup() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - button = tablet.addButton({ - text: buttonName, - icon: "icons/tablet-icons/people-i.svg", - activeIcon: "icons/tablet-icons/people-a.svg", - sortOrder: 7 + ui = new AppUi({ + buttonName: "PEOPLE", + sortOrder: 7, + home: "hifi/Pal.qml", + onOpened: on, + onClosed: off, + onMessage: fromQml }); - button.clicked.connect(onTabletButtonClicked); - tablet.screenChanged.connect(onTabletScreenChanged); + tablet = ui.tablet; + button = ui.button; Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); @@ -877,6 +855,7 @@ var isWired = false; var audioTimer; var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too) function off() { + captureState(); if (isWired) { Script.update.disconnect(updateOverlays); Controller.mousePressEvent.disconnect(handleMouseEvent); @@ -896,15 +875,15 @@ function off() { } removeOverlays(); + if (wasOnPalScreen) { + ContextOverlay.enabled = true; + } } function shutdown() { if (onPalScreen) { tablet.gotoHomeScreen(); } - button.clicked.disconnect(onTabletButtonClicked); - tablet.removeButton(button); - tablet.screenChanged.disconnect(onTabletScreenChanged); Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); From ffa5259319dedee88ce9bd0050eb55a5802d2b2e Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 16 Jul 2018 13:06:12 -0700 Subject: [PATCH 33/56] cleanup references to button, tablet --- scripts/modules/appUi.js | 31 ++++++++++--------- scripts/system/pal.js | 65 ++++++++++------------------------------ 2 files changed, 32 insertions(+), 64 deletions(-) diff --git a/scripts/modules/appUi.js b/scripts/modules/appUi.js index 636affb94a..6e6c82bdc1 100644 --- a/scripts/modules/appUi.js +++ b/scripts/modules/appUi.js @@ -13,13 +13,16 @@ function AppUi(properties) { 1. var AppUi = Script.require('appUi'); 2. Put appname-i.svg, appname-a.svg in graphicsDirectory (where non-default graphicsDirectory can be added in #3). 3. ui = new AppUi({buttonName: "APPNAME", home: "qml-or-html-path"}); - (and if converting an existing app, + (And if converting an existing app, define var tablet = ui.tablet, button = ui.button; as needed. remove button.clicked.[dis]connect and tablet.remove(button).) 4. Define onOpened and onClosed behavior in #3, if any. - (and if converting an existing app, remove screenChanged.[dis]connect.) - 5. Define onMessage in #3, if any. - (and if converting an existing app, remove code that [un]wires that message handling.) + (And if converting an existing app, remove screenChanged.[dis]connect.) + 5. Define onMessage and sendMessage in #3, if any. + (And if converting an existing app, remove code that [un]wires that message handling such as + fromQml/sendToQml or webEventReceived/emitScriptEvent.) + 6. (If converting an existing app, cleanup stuff that is no longer necessary, like references to button, tablet, + and use isOpen, open(), and close() as needed.) x. lint! */ @@ -36,14 +39,14 @@ function AppUi(properties) { that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen. return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix. } - that.toOpen = function toOpen() { // How to open the app. + that.open = function open() { // How to open the app. if (that.isQML()) { that.tablet.loadQMLSource(that.home); } else { that.tablet.gotoWebScreen(that.home, that.inject); } }; - that.toClose = function toClose() { // How to close the app. + that.close = function close() { // How to close the app. // for toolbar-mode: go back to home screen, this will close the window. that.tablet.gotoHomeScreen(); }; @@ -87,7 +90,7 @@ function AppUi(properties) { that.onScreenChanged = function onScreenChanged(type, url) { // Set isOpen, wireEventBridge, set buttonActive as appropriate, // and finally call onOpened() or onClosed() IFF defined. - print('hrs fixme onScreenChanged', type, url, that.isOpen); + console.debug(that.buttonName, 'onScreenChanged', type, url, that.isOpen); if (that.checkIsOpen(type, url)) { if (!that.isOpen) { that.isOpen = true; @@ -112,17 +115,17 @@ function AppUi(properties) { that.hasEventBridge = false; that.wireEventBridge = function wireEventBridge(on) { // Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined. - print('hrs fixme wireEventBridge', on, that.hasEventBridge); + console.debug(that.buttonName, 'wireEventBridge', on, that.hasEventBridge); if (!that.onMessage) { return; } if (on) { if (!that.hasEventBridge) { - print('hrs fixme connecting', that.eventSignal()); + console.debug(that.buttonName, 'connecting', that.eventSignal()); that.eventSignal().connect(that.onMessage); that.hasEventBridge = true; } } else { if (that.hasEventBridge) { - print('hrs fixme connecting', that.eventSignal()); + console.debug(that.buttonName, 'connecting', that.eventSignal()); that.eventSignal().disconnect(that.onMessage); that.hasEventBridge = false; } @@ -132,18 +135,18 @@ function AppUi(properties) { // To facilitate incremental development, only wire onClicked to do something when "home" is defined in properties. that.onClicked = that.home ? function onClicked() { - // Call toOpen() or toClose(), and reset type based on current home property. + // Call open() or close(), and reset type based on current home property. if (that.isOpen) { - that.toClose(); + that.close(); } else { that.type = /.qml$/.test(that.home) ? 'QML' : 'Web' - that.toOpen(); + that.open(); } } : that.ignore; that.onScriptEnding = function onScriptEnding() { // Close if necessary, clean up any remaining handlers, and remove the button. if (that.isOpen) { - that.toClose(); + that.close(); } that.tablet.screenChanged.disconnect(that.onScreenChanged); if (that.button) { diff --git a/scripts/system/pal.js b/scripts/system/pal.js index cc12b7798f..b2560d48c3 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -325,7 +325,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See } function sendToQml(message) { - tablet.sendToQml(message); + ui.tablet.sendToQml(message); } function updateUser(data) { print('PAL update:', JSON.stringify(data)); @@ -670,44 +670,24 @@ triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Cont triggerPressMapping.from(Controller.Standard.RT).peek().to(makePressHandler(Controller.Standard.RightHand)); triggerPressMapping.from(Controller.Standard.LT).peek().to(makePressHandler(Controller.Standard.LeftHand)); +var ui; +// Most apps can have people toggle the tablet closed and open again, and the app should remain "open" even while +// the tablet is not shown. However, for the pal, we explicitly close the app and return the tablet to it's +// home screen (so that the avatar highlighting goes away). function tabletVisibilityChanged() { - if (!tablet.tabletShown && onPalScreen) { - ContextOverlay.enabled = true; - tablet.gotoHomeScreen(); + if (!ui.tablet.tabletShown && ui.isOpen) { + ui.close(); } } -var wasOnPalScreen = false; -var onPalScreen = false; -/*var hasEventBridge = false; -function wireEventBridge(on) { - if (on) { - if (!hasEventBridge) { - tablet.fromQml.connect(fromQml); - hasEventBridge = true; - } - } else { - if (hasEventBridge) { - tablet.fromQml.disconnect(fromQml); - hasEventBridge = false; - } - } -}*/ -function captureState() { - wasOnPalScreen = onPalScreen; - onPalScreen = ui.isOpen; - //wireEventBridge(onPalScreen); -} function on() { - captureState(); - isWired = true; ContextOverlay.enabled = false; Users.requestsDomainListData = true; audioTimer = createAudioInterval(AUDIO_LEVEL_UPDATE_INTERVAL_MS); - tablet.tabletShownChanged.connect(tabletVisibilityChanged); + ui.tablet.tabletShownChanged.connect(tabletVisibilityChanged); Script.update.connect(updateOverlays); Controller.mousePressEvent.connect(handleMouseEvent); Controller.mouseMoveEvent.connect(handleMouseMoveEvent); @@ -716,7 +696,6 @@ function on() { triggerPressMapping.enable(); populateNearbyUserList(); } -var button, ui, tablet; // // Message from other scripts, such as edit.js @@ -729,8 +708,8 @@ function receiveMessage(channel, messageString, senderID) { var message = JSON.parse(messageString); switch (message.method) { case 'select': - if (!onPalScreen) { - tablet.loadQMLSource(ui.home); + if (!ui.isOpen) { + ui.open(); Script.setTimeout(function () { sendToQml(message); }, 1000); } else { sendToQml(message); // Accepts objects, not just strings. @@ -810,9 +789,8 @@ function avatarDisconnected(nodeID) { function clearLocalQMLDataAndClosePAL() { sendToQml({ method: 'clearLocalQMLData' }); - if (onPalScreen) { - ContextOverlay.enabled = true; - tablet.gotoHomeScreen(); + if (ui.isOpen) { + ui.close(); } } @@ -838,7 +816,6 @@ function startup() { onMessage: fromQml }); tablet = ui.tablet; - button = ui.button; Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); @@ -850,40 +827,28 @@ function startup() { } startup(); - -var isWired = false; var audioTimer; var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too) function off() { - captureState(); - if (isWired) { + if (ui.isOpen) { // i.e., only when connected Script.update.disconnect(updateOverlays); Controller.mousePressEvent.disconnect(handleMouseEvent); Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent); - tablet.tabletShownChanged.disconnect(tabletVisibilityChanged); + ui.tablet.tabletShownChanged.disconnect(tabletVisibilityChanged); Users.usernameFromIDReply.disconnect(usernameFromIDReply); - ContextOverlay.enabled = true triggerMapping.disable(); triggerPressMapping.disable(); Users.requestsDomainListData = false; - - isWired = false; - if (audioTimer) { Script.clearInterval(audioTimer); } } removeOverlays(); - if (wasOnPalScreen) { - ContextOverlay.enabled = true; - } + ContextOverlay.enabled = true; } function shutdown() { - if (onPalScreen) { - tablet.gotoHomeScreen(); - } Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); From f1fed377636bb3c1ba16947f5ab72cff64e182cd Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 16 Jul 2018 15:58:01 -0700 Subject: [PATCH 34/56] cleanup --- scripts/modules/appUi.js | 66 +++++++++++++++++++++++++--------------- scripts/system/pal.js | 13 +++++--- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/scripts/modules/appUi.js b/scripts/modules/appUi.js index 6e6c82bdc1..f2b88dc4ea 100644 --- a/scripts/modules/appUi.js +++ b/scripts/modules/appUi.js @@ -14,22 +14,22 @@ function AppUi(properties) { 2. Put appname-i.svg, appname-a.svg in graphicsDirectory (where non-default graphicsDirectory can be added in #3). 3. ui = new AppUi({buttonName: "APPNAME", home: "qml-or-html-path"}); (And if converting an existing app, - define var tablet = ui.tablet, button = ui.button; as needed. - remove button.clicked.[dis]connect and tablet.remove(button).) + define var tablet = ui.tablet, button = ui.button; as needed. + remove button.clicked.[dis]connect and tablet.remove(button).) 4. Define onOpened and onClosed behavior in #3, if any. (And if converting an existing app, remove screenChanged.[dis]connect.) 5. Define onMessage and sendMessage in #3, if any. (And if converting an existing app, remove code that [un]wires that message handling such as - fromQml/sendToQml or webEventReceived/emitScriptEvent.) + fromQml/sendToQml or webEventReceived/emitScriptEvent.) 6. (If converting an existing app, cleanup stuff that is no longer necessary, like references to button, tablet, and use isOpen, open(), and close() as needed.) - x. lint! + 7. lint! */ var that = this; function defaultButton(name, suffix) { - var base = that[name] || (that.buttonPrefix + suffix); - that[name] = (base.indexOf('/') >= 0) ? base : (that.graphicsDirectory + base); //poor man's merge + var base = that[name] || (that.buttonPrefix + suffix); + that[name] = (base.indexOf('/') >= 0) ? base : (that.graphicsDirectory + base); //poor man's merge } // Defaults: @@ -37,34 +37,34 @@ function AppUi(properties) { that.inject = ""; that.graphicsDirectory = "icons/tablet-icons/"; // Where to look for button svgs. See below. that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen. - return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix. + return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix. } that.open = function open() { // How to open the app. - if (that.isQML()) { - that.tablet.loadQMLSource(that.home); - } else { - that.tablet.gotoWebScreen(that.home, that.inject); - } + if (that.isQML()) { + that.tablet.loadQMLSource(that.home); + } else { + that.tablet.gotoWebScreen(that.home, that.inject); + } }; that.close = function close() { // How to close the app. - // for toolbar-mode: go back to home screen, this will close the window. - that.tablet.gotoHomeScreen(); + // for toolbar-mode: go back to home screen, this will close the window. + that.tablet.gotoHomeScreen(); }; that.buttonActive = function buttonActive(isActive) { // How to make the button active (white). - that.button.editProperties({isActive: isActive}); + that.button.editProperties({isActive: isActive}); }; that.messagesWaiting = function messagesWaiting(isWaiting) { // How to indicate a message light on button. - // Note that waitingButton doesn't have to exist unless someone explicitly calls this with isWaiting true. + // Note that waitingButton doesn't have to exist unless someone explicitly calls this with isWaiting true. that.button.editProperties({ icon: isWaiting ? that.normalMessagesButton : that.normalButton, activeIcon: isWaiting ? that.activeMessagesButton : that.activeButton }); }; that.isQML = function isQML() { // We set type property in onClick. - return that.type === 'QML'; + return that.type === 'QML'; } that.eventSignal = function eventSignal() { // What signal to hook onMessage to. - return that.isQML() ? that.tablet.fromQml : that.tablet.webEventReceived; + return that.isQML() ? that.tablet.fromQml : that.tablet.webEventReceived; }; // Overwrite with the given properties: @@ -88,45 +88,61 @@ function AppUi(properties) { // Handlers that.onScreenChanged = function onScreenChanged(type, url) { - // Set isOpen, wireEventBridge, set buttonActive as appropriate, - // and finally call onOpened() or onClosed() IFF defined. + // Set isOpen, wireEventBridge, set buttonActive as appropriate, + // and finally call onOpened() or onClosed() IFF defined. console.debug(that.buttonName, 'onScreenChanged', type, url, that.isOpen); if (that.checkIsOpen(type, url)) { if (!that.isOpen) { - that.isOpen = true; that.wireEventBridge(true); that.buttonActive(true); if (that.onOpened) { that.onOpened(); } + that.isOpen = true; } } else { // Not us. Should we do something for type Home, Menu, and particularly Closed (meaning tablet hidden? if (that.isOpen) { - that.isOpen = false; that.wireEventBridge(false); that.buttonActive(false); if (that.onClosed) { that.onClosed(); } + that.isOpen = false; } } }; that.hasEventBridge = false; + // HTML event bridge uses strings, not objects. Here we abstract over that. + // (Although injected javascript still has to use JSON.stringify/JSON.parse.) + that.sendToHtml = function (messageObject) { that.tablet.emitScriptEvent(JSON.stringify(messageObject)); }; + that.fromHtml = function (messageString) { that.onMessage(JSON.parse(messageString)); } that.wireEventBridge = function wireEventBridge(on) { + // Uniquivocally sets that.sendMessage(messageObject) to do the right thing. // Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined. + var isQml = that.isQML(); console.debug(that.buttonName, 'wireEventBridge', on, that.hasEventBridge); + // Outbound (always, regardless of whether there is an inbound handler). + if (on) { + that.sendMessage = isQml ? that.tablet.sendToQml : that.sendToHtml; + } else { + that.sendMessage = that.ignore; + } + if (!that.onMessage) { return; } + + // Inbound + var handler = isQml ? that.onMessage : that.fromHtml; if (on) { if (!that.hasEventBridge) { console.debug(that.buttonName, 'connecting', that.eventSignal()); - that.eventSignal().connect(that.onMessage); + that.eventSignal().connect(handler); that.hasEventBridge = true; } } else { if (that.hasEventBridge) { - console.debug(that.buttonName, 'connecting', that.eventSignal()); - that.eventSignal().disconnect(that.onMessage); + console.debug(that.buttonName, 'disconnecting', that.eventSignal()); + that.eventSignal().disconnect(handler); that.hasEventBridge = false; } } diff --git a/scripts/system/pal.js b/scripts/system/pal.js index b2560d48c3..fe891087e4 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -20,7 +20,7 @@ var populateNearbyUserList, color, textures, removeOverlays, controllerComputePickRay, off, receiveMessage, avatarDisconnected, clearLocalQMLDataAndClosePAL, - createAudioInterval, tablet, CHANNEL, getConnectionData, findableByChanged, + createAudioInterval, CHANNEL, getConnectionData, findableByChanged, avatarAdded, avatarRemoved, avatarSessionChanged; // forward references; // hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed @@ -325,7 +325,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See } function sendToQml(message) { - ui.tablet.sendToQml(message); + ui.sendMessage(message); } function updateUser(data) { print('PAL update:', JSON.stringify(data)); @@ -680,8 +680,12 @@ function tabletVisibilityChanged() { } } +var previousContextOverlay = ContextOverlay.enabled; +var previousRequestsDomainListData = Users.requestsDomainListData; function on() { + previousContextOverlay = ContextOverlay.enabled; + previousRequestsDomainListData = Users.requestsDomainListData ContextOverlay.enabled = false; Users.requestsDomainListData = true; @@ -815,7 +819,6 @@ function startup() { onClosed: off, onMessage: fromQml }); - tablet = ui.tablet; Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); @@ -838,14 +841,14 @@ function off() { Users.usernameFromIDReply.disconnect(usernameFromIDReply); triggerMapping.disable(); triggerPressMapping.disable(); - Users.requestsDomainListData = false; if (audioTimer) { Script.clearInterval(audioTimer); } } removeOverlays(); - ContextOverlay.enabled = true; + ContextOverlay.enabled = previousContextOverlay; + Users.requestsDomainListData = previousRequestsDomainListData; } function shutdown() { From 2c92b02b95a0b221e26d74f3235b9a6e2c386241 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 16 Jul 2018 16:28:44 -0700 Subject: [PATCH 35/56] lint --- scripts/modules/appUi.js | 107 ++++++++++++++++++++------------------- scripts/system/pal.js | 34 ++++++------- 2 files changed, 71 insertions(+), 70 deletions(-) diff --git a/scripts/modules/appUi.js b/scripts/modules/appUi.js index f2b88dc4ea..7b6169e623 100644 --- a/scripts/modules/appUi.js +++ b/scripts/modules/appUi.js @@ -1,3 +1,5 @@ +"use strict"; +/*global Tablet, Script*/ // // libraries/appUi.js // @@ -25,7 +27,6 @@ function AppUi(properties) { and use isOpen, open(), and close() as needed.) 7. lint! */ - var that = this; function defaultButton(name, suffix) { var base = that[name] || (that.buttonPrefix + suffix); @@ -38,7 +39,7 @@ function AppUi(properties) { that.graphicsDirectory = "icons/tablet-icons/"; // Where to look for button svgs. See below. that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen. return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix. - } + }; that.open = function open() { // How to open the app. if (that.isQML()) { that.tablet.loadQMLSource(that.home); @@ -62,7 +63,7 @@ function AppUi(properties) { }; that.isQML = function isQML() { // We set type property in onClick. return that.type === 'QML'; - } + }; that.eventSignal = function eventSignal() { // What signal to hook onMessage to. return that.isQML() ? that.tablet.fromQml : that.tablet.webEventReceived; }; @@ -90,58 +91,58 @@ function AppUi(properties) { that.onScreenChanged = function onScreenChanged(type, url) { // Set isOpen, wireEventBridge, set buttonActive as appropriate, // and finally call onOpened() or onClosed() IFF defined. - console.debug(that.buttonName, 'onScreenChanged', type, url, that.isOpen); + console.debug(that.buttonName, 'onScreenChanged', type, url, that.isOpen); if (that.checkIsOpen(type, url)) { - if (!that.isOpen) { - that.wireEventBridge(true); - that.buttonActive(true); - if (that.onOpened) { - that.onOpened(); - } - that.isOpen = true; - } + if (!that.isOpen) { + that.wireEventBridge(true); + that.buttonActive(true); + if (that.onOpened) { + that.onOpened(); + } + that.isOpen = true; + } } else { // Not us. Should we do something for type Home, Menu, and particularly Closed (meaning tablet hidden? - if (that.isOpen) { - that.wireEventBridge(false); - that.buttonActive(false); - if (that.onClosed) { - that.onClosed(); - } - that.isOpen = false; - } + if (that.isOpen) { + that.wireEventBridge(false); + that.buttonActive(false); + if (that.onClosed) { + that.onClosed(); + } + that.isOpen = false; + } } }; that.hasEventBridge = false; // HTML event bridge uses strings, not objects. Here we abstract over that. // (Although injected javascript still has to use JSON.stringify/JSON.parse.) that.sendToHtml = function (messageObject) { that.tablet.emitScriptEvent(JSON.stringify(messageObject)); }; - that.fromHtml = function (messageString) { that.onMessage(JSON.parse(messageString)); } + that.fromHtml = function (messageString) { that.onMessage(JSON.parse(messageString)); }; that.wireEventBridge = function wireEventBridge(on) { - // Uniquivocally sets that.sendMessage(messageObject) to do the right thing. - // Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined. - var isQml = that.isQML(); - console.debug(that.buttonName, 'wireEventBridge', on, that.hasEventBridge); - // Outbound (always, regardless of whether there is an inbound handler). - if (on) { - that.sendMessage = isQml ? that.tablet.sendToQml : that.sendToHtml; - } else { - that.sendMessage = that.ignore; - } + // Uniquivocally sets that.sendMessage(messageObject) to do the right thing. + // Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined. + var handler, isQml = that.isQML(); + console.debug(that.buttonName, 'wireEventBridge', on, that.hasEventBridge); + // Outbound (always, regardless of whether there is an inbound handler). + if (on) { + that.sendMessage = isQml ? that.tablet.sendToQml : that.sendToHtml; + } else { + that.sendMessage = that.ignore; + } - if (!that.onMessage) { return; } + if (!that.onMessage) { return; } - // Inbound - var handler = isQml ? that.onMessage : that.fromHtml; + // Inbound + handler = isQml ? that.onMessage : that.fromHtml; if (on) { if (!that.hasEventBridge) { - console.debug(that.buttonName, 'connecting', that.eventSignal()); + console.debug(that.buttonName, 'connecting', that.eventSignal()); that.eventSignal().connect(handler); that.hasEventBridge = true; } } else { if (that.hasEventBridge) { - console.debug(that.buttonName, 'disconnecting', that.eventSignal()); + console.debug(that.buttonName, 'disconnecting', that.eventSignal()); that.eventSignal().disconnect(handler); that.hasEventBridge = false; } @@ -150,31 +151,31 @@ function AppUi(properties) { that.isOpen = false; // To facilitate incremental development, only wire onClicked to do something when "home" is defined in properties. that.onClicked = that.home - ? function onClicked() { - // Call open() or close(), and reset type based on current home property. + ? function onClicked() { + // Call open() or close(), and reset type based on current home property. if (that.isOpen) { - that.close(); + that.close(); } else { - that.type = /.qml$/.test(that.home) ? 'QML' : 'Web' - that.open(); + that.type = /.qml$/.test(that.home) ? 'QML' : 'Web'; + that.open(); } - } : that.ignore; + } : that.ignore; that.onScriptEnding = function onScriptEnding() { - // Close if necessary, clean up any remaining handlers, and remove the button. - if (that.isOpen) { - that.close(); - } - that.tablet.screenChanged.disconnect(that.onScreenChanged); - if (that.button) { + // Close if necessary, clean up any remaining handlers, and remove the button. + if (that.isOpen) { + that.close(); + } + that.tablet.screenChanged.disconnect(that.onScreenChanged); + if (that.button) { if (that.onClicked) { - that.button.clicked.disconnect(that.onClicked); - } + that.button.clicked.disconnect(that.onClicked); + } that.tablet.removeButton(that.button); - } + } }; // Set up the handlers. - that.tablet.screenChanged.connect(that.onScreenChanged); + that.tablet.screenChanged.connect(that.onScreenChanged); that.button.clicked.connect(that.onClicked); Script.scriptEnding.connect(that.onScriptEnding); -}; +} module.exports = AppUi; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index fe891087e4..03dfada7ec 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -12,10 +12,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function() { // BEGIN LOCAL_SCOPE +(function () { // BEGIN LOCAL_SCOPE - var request = Script.require('request').request; - var AppUi = Script.require('appUi'); +var request = Script.require('request').request; +var AppUi = Script.require('appUi'); var populateNearbyUserList, color, textures, removeOverlays, controllerComputePickRay, off, @@ -41,6 +41,7 @@ var HOVER_TEXTURES = { var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6}; var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29}; var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now +var METAVERSE_BASE = Account.metaverseServerURL; Script.include("/~/system/libraries/controllers.js"); @@ -222,7 +223,7 @@ function convertDbToLinear(decibels) { return Math.pow(2, decibels / 10.0); } function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var data; + var data, connectionUserName, friendUserName; switch (message.method) { case 'selected': selectedIds = message.params; @@ -282,7 +283,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See } getConnectionData(false); }); - break + break; case 'removeFriend': friendUserName = message.params; @@ -297,7 +298,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See } getConnectionData(friendUserName); }); - break + break; case 'addFriend': friendUserName = message.params; print("Adding " + friendUserName + " to friends."); @@ -308,17 +309,17 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See body: { username: friendUserName, } - }, function (error, response) { - if (error || (response.status !== 'success')) { - print("Error: unable to friend " + friendUserName, error || response.status); - return; - } - getConnectionData(friendUserName); + }, function (error, response) { + if (error || (response.status !== 'success')) { + print("Error: unable to friend " + friendUserName, error || response.status); + return; } - ); + getConnectionData(friendUserName); + } + ); break; case 'http.request': - break; // Handled by request-service. + break; // Handled by request-service. default: print('Unrecognized message from Pal.qml:', JSON.stringify(message)); } @@ -335,7 +336,6 @@ function updateUser(data) { // User management services // // These are prototype versions that will be changed when the back end changes. -var METAVERSE_BASE = Account.metaverseServerURL; function requestJSON(url, callback) { // callback(data) if successfull. Logs otherwise. request({ @@ -363,7 +363,7 @@ function getProfilePicture(username, callback) { // callback(url) if successfull }); } function getAvailableConnections(domain, callback) { // callback([{usename, location}...]) if successfull. (Logs otherwise) - url = METAVERSE_BASE + '/api/v1/users?per_page=400&' + var url = METAVERSE_BASE + '/api/v1/users?per_page=400&'; if (domain) { url += 'status=' + domain.slice(1, -1); // without curly braces } else { @@ -374,7 +374,7 @@ function getAvailableConnections(domain, callback) { // callback([{usename, loca }); } function getInfoAboutUser(specificUsername, callback) { - url = METAVERSE_BASE + '/api/v1/users?filter=connections' + var url = METAVERSE_BASE + '/api/v1/users?filter=connections'; requestJSON(url, function (connectionsData) { for (user in connectionsData.users) { if (connectionsData.users[user].username === specificUsername) { From 84dac943795d540ef9446b0decea86039827ce8e Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 16 Jul 2018 17:03:50 -0700 Subject: [PATCH 36/56] Allow creator to disable hand touch --- interface/src/avatar/MyAvatar.cpp | 10 + interface/src/avatar/MyAvatar.h | 16 + scripts/system/controllers/handTouch.js | 537 ++++++++++++------------ 3 files changed, 295 insertions(+), 268 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index dbb1d8a56c..53d1fc7dca 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -262,6 +262,16 @@ void MyAvatar::setDominantHand(const QString& hand) { } } +void MyAvatar::requestDisableHandTouch() { + _disableHandTouchCount++; + emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0); +} + +void MyAvatar::requestEnableHandTouch() { + _disableHandTouchCount = std::max(_disableHandTouchCount - 1, 0); + emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0); +} + void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) { QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); engine->globalObject().setProperty("MyAvatar", value); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e795d9356d..e56d40487a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -505,6 +505,14 @@ public: * @returns {boolean} */ Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } + /**jsdoc + * @function MyAvatar.requestEnableHandTouch + */ + Q_INVOKABLE void requestEnableHandTouch(); + /**jsdoc + * @function MyAvatar.requestDisableHandTouch + */ + Q_INVOKABLE void requestDisableHandTouch(); bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); } void setUseAdvancedMovementControls(bool useAdvancedMovementControls) @@ -1391,6 +1399,13 @@ signals: */ void scaleChanged(); + /**jsdoc + * @function MyAvatar.shouldDisableHandTouchChanged + * @param {boolean} shouldDisable + * @returns {Signal} + */ + void shouldDisableHandTouchChanged(bool shouldDisable); + private slots: void leaveDomain(); @@ -1667,6 +1682,7 @@ private: bool _shouldLoadScripts { false }; bool _haveReceivedHeightLimitsFromDomain { false }; + int _disableHandTouchCount { 0 }; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/scripts/system/controllers/handTouch.js b/scripts/system/controllers/handTouch.js index 5e633d4740..86cea91d03 100644 --- a/scripts/system/controllers/handTouch.js +++ b/scripts/system/controllers/handTouch.js @@ -14,64 +14,63 @@ /* global Script, Overlays, Controller, Vec3, MyAvatar, Entities */ -(function() { - - var MSECONDS_AFTER_LOAD = 2000; +(function () { + var handTouchEnabled = true; + var MSECONDS_AFTER_LOAD = 2000; var updateFingerWithIndex = 0; - - + // Keys to access finger data var fingerKeys = ["pinky", "ring", "middle", "index", "thumb"]; - - // Additionally close the hands to achieve a grabbing effect + + // Additionally close the hands to achieve a grabbing effect var grabPercent = { left: 0, right: 0 }; - + var Palm = function() { this.position = {x: 0, y: 0, z: 0}; this.perpendicular = {x: 0, y: 0, z: 0}; this.distance = 0; this.fingers = { - pinky: {x: 0, y: 0, z: 0}, - middle: {x: 0, y: 0, z: 0}, - ring: {x: 0, y: 0, z: 0}, - thumb: {x: 0, y: 0, z: 0}, + pinky: {x: 0, y: 0, z: 0}, + middle: {x: 0, y: 0, z: 0}, + ring: {x: 0, y: 0, z: 0}, + thumb: {x: 0, y: 0, z: 0}, index: {x: 0, y: 0, z: 0} }; this.set = false; }; - + var palmData = { left: new Palm(), right: new Palm() }; var handJointNames = {left: "LeftHand", right: "RightHand"}; - - // Store which fingers are touching - if all false restate the default poses + + // Store which fingers are touching - if all false restate the default poses var isTouching = { left: { - pinky: false, - middle: false, - ring: false, - thumb: false, - index: false + pinky: false, + middle: false, + ring: false, + thumb: false, + index: false }, right: { - pinky: false, - middle: false, - ring: false, - thumb: false, + pinky: false, + middle: false, + ring: false, + thumb: false, index: false } }; - + // frame count for transition to default pose - + var countToDefault = { left: 0, right: 0 }; - + // joint data for open pose var dataOpen = { left: { @@ -128,7 +127,7 @@ ] } }; - + // joint data for close pose var dataClose = { left: { @@ -185,78 +184,78 @@ ] } }; - + // snapshot for the default pose var dataDefault = { left: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], set: false }, right: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], set: false } }; - + // joint data for the current frame var dataCurrent = { left: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] }, right: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] } }; - - // interpolated values on joint data to smooth movement + + // interpolated values on joint data to smooth movement var dataDelta = { left: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] }, right: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] } }; - + // Acquire an updated value per hand every 5 frames when finger is touching (faster in) var touchAnimationSteps = 5; - - // Acquire an updated value per hand every 20 frames when finger is returning to default position (slower out) + + // Acquire an updated value per hand every 20 frames when finger is returning to default position (slower out) var defaultAnimationSteps = 10; - + // Debugging info var showSphere = false; var showLines = false; - + // This get setup on creation var linesCreated = false; var sphereCreated = false; - - // Register object with API Debugger + + // Register object with API Debugger var varsToDebug = { scriptLoaded: false, toggleDebugSphere: function() { @@ -275,17 +274,17 @@ }, fingerPercent: { left: { - pinky: 0.38, - middle: 0.38, - ring: 0.38, - thumb: 0.38, + pinky: 0.38, + middle: 0.38, + ring: 0.38, + thumb: 0.38, index: 0.38 - } , + } , right: { - pinky: 0.38, - middle: 0.38, - ring: 0.38, - thumb: 0.38, + pinky: 0.38, + middle: 0.38, + ring: 0.38, + thumb: 0.38, index: 0.38 } }, @@ -300,12 +299,11 @@ palmData: { left: new Palm(), right: new Palm() - }, + }, offset: {x: 0, y: 0, z: 0}, avatarLoaded: false }; - - + // Add/Subtract the joint data - per finger joint function addVals(val1, val2, sign) { var val = []; @@ -321,7 +319,7 @@ } return val; } - + // Multiply/Divide the joint data - per finger joint function multiplyValsBy(val1, num) { var val = []; @@ -334,7 +332,7 @@ } return val; } - + // Calculate the finger lengths by adding its joint lengths function getJointDistances(jointNamesArray) { var result = {distances: [], totalDistance: 0}; @@ -349,13 +347,12 @@ } return result; } - - function dataRelativeToWorld(side, dataIn, dataOut) { + function dataRelativeToWorld(side, dataIn, dataOut) { var handJoint = handJointNames[side]; var jointIndex = MyAvatar.getJointIndex(handJoint); var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); - + dataOut.position = MyAvatar.jointToWorldPoint(dataIn.position, jointIndex); var localPerpendicular = side === "right" ? {x: 0.2, y: 0, z: 1} : {x: -0.2, y: 0, z: 1}; dataOut.perpendicular = Vec3.normalize( @@ -365,15 +362,14 @@ for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; dataOut.fingers[finger] = MyAvatar.jointToWorldPoint(dataIn.fingers[finger], jointIndex); - } + } } - - function dataRelativeToHandJoint(side, dataIn, dataOut) { + function dataRelativeToHandJoint(side, dataIn, dataOut) { var handJoint = handJointNames[side]; var jointIndex = MyAvatar.getJointIndex(handJoint); var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); - + dataOut.position = MyAvatar.worldToJointPoint(dataIn.position, jointIndex); dataOut.perpendicular = MyAvatar.worldToJointPoint(Vec3.sum(worldPosHand, dataIn.perpendicular), jointIndex); dataOut.distance = dataIn.distance; @@ -382,46 +378,44 @@ dataOut.fingers[finger] = MyAvatar.worldToJointPoint(dataIn.fingers[finger], jointIndex); } } - - // Calculate touch field; Sphere at the center of the palm, + + // Calculate touch field; Sphere at the center of the palm, // perpendicular vector from the palm plane and origin of the the finger rays - function estimatePalmData(side) { // Return data object - var data = new Palm(); - - var jointOffset = { x: 0, y: 0, z: 0 }; - + var data = new Palm(); + + var jointOffset = { x: 0, y: 0, z: 0 }; + var upperSide = side[0].toUpperCase() + side.substring(1); var jointIndexHand = MyAvatar.getJointIndex(upperSide + "Hand"); - + // Store position of the hand joint var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand); var minusWorldPosHand = {x: -worldPosHand.x, y: -worldPosHand.y, z: -worldPosHand.z}; - + // Data for finger rays var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; var positions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; - + var thumbLength = 0; var weightCount = 0; - + // Calculate palm center - var handJointWeight = 1; var fingerJointWeight = 2; - + var palmCenter = {x: 0, y: 0, z: 0}; palmCenter = Vec3.sum(worldPosHand, palmCenter); - + weightCount += handJointWeight; - + for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; var jointSuffixes = 4; // Get 4 joint names with suffix numbers (0, 1, 2, 3) var jointNames = getJointNames(side, finger, jointSuffixes); var fingerLength = getJointDistances(jointNames).totalDistance; - + var jointIndex = MyAvatar.getJointIndex(jointNames[0]); positions[finger] = MyAvatar.jointToWorldPoint(jointOffset, jointIndex); directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand)); @@ -429,66 +423,63 @@ if (finger !== "thumb") { // finger joints have double the weight than the hand joint // This would better position the palm estimation - - palmCenter = Vec3.sum(Vec3.multiply(fingerJointWeight, positions[finger]), palmCenter); + + palmCenter = Vec3.sum(Vec3.multiply(fingerJointWeight, positions[finger]), palmCenter); weightCount += fingerJointWeight; } else { thumbLength = fingerLength; } } - + // perpendicular change direction depending on the side - data.perpendicular = (side === "right") ? - Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): + data.perpendicular = (side === "right") ? + Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): Vec3.normalize(Vec3.cross(directions.pinky, directions.index)); - + data.position = Vec3.multiply(1.0/weightCount, palmCenter); - + if (side === "right") { varsToDebug.offset = MyAvatar.worldToJointPoint(worldPosHand, jointIndexHand); } - + var palmDistanceMultiplier = 1.55; // 1.55 based on test/error for the sphere radius that best fits the hand - data.distance = palmDistanceMultiplier*Vec3.distance(data.position, positions.index); + data.distance = palmDistanceMultiplier*Vec3.distance(data.position, positions.index); // move back thumb ray origin var thumbBackMultiplier = 0.2; data.fingers.thumb = Vec3.sum( data.fingers.thumb, Vec3.multiply( -thumbBackMultiplier * thumbLength, data.perpendicular)); - + // return getDataRelativeToHandJoint(side, data); dataRelativeToHandJoint(side, data, palmData[side]); palmData[side].set = true; - // return palmData[side]; } - + // Register GlobalDebugger for API Debugger Script.registerValue("GlobalDebugger", varsToDebug); // store the rays for the fingers - only for debug purposes - var fingerRays = { + var fingerRays = { left: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, index: undefined - }, + }, right: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, index: undefined } }; - + // Create debug overlays - finger rays + palm rays + spheres - var palmRay, sphereHand; - + function createDebugLines() { - for (var i = 0; i < fingerKeys.length; i++) { fingerRays.left[fingerKeys[i]] = Overlays.addOverlay("line3d", { color: { red: 0, green: 0, blue: 255 }, @@ -503,7 +494,7 @@ visible: showLines }); } - + palmRay = { left: Overlays.addOverlay("line3d", { color: { red: 255, green: 0, blue: 0 }, @@ -520,9 +511,8 @@ }; linesCreated = true; } - + function createDebugSphere() { - sphereHand = { right: Overlays.addOverlay("sphere", { position: MyAvatar.position, @@ -536,10 +526,10 @@ scale: { x: 0.01, y: 0.01, z: 0.01 }, visible: showSphere }) - }; + }; sphereCreated = true; } - + function acquireDefaultPose(side) { for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; @@ -553,85 +543,85 @@ } dataDefault[side].set = true; } - - var rayPicks = { - left: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, + + var rayPicks = { + left: { + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, index: undefined }, - right: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, + right: { + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, index: undefined } }; - - var dataFailed = { - left: { - pinky: 0, - middle: 0, - ring: 0, - thumb: 0, + + var dataFailed = { + left: { + pinky: 0, + middle: 0, + ring: 0, + thumb: 0, index: 0 }, - right: { - pinky: 0, - middle: 0, - ring: 0, - thumb: 0, + right: { + pinky: 0, + middle: 0, + ring: 0, + thumb: 0, index: 0 } }; - + function clearRayPicks(side) { for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; if (rayPicks[side][finger] !== undefined) { RayPick.removeRayPick(rayPicks[side][finger]); rayPicks[side][finger] = undefined; - } + } } } - + function createRayPicks(side) { var data = palmData[side]; clearRayPicks(side); for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; + var finger = fingerKeys[i]; var LOOKUP_DISTANCE_MULTIPLIER = 1.5; var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; - var checkOffset = { - x: data.perpendicular.x * dist, - y: data.perpendicular.y * dist, - z: data.perpendicular.z * dist + var checkOffset = { + x: data.perpendicular.x * dist, + y: data.perpendicular.y * dist, + z: data.perpendicular.z * dist }; - + var checkPoint = Vec3.sum(data.position, Vec3.multiply(2, checkOffset)); var sensorToWorldScale = MyAvatar.getSensorToWorldScale(); - + var origin = data.fingers[finger]; - + var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin)); - + origin = Vec3.multiply(1/sensorToWorldScale, origin); - + rayPicks[side][finger] = RayPick.createRayPick( - { - "enabled": false, + { + "enabled": false, "joint": handJointNames[side], "posOffset": origin, "dirOffset": direction, "filter": RayPick.PICK_ENTITIES } - ); - - RayPick.setPrecisionPicking(rayPicks[side][finger], true); - } + ); + + RayPick.setPrecisionPicking(rayPicks[side][finger], true); + } } function activateNextRay(side, index) { var nextIndex = (index < fingerKeys.length-1) ? index + 1 : 0; @@ -641,46 +631,44 @@ RayPick.enableRayPick(rayPicks[side][finger]); } else { RayPick.disableRayPick(rayPicks[side][finger]); - } + } } } - - function updateSphereHand(side) { + function updateSphereHand(side) { var data = new Palm(); dataRelativeToWorld(side, palmData[side], data); varsToDebug.palmData[side] = palmData[side]; - + var palmPoint = data.position; var LOOKUP_DISTANCE_MULTIPLIER = 1.5; var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; - - // Situate the debugging overlays - - var checkOffset = { - x: data.perpendicular.x * dist, - y: data.perpendicular.y * dist, - z: data.perpendicular.z * dist + + // Situate the debugging overlays + var checkOffset = { + x: data.perpendicular.x * dist, + y: data.perpendicular.y * dist, + z: data.perpendicular.z * dist }; - + var spherePos = Vec3.sum(palmPoint, checkOffset); var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset)); - + if (showLines) { Overlays.editOverlay(palmRay[side], { start: palmPoint, end: checkPoint, visible: showLines - }); + }); for (var i = 0; i < fingerKeys.length; i++) { Overlays.editOverlay(fingerRays[side][fingerKeys[i]], { start: data.fingers[fingerKeys[i]], end: checkPoint, visible: showLines }); - } + } } - + if (showSphere) { Overlays.editOverlay(sphereHand[side], { position: spherePos, @@ -690,16 +678,12 @@ z: 2*dist }, visible: showSphere - }); + }); } - + // Update the intersection of only one finger at a time - - var finger = fingerKeys[updateFingerWithIndex]; - - + var finger = fingerKeys[updateFingerWithIndex]; var grabbables = Entities.findEntities(spherePos, dist); - var intersection; if (rayPicks[side][finger] !== undefined) { intersection = RayPick.getPrevRayPickResult(rayPicks[side][finger]); @@ -708,11 +692,10 @@ var animationSteps = defaultAnimationSteps; var newFingerData = dataDefault[side][finger]; var isAbleToGrab = false; - if (grabbables.length > 0) { - + if (grabbables.length > 0) { RayPick.setIncludeItems(rayPicks[side][finger], grabbables); - if (intersection === undefined) { + if (intersection === undefined) { return; } @@ -725,28 +708,27 @@ // Store if this finger is touching something isTouching[side][finger] = isAbleToGrab; if (isAbleToGrab) { - // update the open/close percentage for this finger - + // update the open/close percentage for this finger var FINGER_REACT_MULTIPLIER = 2.8; - + percent = intersection.distance/(FINGER_REACT_MULTIPLIER*dist); - + var THUMB_FACTOR = 0.2; var FINGER_FACTOR = 0.05; - + // Amount of grab coefficient added to the fingers - thumb is higher - var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR; + var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR; percent += grabMultiplier * grabPercent[side]; - + // Calculate new interpolation data var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1); // Assign close/open ratio to finger to simulate touch - newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); + newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); animationSteps = touchAnimationSteps; - } + } varsToDebug.fingerPercent[side][finger] = percent; - - } + + } if (!isAbleToGrab) { dataFailed[side][finger] = dataFailed[side][finger] === 0 ? 1 : 2; } else { @@ -755,13 +737,12 @@ // If it only fails once it will not update increments if (dataFailed[side][finger] !== 1) { // Calculate animation increments - dataDelta[side][finger] = - multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); + dataDelta[side][finger] = + multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); } } - + // Recreate the finger joint names - function getJointNames(side, finger, count) { var names = []; for (var i = 1; i < count+1; i++) { @@ -772,30 +753,34 @@ } // Capture the controller values - var leftTriggerPress = function (value) { varsToDebug.triggerValues.leftTriggerValue = value; - // the value for the trigger increments the hand-close percentage + // the value for the trigger increments the hand-close percentage grabPercent.left = value; }; + var leftTriggerClick = function (value) { varsToDebug.triggerValues.leftTriggerClicked = value; }; + var rightTriggerPress = function (value) { varsToDebug.triggerValues.rightTriggerValue = value; - // the value for the trigger increments the hand-close percentage + // the value for the trigger increments the hand-close percentage grabPercent.right = value; }; + var rightTriggerClick = function (value) { varsToDebug.triggerValues.rightTriggerClicked = value; }; + var leftSecondaryPress = function (value) { varsToDebug.triggerValues.leftSecondaryValue = value; }; + var rightSecondaryPress = function (value) { varsToDebug.triggerValues.rightSecondaryValue = value; }; - + var MAPPING_NAME = "com.highfidelity.handTouch"; var mapping = Controller.newMapping(MAPPING_NAME); mapping.from([Controller.Standard.RT]).peek().to(rightTriggerPress); @@ -809,16 +794,17 @@ mapping.from([Controller.Standard.RightGrip]).peek().to(rightSecondaryPress); Controller.enableMapping(MAPPING_NAME); - + if (showLines && !linesCreated) { createDebugLines(); linesCreated = true; } + if (showSphere && !sphereCreated) { createDebugSphere(); sphereCreated = true; } - + function getTouching(side) { var animating = false; for (var i = 0; i < fingerKeys.length; i++) { @@ -827,19 +813,57 @@ } return animating; // return false only if none of the fingers are touching } - + function reEstimatePalmData() { ["right", "left"].forEach(function(side) { estimatePalmData(side); }); } - + function recreateRayPicks() { ["right", "left"].forEach(function(side) { createRayPicks(side); }); } - + + function cleanUp() { + ["right", "left"].forEach(function (side) { + if (linesCreated) { + Overlays.deleteOverlay(palmRay[side]); + } + if (sphereCreated) { + Overlays.deleteOverlay(sphereHand[side]); + } + clearRayPicks(side); + for (var i = 0; i < fingerKeys.length; i++) { + var finger = fingerKeys[i]; + var jointSuffixes = 3; // We need to clear the joints 0, 1 and 2 joints + var names = getJointNames(side, finger, jointSuffixes); + for (var j = 0; j < names.length; j++) { + var index = MyAvatar.getJointIndex(names[j]); + MyAvatar.clearJointData(index); + } + if (linesCreated) { + Overlays.deleteOverlay(fingerRays[side][finger]); + } + } + }); + } + + MyAvatar.shouldDisableHandTouchChanged.connect(function (shouldDisable) { + if (shouldDisable) { + if (handTouchEnabled) { + cleanUp(); + } + } else { + if (!handTouchEnabled) { + reEstimatePalmData(); + recreateRayPicks(); + } + } + handTouchEnabled = !shouldDisable; + }); + MyAvatar.onLoadComplete.connect(function () { // Sometimes the rig is not ready when this signal is trigger console.log("avatar loaded"); @@ -848,78 +872,55 @@ recreateRayPicks(); }, MSECONDS_AFTER_LOAD); }); - + MyAvatar.sensorToWorldScaleChanged.connect(function() { reEstimatePalmData(); }); - - Script.scriptEnding.connect(function () { - ["right", "left"].forEach(function(side) { - if (linesCreated) { - Overlays.deleteOverlay(palmRay[side]); - } - if (sphereCreated) { - Overlays.deleteOverlay(sphereHand[side]); - } - clearRayPicks(side); - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - var jointSuffixes = 3; // We need to clear the joints 0, 1 and 2 joints - var names = getJointNames(side, finger, jointSuffixes); - - for (var j = 0; j < names.length; j++) { - var index = MyAvatar.getJointIndex(names[j]); - MyAvatar.clearJointData(index); - } - - if (linesCreated) { - Overlays.deleteOverlay(fingerRays[side][finger]); - } - } - }); + Script.scriptEnding.connect(function () { + cleanUp(); }); - - Script.update.connect(function() { - + + Script.update.connect(function () { + + if (!handTouchEnabled) { + return; + } + // index of the finger that needs to be updated this frame - updateFingerWithIndex = (updateFingerWithIndex < fingerKeys.length-1) ? updateFingerWithIndex + 1 : 0; - + ["right", "left"].forEach(function(side) { - + if (!palmData[side].set) { reEstimatePalmData(); recreateRayPicks(); } - + // recalculate the base data updateSphereHand(side); activateNextRay(side, updateFingerWithIndex); - + // this vars manage the transition to default pose var isHandTouching = getTouching(side); countToDefault[side] = isHandTouching ? 0 : countToDefault[side] + 1; - - + for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; var jointSuffixes = 3; // We need to update rotation of the 0, 1 and 2 joints - var names = getJointNames(side, finger, jointSuffixes); - + var names = getJointNames(side, finger, jointSuffixes); + // Add the animation increments - - dataCurrent[side][finger] = addVals(dataCurrent[side][finger], dataDelta[side][finger], 1); - + dataCurrent[side][finger] = addVals(dataCurrent[side][finger], dataDelta[side][finger], 1); + // update every finger joint - for (var j = 0; j < names.length; j++) { var index = MyAvatar.getJointIndex(names[j]); // if no finger is touching restate the default poses - if (isHandTouching || (dataDefault[side].set && + if (isHandTouching || (dataDefault[side].set && countToDefault[side] < fingerKeys.length*touchAnimationSteps)) { var quatRot = dataCurrent[side][finger][j]; - MyAvatar.setJointRotation(index, quatRot); + MyAvatar.setJointRotation(index, quatRot); } else { MyAvatar.clearJointData(index); } From 82a3b73de893a5b077818cb5de1fc13ed0cbcc30 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 17 Jul 2018 07:06:48 -0700 Subject: [PATCH 37/56] Added disable hand touch for entityID --- interface/src/avatar/MyAvatar.cpp | 8 +++++++ interface/src/avatar/MyAvatar.h | 18 +++++++++++++++ scripts/system/controllers/handTouch.js | 29 ++++++++++++++++++++----- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 53d1fc7dca..094db72e0b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -272,6 +272,14 @@ void MyAvatar::requestEnableHandTouch() { emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0); } +void MyAvatar::disableHandTouchForID(const QString& entityID) { + emit disableHandTouchForIDChanged(entityID, true); +} + +void MyAvatar::enableHandTouchForID(const QString& entityID) { + emit disableHandTouchForIDChanged(entityID, false); +} + void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) { QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); engine->globalObject().setProperty("MyAvatar", value); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e56d40487a..d125c8c3c5 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -513,6 +513,16 @@ public: * @function MyAvatar.requestDisableHandTouch */ Q_INVOKABLE void requestDisableHandTouch(); + /**jsdoc + * @function MyAvatar.disableHandTouchForID + * @param {string} entityId + */ + Q_INVOKABLE void disableHandTouchForID(const QString& entityId); + /**jsdoc + * @function MyAvatar.enableHandTouchForID + * @param {string} entityId + */ + Q_INVOKABLE void enableHandTouchForID(const QString& entityId); bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); } void setUseAdvancedMovementControls(bool useAdvancedMovementControls) @@ -1406,6 +1416,14 @@ signals: */ void shouldDisableHandTouchChanged(bool shouldDisable); + /**jsdoc + * @function MyAvatar.handTouchForIDChanged + * @param {string} entityID + * @param {boolean} disable + * @returns {Signal} + */ + void disableHandTouchForIDChanged(const QString& entityID, bool disable); + private slots: void leaveDomain(); diff --git a/scripts/system/controllers/handTouch.js b/scripts/system/controllers/handTouch.js index 86cea91d03..db79aa4a77 100644 --- a/scripts/system/controllers/handTouch.js +++ b/scripts/system/controllers/handTouch.js @@ -19,8 +19,9 @@ var handTouchEnabled = true; var MSECONDS_AFTER_LOAD = 2000; var updateFingerWithIndex = 0; - - // Keys to access finger data + var untouchableEntities = []; + + // Keys to access finger data var fingerKeys = ["pinky", "ring", "middle", "index", "thumb"]; // Additionally close the hands to achieve a grabbing effect @@ -623,6 +624,7 @@ RayPick.setPrecisionPicking(rayPicks[side][finger], true); } } + function activateNextRay(side, index) { var nextIndex = (index < fingerKeys.length-1) ? index + 1 : 0; for (var i = 0; i < fingerKeys.length; i++) { @@ -683,7 +685,11 @@ // Update the intersection of only one finger at a time var finger = fingerKeys[updateFingerWithIndex]; - var grabbables = Entities.findEntities(spherePos, dist); + var nearbyEntities = Entities.findEntities(spherePos, dist); + // Filter the entities that are allowed to be touched + var touchableEntities = nearbyEntities.filter(function (id) { + return untouchableEntities.indexOf(id) == -1; + }); var intersection; if (rayPicks[side][finger] !== undefined) { intersection = RayPick.getPrevRayPickResult(rayPicks[side][finger]); @@ -692,8 +698,8 @@ var animationSteps = defaultAnimationSteps; var newFingerData = dataDefault[side][finger]; var isAbleToGrab = false; - if (grabbables.length > 0) { - RayPick.setIncludeItems(rayPicks[side][finger], grabbables); + if (touchableEntities.length > 0) { + RayPick.setIncludeItems(rayPicks[side][finger], touchableEntities); if (intersection === undefined) { return; @@ -864,6 +870,19 @@ handTouchEnabled = !shouldDisable; }); + MyAvatar.disableHandTouchForIDChanged.connect(function (entityID, disable) { + var entityIndex = untouchableEntities.indexOf(entityID); + if (disable) { + if (entityIndex == -1) { + untouchableEntities.push(entityID); + } + } else { + if (entityIndex != -1) { + untouchableEntities.splice(entityIndex, 1); + } + } + }); + MyAvatar.onLoadComplete.connect(function () { // Sometimes the rig is not ready when this signal is trigger console.log("avatar loaded"); From 09e1090e7221d1373c63f9044bbaf1006a76e26a Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 17 Jul 2018 02:12:54 +0200 Subject: [PATCH 38/56] Use create app in tablet mode when choosing to use tablet in desktop mode --- scripts/system/edit.js | 27 ++++++++++++++++++-------- scripts/system/libraries/entityList.js | 6 +++--- scripts/system/libraries/gridTool.js | 5 +++-- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index d99734f7a4..0789e1fac2 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -63,6 +63,15 @@ var createToolsWindow = new CreateWindow( false ); +/** + * @description Returns true in case we should use the tablet version of the CreateApp + * @returns boolean + */ +var shouldUseEditTabletApp = function() { + return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true)); +}; + + var selectionDisplay = SelectionDisplay; var selectionManager = SelectionManager; @@ -88,11 +97,12 @@ var cameraManager = new CameraManager(); var grid = new Grid(); var gridTool = new GridTool({ horizontalGrid: grid, - createToolsWindow: createToolsWindow + createToolsWindow: createToolsWindow, + shouldUseEditTabletApp: shouldUseEditTabletApp }); gridTool.setVisible(false); -var entityListTool = new EntityListTool(); +var entityListTool = new EntityListTool(shouldUseEditTabletApp); selectionManager.addEventListener(function () { selectionDisplay.updateHandles(); @@ -578,7 +588,8 @@ var toolBar = (function () { }); createButton = activeButton; tablet.screenChanged.connect(function (type, url) { - var isGoingToHomescreenOnDesktop = (!HMD.active && (url === 'hifi/tablet/TabletHome.qml' || url === '')); + var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() && + (url === 'hifi/tablet/TabletHome.qml' || url === '')); if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml") && !isGoingToHomescreenOnDesktop) { that.setActive(false); } @@ -605,7 +616,7 @@ var toolBar = (function () { }); function createNewEntityDialogButtonCallback(entityType) { return function() { - if (HMD.active) { + if (shouldUseEditTabletApp()) { // tablet version of new-model dialog var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.pushOntoStack("hifi/tablet/New" + entityType + "Dialog.qml"); @@ -837,7 +848,7 @@ var toolBar = (function () { selectionDisplay.triggerMapping.disable(); tablet.landscape = false; } else { - if (HMD.active) { + if (shouldUseEditTabletApp()) { tablet.loadQMLSource("hifi/tablet/Edit.qml", true); } else { // make other apps inactive while in desktop mode @@ -1989,8 +2000,8 @@ var PropertiesTool = function (opts) { that.setVisible = function (newVisible) { visible = newVisible; - webView.setVisible(HMD.active && visible); - createToolsWindow.setVisible(!HMD.active && visible); + webView.setVisible(shouldUseEditTabletApp() && visible); + createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible); }; that.setVisible(false); @@ -2416,7 +2427,7 @@ function selectParticleEntity(entityID) { // Switch to particle explorer var selectTabMethod = { method: 'selectTab', params: { id: 'particle' } }; - if (HMD.active) { + if (shouldUseEditTabletApp()) { var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.sendToQml(selectTabMethod); } else { diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index ae89b63ea6..fb876302dd 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -11,7 +11,7 @@ /* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */ -EntityListTool = function() { +EntityListTool = function(shouldUseEditTabletApp) { var that = {}; var CreateWindow = Script.require('../modules/createWindow.js'); @@ -55,8 +55,8 @@ EntityListTool = function() { that.setVisible = function(newVisible) { visible = newVisible; - webView.setVisible(HMD.active && visible); - entityListWindow.setVisible(!HMD.active && visible); + webView.setVisible(shouldUseEditTabletApp() && visible); + entityListWindow.setVisible(!shouldUseEditTabletApp() && visible); }; that.setVisible(false); diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 669083a545..3a114f23c7 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -1,6 +1,6 @@ var GRID_CONTROLS_HTML_URL = Script.resolvePath('../html/gridControls.html'); -Grid = function(opts) { +Grid = function() { var that = {}; var gridColor = { red: 0, green: 0, blue: 0 }; var gridAlpha = 0.6; @@ -247,6 +247,7 @@ GridTool = function(opts) { var horizontalGrid = opts.horizontalGrid; var verticalGrid = opts.verticalGrid; var createToolsWindow = opts.createToolsWindow; + var shouldUseEditTabletApp = opts.shouldUseEditTabletApp; var listeners = []; var webView = null; @@ -299,7 +300,7 @@ GridTool = function(opts) { }; that.setVisible = function(visible) { - webView.setVisible(HMD.active && visible); + webView.setVisible(shouldUseEditTabletApp() && visible); }; return that; From ef4265de4bbcb70bbb5db1a1e5336b0b2143d55e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 17 Jul 2018 16:16:43 -0700 Subject: [PATCH 39/56] Fix MS16802: In Purchases, there shouldn't be a glyph associated with the Open button --- .../resources/qml/hifi/commerce/purchases/PurchasedItem.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 13dc3cb37f..0935f27388 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -731,7 +731,7 @@ Item { } HiFiGlyphs { id: rezIcon; - text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; + text: root.isInstalled ? "" : (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; anchors.right: rezIconLabel.left; anchors.rightMargin: 2; anchors.verticalCenter: parent.verticalCenter; @@ -750,7 +750,7 @@ Item { text: root.isInstalled ? "OPEN" : (MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]); anchors.verticalCenter: parent.verticalCenter; width: rezIconLabelTextMetrics.width; - x: parent.width/2 - rezIconLabelTextMetrics.width/2 + rezIconTextMetrics.width/2; + x: parent.width/2 - rezIconLabelTextMetrics.width/2 + (rezIcon.text === "" ? 0 : rezIconTextMetrics.width/2); size: 15; font.capitalization: Font.AllUppercase; verticalAlignment: Text.AlignVCenter; From fcb7614f7e4630cef397f5d32c82dcc644b10585 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 17 Jul 2018 16:34:30 -0700 Subject: [PATCH 40/56] Format and fixes --- interface/src/avatar/MyAvatar.cpp | 4 +-- interface/src/avatar/MyAvatar.h | 44 ++++++++++++++++++------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 094db72e0b..a5c426db41 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -272,11 +272,11 @@ void MyAvatar::requestEnableHandTouch() { emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0); } -void MyAvatar::disableHandTouchForID(const QString& entityID) { +void MyAvatar::disableHandTouchForID(const QUuid& entityID) { emit disableHandTouchForIDChanged(entityID, true); } -void MyAvatar::enableHandTouchForID(const QString& entityID) { +void MyAvatar::enableHandTouchForID(const QUuid& entityID) { emit disableHandTouchForIDChanged(entityID, false); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d125c8c3c5..1ca42c115d 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -506,23 +506,27 @@ public: */ Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } /**jsdoc - * @function MyAvatar.requestEnableHandTouch - */ + * Request to enable hand touch effect globally + * @function MyAvatar.requestEnableHandTouch + */ Q_INVOKABLE void requestEnableHandTouch(); /**jsdoc - * @function MyAvatar.requestDisableHandTouch - */ + * Request to disable hand touch effect globally + * @function MyAvatar.requestDisableHandTouch + */ Q_INVOKABLE void requestDisableHandTouch(); /**jsdoc - * @function MyAvatar.disableHandTouchForID - * @param {string} entityId - */ - Q_INVOKABLE void disableHandTouchForID(const QString& entityId); + * Disables hand touch effect on a specific entity + * @function MyAvatar.disableHandTouchForID + * @param {Uuid} entityID - ID of the entity that will disable hand touch effect + */ + Q_INVOKABLE void disableHandTouchForID(const QUuid& entityID); /**jsdoc - * @function MyAvatar.enableHandTouchForID - * @param {string} entityId - */ - Q_INVOKABLE void enableHandTouchForID(const QString& entityId); + * Enables hand touch effect on a specific entity + * @function MyAvatar.enableHandTouchForID + * @param {Uuid} entityID - ID of the entity that will enable hand touch effect + */ + Q_INVOKABLE void enableHandTouchForID(const QUuid& entityID); bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); } void setUseAdvancedMovementControls(bool useAdvancedMovementControls) @@ -1410,6 +1414,7 @@ signals: void scaleChanged(); /**jsdoc + * Triggered when hand touch is globally enable or disable * @function MyAvatar.shouldDisableHandTouchChanged * @param {boolean} shouldDisable * @returns {Signal} @@ -1417,12 +1422,13 @@ signals: void shouldDisableHandTouchChanged(bool shouldDisable); /**jsdoc - * @function MyAvatar.handTouchForIDChanged - * @param {string} entityID - * @param {boolean} disable - * @returns {Signal} - */ - void disableHandTouchForIDChanged(const QString& entityID, bool disable); + * Triggered when hand touch is enable or disable for an specific entity + * @function MyAvatar.disableHandTouchForIDChanged + * @param {Uuid} entityID + * @param {boolean} disable + * @returns {Signal} + */ + void disableHandTouchForIDChanged(const QUuid& entityID, bool disable); private slots: void leaveDomain(); @@ -1700,7 +1706,7 @@ private: bool _shouldLoadScripts { false }; bool _haveReceivedHeightLimitsFromDomain { false }; - int _disableHandTouchCount { 0 }; + std::atomic _disableHandTouchCount { 0 }; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); From 622543538547c37342893fa26d9e3863273ad26d Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 17 Jul 2018 16:38:34 -0700 Subject: [PATCH 41/56] some ortographic fixes --- 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 1ca42c115d..b2638e436c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1414,7 +1414,7 @@ signals: void scaleChanged(); /**jsdoc - * Triggered when hand touch is globally enable or disable + * Triggered when hand touch is globally enabled or disabled * @function MyAvatar.shouldDisableHandTouchChanged * @param {boolean} shouldDisable * @returns {Signal} @@ -1422,7 +1422,7 @@ signals: void shouldDisableHandTouchChanged(bool shouldDisable); /**jsdoc - * Triggered when hand touch is enable or disable for an specific entity + * Triggered when hand touch is enabled or disabled for an specific entity * @function MyAvatar.disableHandTouchForIDChanged * @param {Uuid} entityID * @param {boolean} disable From ba884f8a94f8fd74951f40e14b5954f77058e505 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 17 Jul 2018 16:42:59 -0700 Subject: [PATCH 42/56] Forgotten coment --- interface/src/avatar/MyAvatar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b2638e436c..6a1b889f86 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1424,7 +1424,7 @@ signals: /**jsdoc * Triggered when hand touch is enabled or disabled for an specific entity * @function MyAvatar.disableHandTouchForIDChanged - * @param {Uuid} entityID + * @param {Uuid} entityID - ID of the entity that will enable hand touch effect * @param {boolean} disable * @returns {Signal} */ From e3594fe1b7467d8f342c6bdfe43844df624541da Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 17 Jul 2018 17:23:03 -0700 Subject: [PATCH 43/56] mutex added --- interface/src/avatar/MyAvatar.cpp | 2 ++ interface/src/avatar/MyAvatar.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a5c426db41..bb7e57a7eb 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -263,11 +263,13 @@ void MyAvatar::setDominantHand(const QString& hand) { } void MyAvatar::requestDisableHandTouch() { + std::lock_guard guard(_disableHandTouchMutex); _disableHandTouchCount++; emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0); } void MyAvatar::requestEnableHandTouch() { + std::lock_guard guard(_disableHandTouchMutex); _disableHandTouchCount = std::max(_disableHandTouchCount - 1, 0); emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6a1b889f86..d3b9eef2de 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1666,6 +1666,7 @@ private: // all poses are in sensor-frame std::map _controllerPoseMap; mutable std::mutex _controllerPoseMapMutex; + mutable std::mutex _disableHandTouchMutex; bool _centerOfGravityModelEnabled { true }; bool _hmdLeanRecenterEnabled { true }; @@ -1706,7 +1707,7 @@ private: bool _shouldLoadScripts { false }; bool _haveReceivedHeightLimitsFromDomain { false }; - std::atomic _disableHandTouchCount { 0 }; + int _disableHandTouchCount { 0 }; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); From 919bfce7abbcbe8bbdff17e8cf42c1d5cc451fdc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 18 Jul 2018 09:00:01 -0700 Subject: [PATCH 44/56] Simplify --- .../resources/qml/hifi/commerce/purchases/PurchasedItem.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 0935f27388..b2338d08de 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -750,7 +750,7 @@ Item { text: root.isInstalled ? "OPEN" : (MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]); anchors.verticalCenter: parent.verticalCenter; width: rezIconLabelTextMetrics.width; - x: parent.width/2 - rezIconLabelTextMetrics.width/2 + (rezIcon.text === "" ? 0 : rezIconTextMetrics.width/2); + x: parent.width/2 - rezIconLabelTextMetrics.width/2 + rezIconTextMetrics.width/2; size: 15; font.capitalization: Font.AllUppercase; verticalAlignment: Text.AlignVCenter; From f7b49598b574f8514d4db667c3ad11553c76ac49 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Wed, 18 Jul 2018 09:50:59 -0700 Subject: [PATCH 45/56] Disabled tip boxes for Vive controllers, as per experience team request. --- scripts/system/controllers/viveControllerConfiguration.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/viveControllerConfiguration.js b/scripts/system/controllers/viveControllerConfiguration.js index dc4a5b6bb3..580d7dfd9a 100644 --- a/scripts/system/controllers/viveControllerConfiguration.js +++ b/scripts/system/controllers/viveControllerConfiguration.js @@ -77,7 +77,8 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { dimensions: viveNaturalDimensions, parts: { - tips: { + // DISABLED FOR NOW + /*tips: { type: "static", modelURL: viveTipsModelURL, naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323}, @@ -102,7 +103,7 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Teleport.png" } } - }, + },*/ // The touchpad type draws a dot indicating the current touch/thumb position // and swaps in textures based on the thumb position. @@ -215,6 +216,8 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { }, parts: { + // DISABLED FOR NOW + /* tips: { type: "static", modelURL: viveTipsModelURL, @@ -242,6 +245,7 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { } } }, + */ // The touchpad type draws a dot indicating the current touch/thumb position // and swaps in textures based on the thumb position. From a9eb8103f6dcd82dfe092157a88f53c3db5d7891 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Wed, 18 Jul 2018 09:52:25 -0700 Subject: [PATCH 46/56] Clean up comments a bit. --- scripts/system/controllers/viveControllerConfiguration.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/viveControllerConfiguration.js b/scripts/system/controllers/viveControllerConfiguration.js index 580d7dfd9a..60f0b6b88a 100644 --- a/scripts/system/controllers/viveControllerConfiguration.js +++ b/scripts/system/controllers/viveControllerConfiguration.js @@ -78,7 +78,8 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { parts: { // DISABLED FOR NOW - /*tips: { + /* + tips: { type: "static", modelURL: viveTipsModelURL, naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323}, @@ -103,7 +104,8 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Teleport.png" } } - },*/ + }, + */ // The touchpad type draws a dot indicating the current touch/thumb position // and swaps in textures based on the thumb position. From 0cbcae9181cb2564d5522bb7c5383739714c47e2 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 18 Jul 2018 10:44:37 -0700 Subject: [PATCH 47/56] reverting onLinkActivated brackets --- interface/resources/qml/LoginDialog/LinkAccountBody.qml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index fe971b31ee..814778a4b1 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -140,9 +140,7 @@ Item { horizontalAlignment: Text.AlignHCenter linkColor: hifi.colors.blueAccent - onLinkActivated: { - loginDialog.openUrl(link); - } + onLinkActivated: loginDialog.openUrl(link) } onFocusChanged: { root.text = ""; @@ -172,9 +170,7 @@ Item { horizontalAlignment: Text.AlignHCenter linkColor: hifi.colors.blueAccent - onLinkActivated: { - loginDialog.openUrl(link); - } + onLinkActivated: loginDialog.openUrl(link) } onFocusChanged: { From fe96ad23891c1177af1aa985d204f1d68c0648bf Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Wed, 18 Jul 2018 21:16:47 +0300 Subject: [PATCH 48/56] fix 'the drop down does not shows the wearable' --- interface/resources/qml/hifi/avatarapp/AdjustWearables.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml b/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml index 10613a9ec1..a501185853 100644 --- a/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml +++ b/interface/resources/qml/hifi/avatarapp/AdjustWearables.qml @@ -125,6 +125,7 @@ Rectangle { id: wearablesCombobox anchors.left: parent.left anchors.right: parent.right + comboBox.textRole: "text" model: ListModel { function findIndexById(id) { From b015845371c378cd6f7553339567e16cad06ac36 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 18 Jul 2018 11:34:37 -0700 Subject: [PATCH 49/56] Disable showing the entity edit tools when undoing while disabled --- scripts/system/edit.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 0789e1fac2..a173655e17 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1918,7 +1918,11 @@ function applyEntityProperties(data) { Entities.deleteEntity(entityID); } - selectionManager.setSelections(selectedEntityIDs); + // We might be getting an undo while edit.js is disabled. If that is the case, don't set + // our selections, causing the edit widgets to display. + if (isActive) { + selectionManager.setSelections(selectedEntityIDs); + } } // For currently selected entities, push a command to the UndoStack that uses the current entity properties for the From 0a47672d646cc233ab4b2d2ce10477cc3d2950f3 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 18 Jul 2018 13:00:03 -0700 Subject: [PATCH 50/56] machinery for fetching next page of inifinite scroll before it really needed, and use in our infinite scrolls --- interface/resources/qml/hifi/Feed.qml | 3 +- interface/resources/qml/hifi/Pal.qml | 10 +----- .../commerce/common/sendAsset/SendAsset.qml | 3 +- .../qml/hifi/commerce/purchases/Purchases.qml | 11 ++----- .../qml/hifi/commerce/wallet/WalletHome.qml | 7 +--- .../qml/hifi/models/PSFListModel.qml | 33 +++++++++++++++++-- 6 files changed, 37 insertions(+), 30 deletions(-) diff --git a/interface/resources/qml/hifi/Feed.qml b/interface/resources/qml/hifi/Feed.qml index 5f2dfea8c7..785b586dd2 100644 --- a/interface/resources/qml/hifi/Feed.qml +++ b/interface/resources/qml/hifi/Feed.qml @@ -53,7 +53,7 @@ Column { 'protocol=' + encodeURIComponent(Window.protocolSignature()) ]; endpoint: '/api/v1/user_stories?' + options.join('&'); - itemsPerPage: 3; + itemsPerPage: 4; processPage: function (data) { return data.user_stories.map(makeModelData); }; @@ -106,7 +106,6 @@ Column { highlightMoveDuration: -1; highlightMoveVelocity: -1; currentIndex: -1; - onAtXEndChanged: { if (scroll.atXEnd && !scroll.atXBeginning) { suggestions.getNextPage(); } } spacing: 12; width: parent.width; diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index c66ed1fe18..6884d2e1f6 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -61,7 +61,7 @@ Rectangle { 'username'; } sortAscending: connectionsTable.sortIndicatorOrder === Qt.AscendingOrder; - itemsPerPage: 9; + itemsPerPage: 10; listView: connectionsTable; processPage: function (data) { return data.users.map(function (user) { @@ -786,14 +786,6 @@ Rectangle { } model: connectionsUserModel; - Connections { - target: connectionsTable.flickableItem; - onAtYEndChanged: { - if (connectionsTable.flickableItem.atYEnd && !connectionsTable.flickableItem.atYBeginning) { - connectionsUserModel.getNextPage(); - } - } - } // This Rectangle refers to each Row in the connectionsTable. rowDelegate: Rectangle { diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 3e4bae4780..a515c8031f 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -398,7 +398,7 @@ Item { http: root.http; listModelName: root.listModelName; endpoint: "/api/v1/users?filter=connections"; - itemsPerPage: 8; + itemsPerPage: 9; listView: connectionsList; processPage: function (data) { return data.users; @@ -520,7 +520,6 @@ Item { visible: !connectionsLoading.visible; clip: true; model: connectionsModel; - onAtYEndChanged: if (connectionsList.atYEnd && !connectionsList.atYBeginning) { connectionsModel.getNextPage(); } snapMode: ListView.SnapToItem; // Anchors anchors.fill: parent; diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 91993d0fa3..3569ce6767 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -551,8 +551,9 @@ Rectangle { HifiModels.PSFListModel { id: purchasesModel; - itemsPerPage: 6; + itemsPerPage: 7; listModelName: 'purchases'; + listView: purchasesContentsList; getPage: function () { console.debug('getPage', purchasesModel.listModelName, root.isShowingMyItems, filterBar.primaryFilter_filterName, purchasesModel.currentPageToRetrieve, purchasesModel.itemsPerPage); Commerce.inventory( @@ -781,14 +782,6 @@ Rectangle { } } } - - - onAtYEndChanged: { - if (purchasesContentsList.atYEnd && !purchasesContentsList.atYBeginning) { - console.log("User scrolled to the bottom of 'Purchases'."); - purchasesModel.getNextPage(); - } - } } Rectangle { diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 3e0a56b4c5..a0c6057b3b 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -212,6 +212,7 @@ Item { HifiModels.PSFListModel { id: transactionHistoryModel; listModelName: "transaction history"; // For debugging. Alternatively, we could specify endpoint for that purpose, even though it's not used directly. + listView: transactionHistory; itemsPerPage: 6; getPage: function () { console.debug('getPage', transactionHistoryModel.listModelName, transactionHistoryModel.currentPageToRetrieve); @@ -346,12 +347,6 @@ Item { } } } - onAtYEndChanged: { - if (transactionHistory.atYEnd && !transactionHistory.atYBeginning) { - console.log("User scrolled to the bottom of 'Recent Activity'."); - transactionHistoryModel.getNextPage(); - } - } } Item { diff --git a/interface/resources/qml/hifi/models/PSFListModel.qml b/interface/resources/qml/hifi/models/PSFListModel.qml index 19f1a3e173..988502dd91 100644 --- a/interface/resources/qml/hifi/models/PSFListModel.qml +++ b/interface/resources/qml/hifi/models/PSFListModel.qml @@ -33,7 +33,6 @@ ListModel { // QML fires the following changed handlers even when first instantiating the Item. So we need a guard against firing them too early. property bool initialized: false; - Component.onCompleted: initialized = true; onEndpointChanged: if (initialized) { getFirstPage('delayClear'); } onSortKeyChanged: if (initialized) { getFirstPage('delayClear'); } onSearchFilterChanged: if (initialized) { getFirstPage('delayClear'); } @@ -60,7 +59,37 @@ ListModel { // Override to return one property of data, and/or to transform the elements. Must return an array of model elements. property var processPage: function (data) { return data; } - property var listView; // Optional. For debugging. + property var listView; // Optional. For debugging, or for having the scroll handler automatically call getNextPage. + property var flickable: listView && (listView.flickableItem || listView); + // 2: get two pages before you need it (i.e. one full page before you reach the end). + // 1: equivalent to paging when reaching end (and not before). + // 0: don't getNextPage on scroll at all here. The application code will do it. + property real pageAhead: 2.0; + function needsEarlyYFetch() { + return flickable + && !flickable.atYBeginning + && (flickable.contentY - flickable.originY) >= (flickable.contentHeight - (pageAhead * flickable.height)); + } + function needsEarlyXFetch() { + return flickable + && !flickable.atXBeginning + && (flickable.contentX - flickable.originX) >= (flickable.contentWidth - (pageAhead * flickable.width)); + } + function getNextPageIfHorizontalScroll() { + if (needsEarlyXFetch()) { getNextPage(); } + } + function getNextPageIfVerticalScroll() { + if (needsEarlyYFetch()) { getNextPage(); } + } + Component.onCompleted: { + initialized = true; + if (flickable && pageAhead > 0.0) { + // Pun: Scrollers are usually one direction or another, such that only one of the following will actually fire. + flickable.contentXChanged.connect(getNextPageIfHorizontalScroll); + flickable.contentYChanged.connect(getNextPageIfVerticalScroll); + } + } + property int totalPages: 0; property int totalEntries: 0; // Check consistency and call processPage. From 446ef97fc57f3cf8c37b34e4a79d18f0e20ef4de Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 18 Jul 2018 13:54:03 -0700 Subject: [PATCH 51/56] Only show overlay if textures have loaded --- interface/src/ui/overlays/ModelOverlay.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index f4289b1bf5..f47172eb55 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -136,6 +136,9 @@ void ModelOverlay::update(float deltatime) { } _model->updateRenderItems(); } + + // Only show overlay if textures have loaded + _model->setVisibleInScene(_texturesLoaded, scene); } bool ModelOverlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { From a904182cc2ca7cac9b6a3feb3c92e4136872c427 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 18 Jul 2018 14:03:26 -0700 Subject: [PATCH 52/56] cr feedback --- scripts/modules/appUi.js | 20 +++++++++++++------- scripts/system/pal.js | 3 +-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/scripts/modules/appUi.js b/scripts/modules/appUi.js index 7b6169e623..db81af3755 100644 --- a/scripts/modules/appUi.js +++ b/scripts/modules/appUi.js @@ -20,7 +20,8 @@ function AppUi(properties) { remove button.clicked.[dis]connect and tablet.remove(button).) 4. Define onOpened and onClosed behavior in #3, if any. (And if converting an existing app, remove screenChanged.[dis]connect.) - 5. Define onMessage and sendMessage in #3, if any. + 5. Define onMessage and sendMessage in #3, if any. onMessage is wired/unwired on open/close. If you + want a handler to be "always on", connect it yourself at script startup. (And if converting an existing app, remove code that [un]wires that message handling such as fromQml/sendToQml or webEventReceived/emitScriptEvent.) 6. (If converting an existing app, cleanup stuff that is no longer necessary, like references to button, tablet, @@ -38,16 +39,23 @@ function AppUi(properties) { that.inject = ""; that.graphicsDirectory = "icons/tablet-icons/"; // Where to look for button svgs. See below. that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen. - return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix. + return (type === that.type) && that.currentUrl && (tabletUrl.indexOf(that.currentUrl) >= 0); // Actual url may have prefix or suffix. }; - that.open = function open() { // How to open the app. + that.setCurrentData = function setCurrentData(url) { + that.currentUrl = url; + that.type = /.qml$/.test(url) ? 'QML' : 'Web'; + } + that.open = function open(optionalUrl) { // How to open the app. + var url = optionalUrl || that.home; + that.setCurrentData(url); if (that.isQML()) { - that.tablet.loadQMLSource(that.home); + that.tablet.loadQMLSource(url); } else { - that.tablet.gotoWebScreen(that.home, that.inject); + that.tablet.gotoWebScreen(url, that.inject); } }; that.close = function close() { // How to close the app. + that.currentUrl = ""; // for toolbar-mode: go back to home screen, this will close the window. that.tablet.gotoHomeScreen(); }; @@ -122,7 +130,6 @@ function AppUi(properties) { // Uniquivocally sets that.sendMessage(messageObject) to do the right thing. // Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined. var handler, isQml = that.isQML(); - console.debug(that.buttonName, 'wireEventBridge', on, that.hasEventBridge); // Outbound (always, regardless of whether there is an inbound handler). if (on) { that.sendMessage = isQml ? that.tablet.sendToQml : that.sendToHtml; @@ -156,7 +163,6 @@ function AppUi(properties) { if (that.isOpen) { that.close(); } else { - that.type = /.qml$/.test(that.home) ? 'QML' : 'Web'; that.open(); } } : that.ignore; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index b6b11837e1..9485b8b49a 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -315,8 +315,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See return; } getConnectionData(friendUserName); - } - ); + }); break; case 'http.request': break; // Handled by request-service. From a882931c6bf2728c7a557d5b63ebe6166d1915f4 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 18 Jul 2018 15:02:02 -0700 Subject: [PATCH 53/56] Only show overlay if textures have loaded --- interface/src/ui/overlays/ModelOverlay.cpp | 26 ++++++++++++---------- interface/src/ui/overlays/ModelOverlay.h | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index f47172eb55..dbb0b23558 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -27,6 +27,11 @@ ModelOverlay::ModelOverlay() { _model->setLoadingPriority(_loadPriority); _isLoaded = false; + + _scene = qApp->getMain3DScene(); + + // Don't show overlay until textures have loaded + _model->setVisibleInScene(false, _scene); } ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) : @@ -85,12 +90,11 @@ void ModelOverlay::update(float deltatime) { // check to see if when we added our model to the scene they were ready, if they were not ready, then // fix them up in the scene - render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; if (_model->needsFixupInScene()) { emit DependencyManager::get()->modelRemovedFromScene(getID(), NestableType::Overlay, _model); - _model->removeFromScene(scene, transaction); - _model->addToScene(scene, transaction); + _model->removeFromScene(_scene, transaction); + _model->addToScene(_scene, transaction); auto newRenderItemIDs{ _model->fetchRenderItemIDs() }; transaction.updateItem(getRenderItemID(), [newRenderItemIDs](Overlay& data) { @@ -105,40 +109,38 @@ void ModelOverlay::update(float deltatime) { _visibleDirty = false; // don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true uint8_t modelRenderTagMask = (_isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW); - _model->setTagMask(modelRenderTagMask, scene); - _model->setVisibleInScene(getVisible(), scene); + _model->setTagMask(modelRenderTagMask, _scene); metaDirty = true; } if (_drawInFrontDirty) { _drawInFrontDirty = false; - _model->setLayeredInFront(getDrawInFront(), scene); + _model->setLayeredInFront(getDrawInFront(), _scene); metaDirty = true; } if (_drawInHUDDirty) { _drawInHUDDirty = false; - _model->setLayeredInHUD(getDrawHUDLayer(), scene); + _model->setLayeredInHUD(getDrawHUDLayer(), _scene); metaDirty = true; } if (_groupCulledDirty) { _groupCulledDirty = false; - _model->setGroupCulled(_isGroupCulled, scene); + _model->setGroupCulled(_isGroupCulled, _scene); metaDirty = true; } if (metaDirty) { transaction.updateItem(getRenderItemID(), [](Overlay& data) {}); } - scene->enqueueTransaction(transaction); + _scene->enqueueTransaction(transaction); if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) { _texturesLoaded = true; if (!_modelTextures.isEmpty()) { _model->setTextures(_modelTextures); } + + _model->setVisibleInScene(true, _scene); _model->updateRenderItems(); } - - // Only show overlay if textures have loaded - _model->setVisibleInScene(_texturesLoaded, scene); } bool ModelOverlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index f7a79c5615..9b5a8e2ec1 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -128,6 +128,7 @@ private: void processMaterials(); + render::ScenePointer _scene; }; #endif // hifi_ModelOverlay_h From 499aa4ad13b3993ea46682062bd7f3e1a61676cd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Jul 2018 15:17:19 -0700 Subject: [PATCH 54/56] 404 malformed agent script requests, check doc root --- domain-server/src/DomainServer.cpp | 9 +++-- .../embedded-webserver/src/HTTPManager.cpp | 34 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index eccd1c1e20..86a9a58058 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1916,14 +1916,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url // don't handle if we don't have a matching node if (!matchingNode) { - return false; + connection->respond(HTTPConnection::StatusCode404, "Resource not found."); + return true; } auto nodeData = static_cast(matchingNode->getLinkedData()); // don't handle if we don't have node data for this node if (!nodeData) { - return false; + connection->respond(HTTPConnection::StatusCode404, "Resource not found."); + return true; } SharedAssignmentPointer matchingAssignment = _allAssignments.value(nodeData->getAssignmentUUID()); @@ -1944,7 +1946,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } // request not handled - return false; + connection->respond(HTTPConnection::StatusCode404, "Resource not found."); + return true; } // check if this is a request for our domain ID diff --git a/libraries/embedded-webserver/src/HTTPManager.cpp b/libraries/embedded-webserver/src/HTTPManager.cpp index 4a75994e12..ccebeaf9cc 100644 --- a/libraries/embedded-webserver/src/HTTPManager.cpp +++ b/libraries/embedded-webserver/src/HTTPManager.cpp @@ -48,6 +48,13 @@ void HTTPManager::incomingConnection(qintptr socketDescriptor) { } bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) { + // Reject paths with embedded NULs + if (url.path().contains(QChar(0x00))) { + connection->respond(HTTPConnection::StatusCode400, "Embedded NULs not allowed in requests"); + qCWarning(embeddedwebserver) << "Received a request with embedded NULs"; + return true; + } + if (!skipSubHandler && requestHandledByRequestHandler(connection, url)) { // this request was handled by our request handler object // so we don't need to attempt to do so in the document root @@ -57,17 +64,27 @@ bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, if (!_documentRoot.isEmpty()) { // check to see if there is a file to serve from the document root for this path QString subPath = url.path(); - + // remove any slash at the beginning of the path if (subPath.startsWith('/')) { subPath.remove(0, 1); } - + + QString absoluteDocumentRoot { QFileInfo(_documentRoot).absolutePath() }; QString filePath; - - if (QFileInfo(_documentRoot + subPath).isFile()) { - filePath = _documentRoot + subPath; - } else if (subPath.size() > 0 && !subPath.endsWith('/')) { + QFileInfo pathFileInfo { _documentRoot + subPath }; + QString absoluteFilePath { pathFileInfo.absoluteFilePath() }; + + // The absolute path for this file isn't under the document root + if (absoluteFilePath.indexOf(absoluteDocumentRoot) != 0) { + qCWarning(embeddedwebserver) << absoluteFilePath << "is outside the document root"; + connection->respond(HTTPConnection::StatusCode400, "Requested path outside document root"); + return true; + } + + if (pathFileInfo.isFile()) { + filePath = absoluteFilePath; + } else if (subPath.size() > 0 && !subPath.endsWith('/') && pathFileInfo.isDir()) { // this could be a directory with a trailing slash // send a redirect to the path with a slash so we can QString redirectLocation = '/' + subPath + '/'; @@ -80,6 +97,7 @@ bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, redirectHeader.insert(QByteArray("Location"), redirectLocation.toUtf8()); connection->respond(HTTPConnection::StatusCode302, "", HTTPConnection::DefaultContentType, redirectHeader); + return true; } // if the last thing is a trailing slash then we want to look for index file @@ -87,8 +105,8 @@ bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, QStringList possibleIndexFiles = QStringList() << "index.html" << "index.shtml"; foreach (const QString& possibleIndexFilename, possibleIndexFiles) { - if (QFileInfo(_documentRoot + subPath + possibleIndexFilename).exists()) { - filePath = _documentRoot + subPath + possibleIndexFilename; + if (QFileInfo(absoluteFilePath + possibleIndexFilename).exists()) { + filePath = absoluteFilePath + possibleIndexFilename; break; } } From 4c0b7ca24cf5581ccd9e322b267b903ba1dd8fa2 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 18 Jul 2018 17:30:46 -0700 Subject: [PATCH 55/56] Updated per Samuel's/Austin's comments. --- interface/src/ui/overlays/ModelOverlay.cpp | 28 ++++++++++++---------- interface/src/ui/overlays/ModelOverlay.h | 1 - 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index dbb0b23558..71354002ea 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -28,10 +28,11 @@ ModelOverlay::ModelOverlay() _model->setLoadingPriority(_loadPriority); _isLoaded = false; - _scene = qApp->getMain3DScene(); - // Don't show overlay until textures have loaded - _model->setVisibleInScene(false, _scene); + _visible = false; + + render::ScenePointer scene = qApp->getMain3DScene(); + _model->setVisibleInScene(false, scene); } ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) : @@ -90,11 +91,12 @@ void ModelOverlay::update(float deltatime) { // check to see if when we added our model to the scene they were ready, if they were not ready, then // fix them up in the scene + render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; if (_model->needsFixupInScene()) { emit DependencyManager::get()->modelRemovedFromScene(getID(), NestableType::Overlay, _model); - _model->removeFromScene(_scene, transaction); - _model->addToScene(_scene, transaction); + _model->removeFromScene(scene, transaction); + _model->addToScene(scene, transaction); auto newRenderItemIDs{ _model->fetchRenderItemIDs() }; transaction.updateItem(getRenderItemID(), [newRenderItemIDs](Overlay& data) { @@ -105,32 +107,34 @@ void ModelOverlay::update(float deltatime) { emit DependencyManager::get()->modelAddedToScene(getID(), NestableType::Overlay, _model); } bool metaDirty = false; - if (_visibleDirty) { + if (_visibleDirty && _texturesLoaded) { _visibleDirty = false; // don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true uint8_t modelRenderTagMask = (_isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW); - _model->setTagMask(modelRenderTagMask, _scene); + + _model->setTagMask(modelRenderTagMask, scene); + _model->setVisibleInScene(getVisible(), scene); metaDirty = true; } if (_drawInFrontDirty) { _drawInFrontDirty = false; - _model->setLayeredInFront(getDrawInFront(), _scene); + _model->setLayeredInFront(getDrawInFront(), scene); metaDirty = true; } if (_drawInHUDDirty) { _drawInHUDDirty = false; - _model->setLayeredInHUD(getDrawHUDLayer(), _scene); + _model->setLayeredInHUD(getDrawHUDLayer(), scene); metaDirty = true; } if (_groupCulledDirty) { _groupCulledDirty = false; - _model->setGroupCulled(_isGroupCulled, _scene); + _model->setGroupCulled(_isGroupCulled, scene); metaDirty = true; } if (metaDirty) { transaction.updateItem(getRenderItemID(), [](Overlay& data) {}); } - _scene->enqueueTransaction(transaction); + scene->enqueueTransaction(transaction); if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) { _texturesLoaded = true; @@ -138,7 +142,7 @@ void ModelOverlay::update(float deltatime) { _model->setTextures(_modelTextures); } - _model->setVisibleInScene(true, _scene); + _model->setVisibleInScene(getVisible(), scene); _model->updateRenderItems(); } } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 9b5a8e2ec1..f7a79c5615 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -128,7 +128,6 @@ private: void processMaterials(); - render::ScenePointer _scene; }; #endif // hifi_ModelOverlay_h From 63fa54ceda12a29fb799cd2d35e9c44959069bd3 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 18 Jul 2018 14:54:19 -0700 Subject: [PATCH 56/56] Fix for audio continuing on destroyed Web 3D overlays --- interface/src/ui/overlays/Web3DOverlay.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index a8a82c74b7..fbea492d1d 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -138,11 +138,8 @@ void Web3DOverlay::destroyWebSurface() { // Fix for crash in QtWebEngineCore when rapidly switching domains // Call stop on the QWebEngineView before destroying OffscreenQMLSurface. if (rootItem) { - QObject* obj = rootItem->findChild("webEngineView"); - if (obj) { - // stop loading - QMetaObject::invokeMethod(obj, "stop"); - } + // stop loading + QMetaObject::invokeMethod(rootItem, "stop"); } _webSurface->pause(); @@ -152,6 +149,11 @@ void Web3DOverlay::destroyWebSurface() { // If the web surface was fetched out of the cache, release it back into the cache if (_cachedWebSurface) { + // If it's going back into the cache make sure to explicitly set the URL to a blank page + // in order to stop any resource consumption or audio related to the page. + if (rootItem) { + rootItem->setProperty("url", "about:blank"); + } auto offscreenCache = DependencyManager::get(); // FIXME prevents crash on shutdown, but we shoudln't have to do this check if (offscreenCache) {