From 15bdb66943c664a3c8f3f32101083527abaa9804 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 17 May 2019 17:25:48 -0700 Subject: [PATCH 01/40] Integrate Status into top bar; improve Audio settings; improve spacing between settings --- .../simplifiedUI/settingsApp/audio/Audio.qml | 12 +- .../settingsApp/general/General.qml | 7 +- .../hifi/simplifiedUI/settingsApp/vr/VR.qml | 9 +- .../SimplifiedConstants.qml | 7 +- .../simplifiedControls/RadioButton.qml | 2 +- .../simplifiedUI/topBar/SimplifiedTopBar.qml | 54 ++++ .../simplifiedUI/topBar/images/status.svg | 3 + .../simplifiedStatusIndicator.js | 244 ++++++++++++++++++ scripts/system/simplifiedUI/simplifiedUI.js | 32 +++ 9 files changed, 356 insertions(+), 14 deletions(-) create mode 100644 interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg create mode 100644 scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml index 840a2bb69a..da924615e3 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml @@ -19,8 +19,8 @@ Flickable { id: root contentWidth: parent.width contentHeight: audioColumnLayout.height - topMargin: 16 - bottomMargin: 16 + topMargin: 24 + bottomMargin: 24 clip: true function changePeakValuesEnabled(enabled) { @@ -189,7 +189,7 @@ Flickable { Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin interactive: false height: contentItem.height - spacing: 4 + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons clip: true model: AudioScriptingInterface.devices.input delegate: Item { @@ -200,6 +200,8 @@ Flickable { id: inputDeviceCheckbox anchors.left: parent.left width: parent.width - inputLevel.width + height: paintedHeight + wrapLabel: false checked: selectedDesktop text: model.devicename ButtonGroup.group: inputDeviceButtonGroup @@ -288,7 +290,7 @@ Flickable { Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin interactive: false height: contentItem.height - spacing: 4 + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons clip: true model: AudioScriptingInterface.devices.output delegate: Item { @@ -299,8 +301,10 @@ Flickable { id: outputDeviceCheckbox anchors.left: parent.left width: parent.width + height: paintedHeight checked: selectedDesktop text: model.devicename + wrapLabel: false ButtonGroup.group: outputDeviceButtonGroup onClicked: { AudioScriptingInterface.setOutputDevice(model.info, false); // `false` argument for Desktop mode setting diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml index de5e75b7e5..e32890a2dd 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml @@ -20,8 +20,8 @@ Flickable { id: root contentWidth: parent.width contentHeight: generalColumnLayout.height - topMargin: 16 - bottomMargin: 16 + topMargin: 24 + bottomMargin: 24 clip: true onAvatarNametagModeChanged: { @@ -63,6 +63,7 @@ Flickable { ColumnLayout { id: avatarNameTagsRadioButtonGroup Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons SimplifiedControls.RadioButton { id: avatarNameTagsOff @@ -110,6 +111,7 @@ Flickable { ColumnLayout { id: performanceRadioButtonGroup Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons SimplifiedControls.RadioButton { id: performanceLow @@ -157,6 +159,7 @@ Flickable { ColumnLayout { id: cameraRadioButtonGroup Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons SimplifiedControls.RadioButton { id: firstPerson diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml index a462af0722..96dbc5e180 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml @@ -19,8 +19,8 @@ Flickable { id: root contentWidth: parent.width contentHeight: vrColumnLayout.height - topMargin: 16 - bottomMargin: 16 + topMargin: 24 + bottomMargin: 24 clip: true function changePeakValuesEnabled(enabled) { @@ -70,6 +70,7 @@ Flickable { id: controlsRadioButtonGroup width: parent.width Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons ButtonGroup { id: controlsButtonGroup } @@ -202,7 +203,7 @@ Flickable { Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin interactive: false height: contentItem.height - spacing: 4 + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons clip: true model: AudioScriptingInterface.devices.input delegate: Item { @@ -301,7 +302,7 @@ Flickable { Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin interactive: false height: contentItem.height - spacing: 4 + spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons clip: true model: AudioScriptingInterface.devices.output delegate: Item { diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml index 5ccc1a7e5c..5d71d8bdb2 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml @@ -182,9 +182,10 @@ QtObject { } readonly property QtObject settings: QtObject { - property real subtitleTopMargin: 2 - property real settingsGroupTopMargin: 10 - property real spacingBetweenSettings: 48 + property int subtitleTopMargin: 2 + property int settingsGroupTopMargin: 24 + property int spacingBetweenSettings: 48 + property int spacingBetweenRadiobuttons: 14 } } diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/RadioButton.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/RadioButton.qml index 59c4fa26e4..43d4aaee33 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/RadioButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/RadioButton.qml @@ -87,7 +87,6 @@ RadioButton { contentItem: Text { id: radioButtonLabel - height: root.radioButtonRadius font.pixelSize: 14 font.family: "Graphik" font.weight: Font.Normal @@ -99,5 +98,6 @@ RadioButton { enabled: root.enabled verticalAlignment: Text.AlignVCenter leftPadding: radioButtonIndicator.width + root.labelLeftMargin + topPadding: -3 // For perfect alignment when using Graphik } } diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 09873396fa..ae50a746b6 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -242,6 +242,56 @@ Rectangle { } + Item { + id: statusButtonContainer + anchors.verticalCenter: parent.verticalCenter + anchors.left: outputDeviceButtonContainer.right + anchors.leftMargin: 2 + width: 32 + height: width + + Rectangle { + id: statusButton + property string currentStatus: "" + anchors.centerIn: parent + width: 20 + height: width + radius: width/2 + visible: false + } + + ColorOverlay { + anchors.fill: statusButton + opacity: statusButtonMouseArea.containsMouse ? 1.0 : 0.7 + source: statusButton + color: if (statusButton.currentStatus === "busy") { + "red" + } else if (statusButton.currentStatus === "available") { + "green" + } else { + "yellow" + } + } + + MouseArea { + id: statusButtonMouseArea + anchors.fill: parent + hoverEnabled: true + onEntered: { + Tablet.playSound(TabletEnums.ButtonHover); + } + onClicked: { + Tablet.playSound(TabletEnums.ButtonClick); + + sendToScript({ + "source": "SimplifiedTopBar.qml", + "method": "toggleStatus" + }); + } + } + } + + Item { id: hmdButtonContainer @@ -401,6 +451,10 @@ Rectangle { outputDeviceButton.outputMuted = message.data.outputMuted; break; + case "updateStatusButton": + statusButton.currentStatus = message.data.currentStatus; + break; + default: console.log('SimplifiedTopBar.qml: Unrecognized message from JS'); break; diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg new file mode 100644 index 0000000000..ebd844c471 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg @@ -0,0 +1,3 @@ + + + diff --git a/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js new file mode 100644 index 0000000000..a56e9f3a24 --- /dev/null +++ b/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -0,0 +1,244 @@ +// +// simplifiedStatusIndicator.js +// +// Created by Robin Wilson on 2019-05-17 +// Copyright 2019 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 simplifiedStatusIndicator(properties) { + var that = this; + var DEBUG = false; + + // #region HEARTBEAT + + // Send heartbeat with updates to database + // When this stops, the database will set status to offline + var HEARTBEAT_TIMEOUT_MS = 5000, + heartbeat; + function startHeartbeatTimer() { + if (heartbeat) { + Script.clearTimeout(heartbeat); + heartbeat = false; + } + + heartbeat = Script.setTimeout(function() { + heartbeat = false; + getStatus(setStatus); + }, HEARTBEAT_TIMEOUT_MS); + } + + // #endregion HEARTBEAT + + + // #region SEND/GET STATUS REQUEST + + function setStatusExternally(newStatus) { + if (!newStatus) { + return; + } + + setStatus(newStatus); + } + + + var request = Script.require('request').request, + REQUEST_URL = "https://highfidelity.co/api/statusIndicator/"; + function setStatus(newStatus) { + if (heartbeat) { + Script.clearTimeout(heartbeat); + heartbeat = false; + } + + if (newStatus && currentStatus !== newStatus) { + currentStatus = newStatus; + that.statusChanged(); + } + + var displayNameToSend = MyAvatar.sessionDisplayName; + queryParamString += currentStatus; + if (displayNameToSend === "") { + displayNameToSend = MyAvatar.displayName; + } + + var queryParamString = "type=heartbeat"; + queryParamString += "&username=" + AccountServices.username; + queryParamString += "&displayName=" + displayNameToSend; + queryParamString += "&status="; + queryParamString += currentStatus; + + var uri = REQUEST_URL + "?" + queryParamString; + + if (DEBUG) { + console.log("setStatus: " + uri); + } + + request({ + uri: uri + }, function (error, response) { + startHeartbeatTimer(); + + if (error || !response || response.status !== "success") { + console.error("Error with setStatus: " + JSON.stringify(response)); + return; + } + }); + } + + // Get status from database + function getStatus(callback) { + var queryParamString = "type=getStatus"; + queryParamString += "&username=" + AccountServices.username; + + var uri = REQUEST_URL + "?" + queryParamString; + + if (DEBUG) { + console.log("getStatus: " + uri); + } + + request({ + uri: uri + }, function (error, response) { + if (error || !response || response.status !== "success") { + console.error("Error with getStatus: " + JSON.stringify(response)); + } else if (response.data.userStatus.toLowerCase() !== "offline") { + if (response.data.userStatus !== currentStatus) { + currentStatus = response.data.userStatus; + that.statusChanged(); + } + } + + if (callback) { + callback(); + } + }); + } + + + function getLocalStatus() { + return currentStatus; + } + + // #endregion SEND/GET STATUS REQUEST + + + // #region SIGNALS + + var currentStatus = "available"; // Default is available + function toggleStatus() { + if (currentStatus === "busy") { + currentStatus = "available"; + // Else if current status is "available" OR anything else (custom) + } else { + currentStatus = "busy"; + } + + that.statusChanged(); + + setStatus(); + } + + + // When avatar becomes active from being away + // Set status back to previousStatus + function onWentActive() { + if (currentStatus !== previousStatus) { + currentStatus = previousStatus; + that.statusChanged(); + } + setStatus(); + } + + + // When avatar goes away, set status to busy + var previousStatus; + function onWentAway() { + previousStatus = currentStatus; + if (currentStatus !== "busy") { + currentStatus = "busy"; + that.statusChanged(); + } + setStatus(); + } + + + // Domain changed update avatar location + function onDomainChanged() { + var queryParamString = "type=updateEmployee"; + queryParamString += "&username=" + AccountServices.username; + queryParamString += "&location=unknown"; + + var uri = REQUEST_URL + "?" + queryParamString; + + if (DEBUG) { + console.log("simplifiedStatusIndicator onDomainChanged: " + uri); + } + + request({ + uri: uri + }, function (error, response) { + if (error || !response || response.status !== "success") { + console.error("Error with onDomainChanged: " + JSON.stringify(response)); + } else { + // successfully sent updateLocation + if (DEBUG) { + console.log("Successfully updated location after domain change."); + } + } + }); + } + + + function statusChanged() { + + } + + // #endregion SIGNALS + + + // #region APP LIFETIME + + // Creates the app button and sets up signals and hearbeat + function startup() { + MyAvatar.wentAway.connect(onWentAway); + MyAvatar.wentActive.connect(onWentActive); + MyAvatar.displayNameChanged.connect(setStatus); + Window.domainChanged.connect(onDomainChanged); + + getStatus(setStatus); + } + + + // Cleans up timeouts, signals, and overlays + function unload() { + MyAvatar.wentAway.disconnect(onWentAway); + MyAvatar.wentActive.disconnect(onWentActive); + MyAvatar.displayNameChanged.disconnect(setStatus); + Window.domainChanged.disconnect(onDomainChanged); + if (heartbeat) { + Script.clearTimeout(heartbeat); + heartbeat = false; + } + } + + // #endregion APP LIFETIME + + that.startup = startup; + that.unload = unload; + that.toggleStatus = toggleStatus; + that.setStatus = setStatus; + that.getLocalStatus = getLocalStatus; + that.statusChanged = statusChanged; + + // Overwrite with the given properties + var overwriteableKeys = ["statusChanged"]; + Object.keys(properties).forEach(function (key) { + if (overwriteableKeys.indexOf(key) > -1) { + that[key] = properties[key]; + } + }); +} + +module.exports = simplifiedStatusIndicator; \ No newline at end of file diff --git a/scripts/system/simplifiedUI/simplifiedUI.js b/scripts/system/simplifiedUI/simplifiedUI.js index c3556a1fbf..f208fcaf1e 100644 --- a/scripts/system/simplifiedUI/simplifiedUI.js +++ b/scripts/system/simplifiedUI/simplifiedUI.js @@ -276,6 +276,11 @@ function setOutputMuted(outputMuted) { } +function toggleStatus() { + +} + + var TOP_BAR_MESSAGE_SOURCE = "SimplifiedTopBar.qml"; function onMessageFromTopBar(message) { if (message.source !== TOP_BAR_MESSAGE_SOURCE) { @@ -295,6 +300,10 @@ function onMessageFromTopBar(message) { setOutputMuted(message.data.outputMuted); break; + case "toggleStatus": + si.toggleStatus(); + break; + default: console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message)); break; @@ -435,7 +444,25 @@ function ensureFirstPersonCameraInHMD(isHMDMode) { } } + +function onStatusChanged() { + var currentStatus = si.getLocalStatus(); + + if (topBarWindow) { + topBarWindow.sendToQml({ + "source": "simplifiedUI.js", + "method": "updateStatusButton", + "data": { + "currentStatus": currentStatus + } + }); + } +} + + var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js"); +var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js"); +var si; var oldShowAudioTools; var oldShowBubbleTools; var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false); @@ -456,6 +483,10 @@ function startup() { loadSimplifiedTopBar(); simplifiedNametag.create(); + si = new SimplifiedStatusIndicator({ + statusChanged: onStatusChanged + }); + si.startup(); updateInputDeviceMutedOverlay(Audio.muted); updateOutputDeviceMutedOverlay(isOutputMuted()); Audio.mutedDesktopChanged.connect(onDesktopInputDeviceMutedChanged); @@ -506,6 +537,7 @@ function shutdown() { maybeDeleteOutputDeviceMutedOverlay(); simplifiedNametag.destroy(); + si.unload(); Audio.mutedDesktopChanged.disconnect(onDesktopInputDeviceMutedChanged); Window.geometryChanged.disconnect(onGeometryChanged); From 2e666836c716ba99aa50c13b64e4cc5918dc4a8a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 20 May 2019 13:42:53 -0700 Subject: [PATCH 02/40] add more options to render scripting interface --- interface/src/Menu.cpp | 50 ++-------- .../scripting/RenderScriptingInterface.cpp | 94 +++++++++++++++++-- .../src/scripting/RenderScriptingInterface.h | 52 +++++++++- .../render-utils/src/AntialiasingEffect.h | 2 - 4 files changed, 144 insertions(+), 54 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9341b2316c..5880076358 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -49,16 +49,13 @@ #include "DeferredLightingEffect.h" #include "PickManager.h" -#include "LightingModel.h" -#include "AmbientOcclusionEffect.h" -#include "RenderShadowTask.h" -#include "AntialiasingEffect.h" - #include "scripting/SettingsScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" #endif +#include "scripting/RenderScriptingInterface.h" + extern bool DEV_DECIMATE_TEXTURES; Menu* Menu::getInstance() { @@ -367,45 +364,14 @@ Menu::Menu() { // Developer > Render >>> MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); - action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, true); - connect(action, &QAction::triggered, [action] { - auto renderConfig = qApp->getRenderEngine()->getConfiguration(); - if (renderConfig) { - auto mainViewJitterCamConfig = renderConfig->getConfig("RenderMainView.JitterCam"); - auto mainViewAntialiasingConfig = renderConfig->getConfig("RenderMainView.Antialiasing"); - if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { - if (action->isChecked()) { - mainViewJitterCamConfig->play(); - mainViewAntialiasingConfig->setDebugFXAA(false); - } else { - mainViewJitterCamConfig->none(); - mainViewAntialiasingConfig->setDebugFXAA(true); - } - } - } - }); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, RenderScriptingInterface::getInstance()->getAntialiasingEnabled(), + RenderScriptingInterface::getInstance(), SLOT(setAntialiasingEnabled(bool))); - action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, true); - connect(action, &QAction::triggered, [action] { - auto renderConfig = qApp->getRenderEngine()->getConfiguration(); - if (renderConfig) { - auto lightingModelConfig = renderConfig->getConfig("RenderMainView.LightingModel"); - if (lightingModelConfig) { - lightingModelConfig->setShadow(action->isChecked()); - } - } - }); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, RenderScriptingInterface::getInstance()->getShadowsEnabled(), + RenderScriptingInterface::getInstance(), SLOT(setShadowsEnabled(bool))); - action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, false); - connect(action, &QAction::triggered, [action] { - auto renderConfig = qApp->getRenderEngine()->getConfiguration(); - if (renderConfig) { - auto lightingModelConfig = renderConfig->getConfig("RenderMainView.LightingModel"); - if (lightingModelConfig) { - lightingModelConfig->setAmbientOcclusion(action->isChecked()); - } - } - }); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, RenderScriptingInterface::getInstance()->getAmbientOcclusionEnabled(), + RenderScriptingInterface::getInstance(), SLOT(setAmbientOcclusionEnabled(bool))); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DefaultSkybox, 0, true); diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 8581c7527d..360a75b557 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -7,6 +7,9 @@ // #include "RenderScriptingInterface.h" +#include "LightingModel.h" +#include "AntialiasingEffect.h" + const QString DEFERRED = "deferred"; const QString FORWARD = "forward"; @@ -17,6 +20,9 @@ RenderScriptingInterface* RenderScriptingInterface::getInstance() { RenderScriptingInterface::RenderScriptingInterface() { setRenderMethod((render::Args::RenderMethod)_renderMethodSetting.get() == render::Args::RenderMethod::DEFERRED ? DEFERRED : FORWARD); + setShadowsEnabled(_shadowsEnabledSetting.get()); + setAmbientOcclusionEnabled(_ambientOcclusionEnabledSetting.get()); + setAntialiasingEnabled(_antialiasingEnabledSetting.get()); } QString RenderScriptingInterface::getRenderMethod() { @@ -24,6 +30,11 @@ QString RenderScriptingInterface::getRenderMethod() { } void RenderScriptingInterface::setRenderMethod(const QString& renderMethod) { + render::Args::RenderMethod newMethod = renderMethod == FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED; + if (_renderMethodSetting.get() == newMethod) { + return; + } + if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setRenderMethod", Q_ARG(const QString&, renderMethod)); return; @@ -31,14 +42,81 @@ void RenderScriptingInterface::setRenderMethod(const QString& renderMethod) { auto config = dynamic_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch")); if (config) { - if (renderMethod == DEFERRED) { - _renderMethodSetting.set(render::Args::RenderMethod::DEFERRED); - config->setBranch(render::Args::RenderMethod::DEFERRED); - emit config->dirtyEnabled(); - } else if (renderMethod == FORWARD) { - _renderMethodSetting.set(render::Args::RenderMethod::FORWARD); - config->setBranch(render::Args::RenderMethod::FORWARD); - emit config->dirtyEnabled(); + _renderMethodSetting.set(newMethod); + config->setBranch(newMethod); + emit config->dirtyEnabled(); + } +} + +bool RenderScriptingInterface::getShadowsEnabled() { + return _shadowsEnabledSetting.get(); +} + +void RenderScriptingInterface::setShadowsEnabled(bool enabled) { + if (_shadowsEnabledSetting.get() == enabled) { + return; + } + + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setShadowsEnabled", Q_ARG(bool, enabled)); + return; + } + + auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.LightingModel"); + if (lightingModelConfig) { + Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled); + _shadowsEnabledSetting.set(enabled); + lightingModelConfig->setShadow(enabled); + } +} + +bool RenderScriptingInterface::getAmbientOcclusionEnabled() { + return _ambientOcclusionEnabledSetting.get(); +} + +void RenderScriptingInterface::setAmbientOcclusionEnabled(bool enabled) { + if (_ambientOcclusionEnabledSetting.get() == enabled) { + return; + } + + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setAmbientOcclusionEnabled", Q_ARG(bool, enabled)); + return; + } + + auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.LightingModel"); + if (lightingModelConfig) { + Menu::getInstance()->setIsOptionChecked(MenuOption::AmbientOcclusion, enabled); + _ambientOcclusionEnabledSetting.set(enabled); + lightingModelConfig->setAmbientOcclusion(enabled); + } +} + +bool RenderScriptingInterface::getAntialiasingEnabled() { + return _antialiasingEnabledSetting.get(); +} + +void RenderScriptingInterface::setAntialiasingEnabled(bool enabled) { + if (_antialiasingEnabledSetting.get() == enabled) { + return; + } + + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setAntialiasingEnabled", Q_ARG(bool, enabled)); + return; + } + + auto mainViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.JitterCam"); + auto mainViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.Antialiasing"); + if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { + Menu::getInstance()->setIsOptionChecked(MenuOption::AntiAliasing, enabled); + _antialiasingEnabledSetting.set(enabled); + if (enabled) { + mainViewJitterCamConfig->play(); + mainViewAntialiasingConfig->setDebugFXAA(false); + } else { + mainViewJitterCamConfig->none(); + mainViewAntialiasingConfig->setDebugFXAA(true); } } } \ No newline at end of file diff --git a/interface/src/scripting/RenderScriptingInterface.h b/interface/src/scripting/RenderScriptingInterface.h index 2aff3a08b6..329433fb60 100644 --- a/interface/src/scripting/RenderScriptingInterface.h +++ b/interface/src/scripting/RenderScriptingInterface.h @@ -26,6 +26,9 @@ class RenderScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(QString renderMethod READ getRenderMethod WRITE setRenderMethod) + Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled) + Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled) + Q_PROPERTY(bool antialiasingEnabled READ getAntialiasingEnabled WRITE setAntialiasingEnabled) public: RenderScriptingInterface(); @@ -37,8 +40,8 @@ public slots: * Get a config for a job by name * @function Render.getConfig * @param {string} name - Can be: - * - . Search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root) - * - .[.]. Allows you to first look for the parent_name job (from this task as root) and then search from there for the + * - : Search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root) + * - .[.]: Allows you to first look for the parent_name job (from this task as root) and then search from there for the * optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path is found) * @returns {object} The sub job config. */ @@ -58,8 +61,53 @@ public slots: */ void setRenderMethod(const QString& renderMethod); + /**jsdoc + * Whether or not shadows are enabled + * @function Render.getShadowsEnabled + * @returns {bool} true if shadows are enabled, otherwise false + */ + bool getShadowsEnabled(); + + /**jsdoc + * Enables or disables shadows + * @function Render.setShadowsEnabled + * @param {bool} enabled - true to enable shadows, false to disable them + */ + void setShadowsEnabled(bool enabled); + + /**jsdoc + * Whether or not ambient occlusion is enabled + * @function Render.getAmbientOcclusionEnabled + * @returns {bool} true if ambient occlusion is enabled, otherwise false + */ + bool getAmbientOcclusionEnabled(); + + /**jsdoc + * Enables or disables ambient occlusion + * @function Render.setAmbientOcclusionEnabled + * @param {bool} enabled - true to enable ambient occlusion, false to disable it + */ + void setAmbientOcclusionEnabled(bool enabled); + + /**jsdoc + * Whether or not anti-aliasing is enabled + * @function Render.getAntialiasingEnabled + * @returns {bool} true if anti-aliasing is enabled, otherwise false + */ + bool getAntialiasingEnabled(); + + /**jsdoc + * Enables or disables anti-aliasing + * @function Render.setAntialiasingEnabled + * @param {bool} enabled - true to enable anti-aliasing, false to disable it + */ + void setAntialiasingEnabled(bool enabled); + private: Setting::Handle _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED }; + Setting::Handle _shadowsEnabledSetting { "shadowsEnabled", true }; + Setting::Handle _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false }; + Setting::Handle _antialiasingEnabledSetting { "antialiasingEnabled", true }; }; #endif // hifi_RenderScriptingInterface_h diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 936ade043d..8057601317 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -107,8 +107,6 @@ public: AntialiasingConfig() : render::Job::Config(true) {} void setDebugFXAA(bool debug) { debugFXAAX = (debug ? 0.0f : 1.0f); emit dirty();} - bool debugFXAA() const { return (debugFXAAX == 0.0f ? true : false); } - float blend{ 0.25f }; float sharpen{ 0.05f }; From 0e478de1a28216b6df4ea5ca05fd7da4851ee599 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 8 May 2019 10:47:06 +1200 Subject: [PATCH 03/40] Stub out missing Script JSDoc --- libraries/script-engine/src/ScriptEngine.h | 4 ++- libraries/shared/src/BaseScriptEngine.h | 33 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 3549578ed5..c4d4dd2c31 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -359,6 +359,7 @@ public: * @param {boolean} [deleteScriptCache=false] */ Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false); + QScriptValue currentModule(); bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent); QScriptValue newModule(const QString& modulePath, const QScriptValue& parent = QScriptValue()); @@ -496,7 +497,7 @@ public: * @function Script.callEntityScriptMethod * @param {Uuid} entityID * @param {string} methodName - * @param {string[]} parameters + * @param {string[]} [parameters=[]] * @param {Uuid} [remoteCallerID=Uuid.NULL] */ Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, @@ -721,6 +722,7 @@ signals: /**jsdoc * @function Script.entityScriptPreloadFinished + * @param {Uuid} entityID * @returns {Signal} */ // Emitted when an entity script has finished running preload diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index 8820a386bf..0a1addaa2e 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -31,8 +31,29 @@ public: BaseScriptEngine() {} + /**jsdoc + * @function Script.lintScript + * @param {string} sourceCode + * @param {string} fileName + * @param {number} [lineNumber=1] + * @returns {object} + */ Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); + + /**jsdoc + * @function Script.makeError + * @param {object} [other] + * @param {string} [type="Error"] + * @returns {object} + */ Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); + + /**jsdoc + * @function Script.formatExecption + * @param {object} exception + * @param {boolean} inludeExtendeDetails + * @returns {string} + */ Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails); QScriptValue cloneUncaughtException(const QString& detail = QString()); @@ -48,6 +69,18 @@ public: // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways static bool IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method); signals: + /**jsdoc + * @function Script.signalHandlerException + * @param {object} exception + * @returns {Signal} + */ + // Script.signalHandlerException is exposed by QScriptEngine. + + /**jsdoc + * @function Script.unhandledException + * @param {object} exception + * @returns {Signal} + */ void unhandledException(const QScriptValue& exception); protected: From d196e357012b61394067b3a25d7a467b32578115 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 10 May 2019 08:33:03 +1200 Subject: [PATCH 04/40] Polish existing Script JSDoc --- libraries/script-engine/src/ScriptEngine.h | 84 ++++++++++++++-------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index c4d4dd2c31..36e115411c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -100,6 +100,8 @@ public: }; /**jsdoc + * The Script API provides facilities for working with scripts. + * * @namespace Script * * @hifi-interface @@ -150,9 +152,18 @@ public: QList getListOfEntityScriptIDs(); /**jsdoc - * Stop the current script. + * Stops and unloads the current script. * @function Script.stop - * @param {boolean} [marshal=false] + * @param {boolean} [marshal=false] - Marshal. + *

Deprecated: This parameter is deprecated and will be removed.

+ * @example Stop a script after 5s. + * Script.setInterval(function () { + * print("Hello"); + * }, 1000); + * + * Script.setTimeout(function () { + * Script.stop(true); + * }, 5000); */ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts @@ -292,9 +303,10 @@ public: Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); /**jsdoc - * Start a new Interface or entity script. + * Starts running another script in Interface. + *

Note: Only works for Interface and avatar scripts.

* @function Script.load - * @param {string} filename - The URL of the script to load. Can be relative to the current script. + * @param {string} filename - The URL of the script to load. This can be relative to the current script's URL. * @example Load a script from another script. * // First file: scriptA.js * print("This is script A"); @@ -303,7 +315,7 @@ public: * print("This is script B"); * Script.load("scriptA.js"); * - * // If you run scriptB.js you should see both scripts in the running scripts list. + * // If you run scriptB.js you should see both scripts in the Running Scripts dialog. * // And you should see the following output: * // This is script B * // This is script A @@ -311,21 +323,23 @@ public: Q_INVOKABLE void load(const QString& loadfile); /**jsdoc - * Include JavaScript from other files in the current script. If a callback is specified the files are loaded and included - * asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are included). + * Includes JavaScript from other files in the current script. If a callback is specified, the files are loaded and + * included asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are + * included). * @function Script.include + * @variation 0 * @param {string[]} filenames - The URLs of the scripts to include. Each can be relative to the current script. - * @param {function} [callback=null] - The function to call back when the scripts have been included. Can be an in-line + * @param {function} [callback=null] - The function to call back when the scripts have been included. It can be an in-line * function or the name of a function. */ Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue()); /**jsdoc - * Include JavaScript from another file in the current script. If a callback is specified the file is loaded and included + * Includes JavaScript from another file in the current script. If a callback is specified, the file is loaded and included * asynchronously, otherwise it is included synchronously (i.e., script execution blocks while the file is included). * @function Script.include - * @param {string} filename - The URL of the script to include. Can be relative to the current script. - * @param {function} [callback=null] - The function to call back when the script has been included. Can be an in-line + * @param {string} filename - The URL of the script to include. It can be relative to the current script. + * @param {function} [callback=null] - The function to call back when the script has been included. It can be an in-line * function or the name of a function. * @example Include a script file asynchronously. * // First file: scriptA.js @@ -367,53 +381,53 @@ public: QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode); /**jsdoc - * Call a function at a set interval. + * Calls a function repeatedly, at a set interval. * @function Script.setInterval - * @param {function} function - The function to call. Can be an in-line function or the name of a function. + * @param {function} function - The function to call. This can be an in-line function or the name of a function. * @param {number} interval - The interval at which to call the function, in ms. - * @returns {object} A handle to the interval timer. Can be used by {@link Script.clearInterval}. + * @returns {object} A handle to the interval timer. This can be used by {@link Script.clearInterval}. * @example Print a message every second. * Script.setInterval(function () { - * print("Timer fired"); + * print("Interval timer fired"); * }, 1000); */ Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS); /**jsdoc - * Call a function after a delay. + * Calls a function once, after a delay. * @function Script.setTimeout - * @param {function} function - The function to call. Can be an in-line function or the name of a function. + * @param {function} function - The function to call. This can be an in-line function or the name of a function. * @param {number} timeout - The delay after which to call the function, in ms. - * @returns {object} A handle to the timeout timer. Can be used by {@link Script.clearTimeout}. - * @example Print a message after a second. + * @returns {object} A handle to the timeout timer. This can be used by {@link Script.clearTimeout}. + * @example Print a message once, after a second. * Script.setTimeout(function () { - * print("Timer fired"); + * print("Timeout timer fired"); * }, 1000); */ Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS); /**jsdoc - * Stop an interval timer set by {@link Script.setInterval|setInterval}. + * Stops an interval timer set by {@link Script.setInterval|setInterval}. * @function Script.clearInterval - * @param {object} timer - The interval timer to clear. + * @param {object} timer - The interval timer to stop. * @example Stop an interval timer. * // Print a message every second. * var timer = Script.setInterval(function () { - * print("Timer fired"); + * print("Interval timer fired"); * }, 1000); * * // Stop the timer after 10 seconds. * Script.setTimeout(function () { - * print("Stop timer"); + * print("Stop interval timer"); * Script.clearInterval(timer); * }, 10000); */ Q_INVOKABLE void clearInterval(QObject* timer) { stopTimer(reinterpret_cast(timer)); } /**jsdoc - * Clear a timeout timer set by {@link Script.setTimeout|setTimeout}. + * Stops a timeout timer set by {@link Script.setTimeout|setTimeout}. * @function Script.clearTimeout - * @param {object} timer - The timeout timer to clear. + * @param {object} timer - The timeout timer to stop. * @example Stop a timeout timer. * // Print a message after two seconds. * var timer = Script.setTimeout(function () { @@ -432,10 +446,16 @@ public: Q_INVOKABLE void print(const QString& message); /**jsdoc - * Resolve a relative path to an absolute path. + * Resolves a relative path to an absolute path. The relative path is relative to the script's location. * @function Script.resolvePath * @param {string} path - The relative path to resolve. * @returns {string} The absolute path. + * @example Report the directory and filename of the running script. + * print(Script.resolvePath("")); + * @example Report the directory of the running script. + * print(Script.resolvePath(".")); + * @example Report the path to a file located relative to the running script. + * print(Script.resolvePath("../assets/sounds/hello.wav")); */ Q_INVOKABLE QUrl resolvePath(const QString& path) const; @@ -606,18 +626,22 @@ signals: void errorLoadingScript(const QString& scriptFilename); /**jsdoc - * Triggered regularly at a system-determined frequency. + * Triggered frequently at a system-determined interval. * @function Script.update * @param {number} deltaTime - The time since the last update, in s. * @returns {Signal} + * @example Report script update intervals. + * Script.update.connect(function (deltaTime) { + * print("Update: " + deltaTime); + * }); */ void update(float deltaTime); /**jsdoc - * Triggered when the script is ending. + * Triggered when the script is stopping. * @function Script.scriptEnding * @returns {Signal} - * @example Connect to the scriptEnding signal. + * @example Report when a script is stopping. * print("Script started"); * * Script.scriptEnding.connect(function () { From 0a0a25139c09dbcc6ebf3bec29ad4391cd0f0d69 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 11 May 2019 09:29:13 +1200 Subject: [PATCH 05/40] Deprecate items that shouldn't be in the Script API --- libraries/script-engine/src/ScriptEngine.h | 105 ++++++++++++--------- libraries/shared/src/BaseScriptEngine.h | 17 ++-- 2 files changed, 72 insertions(+), 50 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 36e115411c..b81829aa54 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -178,18 +178,20 @@ public: /**jsdoc * @function Script.registerGlobalObject - * @param {string} name - * @param {object} object + * @param {string} name - Name. + * @param {object} object - Object. + * @deprecated This function is deprecated and will be removed. */ /// registers a global object by name Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object); /**jsdoc * @function Script.registerGetterSetter - * @param {string} name - * @param {object} getter - * @param {object} setter - * @param {string} [parent=""] + * @param {string} name - Name. + * @param {object} getter - Getter. + * @param {object} setter - Setter. + * @param {string} [parent=""] - Parent. + * @deprecated This function is deprecated and will be removed. */ /// registers a global getter/setter Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter, @@ -197,19 +199,21 @@ public: /**jsdoc * @function Script.registerFunction - * @param {string} name - * @param {object} function - * @param {number} [numArguments=-1] + * @param {string} name - Name. + * @param {object} function - Function. + * @param {number} [numArguments=-1] - Number of arguments. + * @deprecated This function is deprecated and will be removed. */ /// register a global function Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1); /**jsdoc * @function Script.registerFunction - * @param {string} parent - * @param {string} name - * @param {object} function - * @param {number} [numArguments=-1] + * @param {string} parent - Parent. + * @param {string} name - Name. + * @param {object} function - Function. + * @param {number} [numArguments=-1] - Number of arguments. + * @deprecated This function is deprecated and will be removed. */ /// register a function as a method on a previously registered global object Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun, @@ -217,27 +221,30 @@ public: /**jsdoc * @function Script.registerValue - * @param {string} name - * @param {object} value + * @param {string} name - Name. + * @param {object} value - Value. + * @deprecated This function is deprecated and will be removed. */ /// registers a global object by name Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value); /**jsdoc * @function Script.evaluate - * @param {string} program - * @param {string} filename - * @param {number} [lineNumber=-1] - * @returns {object} + * @param {string} program - Program. + * @param {string} filename - File name. + * @param {number} [lineNumber=-1] - Line number. + * @returns {object} Object. + * @deprecated This function is deprecated and will be removed. */ /// evaluate some code in the context of the ScriptEngine and return the result Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName, int lineNumber = 1); // this is also used by the script tool widget /**jsdoc * @function Script.evaluateInClosure - * @param {object} locals - * @param {object} program - * @returns {object} + * @param {object} locals - Locals. + * @param {object} program - Program. + * @returns {object} Object. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program); @@ -495,21 +502,24 @@ public: /**jsdoc * @function Script.loadEntityScript - * @param {Uuid} entityID - * @param {string} script - * @param {boolean} forceRedownload + * @param {Uuid} entityID - Entity IUD. + * @param {string} script - Script. + * @param {boolean} forceRedownload - Force re-download. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload); /**jsdoc * @function Script.unloadEntityScript - * @param {Uuid} entityID - * @param {boolean} [shouldRemoveFromMap=false] + * @param {Uuid} entityID - Entity ID. + * @param {boolean} [shouldRemoveFromMap=false] - Should remove from map. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method /**jsdoc * @function Script.unloadAllEntityScripts + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void unloadAllEntityScripts(); @@ -548,7 +558,8 @@ public: /**jsdoc * @function Script.generateUUID - * @returns {Uuid} + * @returns {Uuid} A new UUID. + * @deprecated This function is deprecated and will be removed. Use {@link Uuid.generate} instead. */ Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); } @@ -605,7 +616,8 @@ public slots: /**jsdoc * @function Script.updateMemoryCost - * @param {number} deltaSize + * @param {number} deltaSize - Delta size. + * @deprecated This function is deprecated and will be removed. */ void updateMemoryCost(const qint64&); @@ -657,16 +669,18 @@ signals: /**jsdoc * @function Script.finished - * @param {string} filename - * @param {object} engine + * @param {string} filename - File name. + * @param {object} engine - Engine. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void finished(const QString& fileNameString, ScriptEnginePointer); /**jsdoc * @function Script.cleanupMenuItem - * @param {string} menuItem + * @param {string} menuItem - Menu item. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void cleanupMenuItem(const QString& menuItemString); @@ -711,6 +725,7 @@ signals: /**jsdoc * @function Script.clearDebugWindow * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void clearDebugWindow(); @@ -739,6 +754,7 @@ signals: /**jsdoc * @function Script.entityScriptDetailsUpdated * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ // Emitted when an entity script is added or removed, or when the status of an entity // script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example) @@ -757,16 +773,18 @@ protected: /**jsdoc * @function Script.executeOnScriptThread - * @param {object} function - * @param {ConnectionType} [type=2] + * @param {object} function - Function. + * @param {ConnectionType} [type=2] - Connection type. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void executeOnScriptThread(std::function function, const Qt::ConnectionType& type = Qt::QueuedConnection ); /**jsdoc * @function Script._requireResolve - * @param {string} module - * @param {string} [relativeTo=""] - * @returns {string} + * @param {string} module - Module. + * @param {string} [relativeTo=""] - Relative to. + * @returns {string} Result. + * @deprecated This function is deprecated and will be removed. */ // note: this is not meant to be called directly, but just to have QMetaObject take care of wiring it up in general; // then inside of init() we just have to do "Script.require.resolve = Script._requireResolve;" @@ -789,12 +807,13 @@ protected: /**jsdoc * @function Script.entityScriptContentAvailable - * @param {Uuid} entityID - * @param {string} scriptOrURL - * @param {string} contents - * @param {boolean} isURL - * @param {boolean} success - * @param {string} status + * @param {Uuid} entityID - Entity ID. + * @param {string} scriptOrURL - Path. + * @param {string} contents - Contents. + * @param {boolean} isURL - Is URL. + * @param {boolean} success - Success. + * @param {string} status - Status. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success, const QString& status); diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index 0a1addaa2e..6baa5d3c35 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -42,17 +42,19 @@ public: /**jsdoc * @function Script.makeError - * @param {object} [other] - * @param {string} [type="Error"] - * @returns {object} + * @param {object} [other] - Other. + * @param {string} [type="Error"] - Errorl + * @returns {object} Object. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); /**jsdoc * @function Script.formatExecption - * @param {object} exception - * @param {boolean} inludeExtendeDetails - * @returns {string} + * @param {object} exception - Exception. + * @param {boolean} inludeExtendeDetails - Include extended details. + * @returns {string} String. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails); @@ -71,8 +73,9 @@ public: signals: /**jsdoc * @function Script.signalHandlerException - * @param {object} exception + * @param {object} exception - Exception. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ // Script.signalHandlerException is exposed by QScriptEngine. From ca7ddece8b1dc6c763dfc4c226836cc367522f43 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 May 2019 09:49:21 +1200 Subject: [PATCH 06/40] Add missing Script JSDoc --- .../entities/src/EntityScriptingInterface.h | 12 ++ libraries/script-engine/src/ScriptEngine.cpp | 29 ++- libraries/script-engine/src/ScriptEngine.h | 202 +++++++++++++----- libraries/shared/src/BaseScriptEngine.h | 17 +- 4 files changed, 199 insertions(+), 61 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c072dedaf9..39700bfc31 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -1770,6 +1770,7 @@ signals: /**jsdoc * Triggered on the client that is the physics simulation owner during the collision of two entities. Note: Isn't triggered * for a collision with an avatar. + *

See also, {@link Script.addEventHandler}.

* @function Entities.collisionWithEntity * @param {Uuid} idA - The ID of one entity in the collision. For an entity script, this is the ID of the entity containing * the script. @@ -1882,6 +1883,7 @@ signals: /**jsdoc * Triggered when a mouse button is clicked while the mouse cursor is on an entity, or a controller trigger is fully * pressed while its laser is on an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.mousePressOnEntity * @param {Uuid} entityID - The ID of the entity that was pressed. * @param {PointerEvent} event - Details of the event. @@ -1906,6 +1908,7 @@ signals: /**jsdoc * Repeatedly triggered while the mouse cursor or controller laser moves on an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.mouseMoveOnEntity * @param {Uuid} entityID - The ID of the entity that was moved on. * @param {PointerEvent} event - Details of the event. @@ -1916,6 +1919,7 @@ signals: /**jsdoc * Triggered when a mouse button is released after clicking on an entity or the controller trigger is partly or fully * released after pressing on an entity, even if the mouse pointer or controller laser has moved off the entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.mouseReleaseOnEntity * @param {Uuid} entityID - The ID of the entity that was originally pressed. * @param {PointerEvent} event - Details of the event. @@ -1942,6 +1946,7 @@ signals: /**jsdoc * Triggered when a mouse button is clicked while the mouse cursor is on an entity. Note: Not triggered by controller. + *

See also, {@link Script.addEventHandler}.

* @function Entities.clickDownOnEntity * @param {Uuid} entityID - The ID of the entity that was clicked. * @param {PointerEvent} event - Details of the event. @@ -1952,6 +1957,7 @@ signals: /**jsdoc * Repeatedly triggered while a mouse button continues to be held after clicking an entity, even if the mouse cursor has * moved off the entity. Note: Not triggered by controller. + *

See also, {@link Script.addEventHandler}.

* @function Entities.holdingClickOnEntity * @param {Uuid} entityID - The ID of the entity that was originally clicked. * @param {PointerEvent} event - Details of the event. @@ -1962,6 +1968,7 @@ signals: /**jsdoc * Triggered when a mouse button is released after clicking on an entity, even if the mouse cursor has moved off the * entity. Note: Not triggered by controller. + *

See also, {@link Script.addEventHandler}.

* @function Entities.clickReleaseOnEntity * @param {Uuid} entityID - The ID of the entity that was originally clicked. * @param {PointerEvent} event - Details of the event. @@ -1971,6 +1978,7 @@ signals: /**jsdoc * Triggered when the mouse cursor or controller laser starts hovering on an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.hoverEnterEntity * @param {Uuid} entityID - The ID of the entity that is being hovered. * @param {PointerEvent} event - Details of the event. @@ -1980,6 +1988,7 @@ signals: /**jsdoc * Repeatedly triggered when the mouse cursor or controller laser moves while hovering over an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.hoverOverEntity * @param {Uuid} entityID - The ID of the entity that is being hovered. * @param {PointerEvent} event - Details of the event. @@ -1989,6 +1998,7 @@ signals: /**jsdoc * Triggered when the mouse cursor or controller laser stops hovering over an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.hoverLeaveEntity * @param {Uuid} entityID - The ID of the entity that was being hovered. * @param {PointerEvent} event - Details of the event. @@ -1999,6 +2009,7 @@ signals: /**jsdoc * Triggered when an avatar enters an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.enterEntity * @param {Uuid} entityID - The ID of the entity that the avatar entered. * @returns {Signal} @@ -2032,6 +2043,7 @@ signals: /**jsdoc * Triggered when an avatar leaves an entity. + *

See also, {@link Script.addEventHandler}.

* @function Entities.leaveEntity * @param {Uuid} entityID - The ID of the entity that the avatar left. * @returns {Signal} diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 7abb63ca1c..309161206c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -987,6 +987,31 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& }; }; + /**jsdoc + * The name of an entity event. When the entity event occurs, any function that has been registered for that event via + * {@link Script.addEventHandler} is called with parameters per the entity event. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Event NameEntity Event
"enterEntity"{@link Entities.enterEntity}
"leaveEntity"{@link Entities.leaveEntity}
"mousePressOnEntity"{@link Entities.mousePressOnEntity}
"mouseMoveOnEntity"{@link Entities.mouseMoveOnEntity}
"mouseReleaseOnEntity"{@link Entities.mouseReleaseOnEntity}
"clickDownOnEntity"{@link Entities.clickDownOnEntity}
"holdingClickOnEntity"{@link Entities.holdingClickOnEntity}
"clickReleaseOnEntity"{@link Entities.clickReleaseOnEntity}
"hoverEnterEntity"{@link Entities.hoverEnterEntity}
"hoverOverEntity"{@link Entities.hoverOverEntity}
"hoverLeaveEntity"{@link Entities.hoverLeaveEntity}
"collisionWithEntity"{@link Entities.collisionWithEntity}
+ * + * @typedef {string} Script.EntityEvent + */ connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity")); connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity")); @@ -2147,7 +2172,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& } /**jsdoc - * Triggered when the script starts for a user. + * Triggered when the script starts for a user. See also, {@link Script.entityScriptPreloadFinished}. *

Note: Can only be connected to via this.preload = function (...) { ... } in the entity script.

*
Available in:Client Entity ScriptsServer Entity Scripts
* @function Entities.preload @@ -2161,7 +2186,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& * this.entityID = entityID; * print("Entity ID: " + this.entityID); * }; - * ); + * }); * * var entityID = Entities.addEntity({ * type: "Box", diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index b81829aa54..c6b1135fc6 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -110,7 +110,14 @@ public: * @hifi-server-entity * @hifi-assignment-client * - * @property {string} context + * @property {string} context - The context that the script is running in: + *
    + *
  • "client": An Interface or avatar script.
  • + *
  • "entity_client": A client entity script.
  • + *
  • "entity_server": A server entity script.
  • + *
  • "agent": An assignment client script.
  • + *
+ * Read-only. */ class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider { Q_OBJECT @@ -153,6 +160,7 @@ public: /**jsdoc * Stops and unloads the current script. + *

Warning: If an assignment client script, the script gets restarted after stopping.

* @function Script.stop * @param {boolean} [marshal=false] - Marshal. *

Deprecated: This parameter is deprecated and will be removed.

@@ -255,38 +263,53 @@ public: bool hasValidScriptSuffix(const QString& scriptFileName); /**jsdoc + * Gets the context that the script is running in: Interface/avatar, client entity, server entity, or assignment client. * @function Script.getContext - * @returns {string} + * @returns {string} The context that the script is running in: + *
    + *
  • "client": An Interface or avatar script.
  • + *
  • "entity_client": A client entity script.
  • + *
  • "entity_server": A server entity script.
  • + *
  • "agent": An assignment client script.
  • + *
*/ Q_INVOKABLE QString getContext() const; /**jsdoc + * Checks whether the script is running as an Interface or avatar script. * @function Script.isClientScript - * @returns {boolean} + * @returns {boolean} true if the script is running as an Interface or avatar script, false if it + * isn't. */ Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } /**jsdoc + * Checks whether the application was compiled as a debug build. * @function Script.isDebugMode - * @returns {boolean} + * @returns {boolean} true if the software was compiled as a debug build, false if it was + * compiled as a release build. */ Q_INVOKABLE bool isDebugMode() const; /**jsdoc + * Checks whether the script content is a client entity script. * @function Script.isEntityClientScript - * @returns {boolean} + * @returns {boolean} true if the script is running as a client entity script, false if it isn't. */ Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } /**jsdoc + * Checks whether the script context is a server entity script. * @function Script.isEntityServerScript - * @returns {boolean} + * @returns {boolean} true if the script is running as a server entity script, false if it isn't. */ Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; } /**jsdoc + * Checks whether the script is running as an assignment client script. * @function Script.isAgentScript - * @returns {boolean} + * @returns {boolean} true if the script is running as an assignment client script, false if it + * isn't. */ Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; } @@ -294,24 +317,40 @@ public: // NOTE - these are intended to be public interfaces available to scripts /**jsdoc + * Adds a function to the list of functions called upon the occurrence of an entity event on a particular entity. * @function Script.addEventHandler - * @param {Uuid} entityID - * @param {string} eventName - * @param {function} handler + * @param {Uuid} entityID - The ID of the entity. + * @param {Script.EntityEvent} eventName - The name of the entity event. + * @param {function} handler - The function to call when the entity event occurs on the entity. It can be either the name + * of a function or an in-line definition. + * @example Report when a mouse press occurs on a particular entity. + * var entityID = Entities.addEntity({ + * type: "Box", + * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })), + * dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + * lifetime: 300 // Delete after 5 minutes. + * }); + * + * function reportMousePress(entityID, event) { + * print("Mouse pressed on entity: " + JSON.stringify(event)); + * } + * + * Script.addEventHandler(entityID, "mousePressOnEntity", reportMousePress); */ Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); /**jsdoc + * Removes a function from the list of functions called upon the occurrence of an entity event on a particular entity. * @function Script.removeEventHandler - * @param {Uuid} entityID - * @param {string} eventName - * @param {function} handler + * @param {Uuid} entityID - The ID of the entity. + * @param {Script.EntityEvent} eventName - The name of the entity event. + * @param {function} handler - The name of the function to no longer call when the entity event occurs on the entity. */ Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); /**jsdoc * Starts running another script in Interface. - *

Note: Only works for Interface and avatar scripts.

+ *
Available in:Interface ScriptsAvatar Scripts
* @function Script.load * @param {string} filename - The URL of the script to load. This can be relative to the current script's URL. * @example Load a script from another script. @@ -336,8 +375,8 @@ public: * @function Script.include * @variation 0 * @param {string[]} filenames - The URLs of the scripts to include. Each can be relative to the current script. - * @param {function} [callback=null] - The function to call back when the scripts have been included. It can be an in-line - * function or the name of a function. + * @param {function} [callback=null] - The function to call back when the scripts have been included. It can be either the + * name of a function or an in-line definition. */ Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue()); @@ -346,8 +385,8 @@ public: * asynchronously, otherwise it is included synchronously (i.e., script execution blocks while the file is included). * @function Script.include * @param {string} filename - The URL of the script to include. It can be relative to the current script. - * @param {function} [callback=null] - The function to call back when the script has been included. It can be an in-line - * function or the name of a function. + * @param {function} [callback=null] - The function to call back when the script has been included. It can be either the + * name of a function or an in-line definition. * @example Include a script file asynchronously. * // First file: scriptA.js * print("This is script A"); @@ -370,14 +409,18 @@ public: // MODULE related methods /**jsdoc + * Provides access to methods or objects provided in an external JavaScript or JSON file. + * See {@link https://docs.highfidelity.com/script/js-tips.html} for further details. * @function Script.require - * @param {string} module + * @param {string} module - The module to use. May be a JavaScript file or the name of system model such as + * "sppUi". */ Q_INVOKABLE QScriptValue require(const QString& moduleId); /**jsdoc * @function Script.resetModuleCache - * @param {boolean} [deleteScriptCache=false] + * @param {boolean} [deleteScriptCache=false] - Delete script cache. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false); @@ -390,7 +433,7 @@ public: /**jsdoc * Calls a function repeatedly, at a set interval. * @function Script.setInterval - * @param {function} function - The function to call. This can be an in-line function or the name of a function. + * @param {function} function - The function to call. This can be either the name of a function or an in-line definition. * @param {number} interval - The interval at which to call the function, in ms. * @returns {object} A handle to the interval timer. This can be used by {@link Script.clearInterval}. * @example Print a message every second. @@ -403,7 +446,7 @@ public: /**jsdoc * Calls a function once, after a delay. * @function Script.setTimeout - * @param {function} function - The function to call. This can be an in-line function or the name of a function. + * @param {function} function - The function to call. This can be either the name of a function or an in-line definition. * @param {number} timeout - The delay after which to call the function, in ms. * @returns {object} A handle to the timeout timer. This can be used by {@link Script.clearTimeout}. * @example Print a message once, after a second. @@ -447,8 +490,16 @@ public: Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast(timer)); } /**jsdoc + * Prints a message to the program log. + *

Alternatively, you can use {@link print}, {@link console.log}, or one of the other {@link console} methods.

* @function Script.print - * @param {string} message + * @param {string} message - The message to print. + */ + /**jsdoc + * Prints a message to the program log. + *

This is an alias of {@link Script.print}.

+ * @function print + * @param {string} message - The message to print. */ Q_INVOKABLE void print(const QString& message); @@ -467,20 +518,25 @@ public: Q_INVOKABLE QUrl resolvePath(const QString& path) const; /**jsdoc + * Gets the path to the resources directory for QML files. * @function Script.resourcesPath - * @returns {string} + * @returns {string} The path to the resources directory for QML files. */ Q_INVOKABLE QUrl resourcesPath() const; /**jsdoc + * Starts timing a section of code in order to send usage data about it to High Fidelity. Shouldn't be used outside of the + * standard scripts. * @function Script.beginProfileRange - * @param {string} label + * @param {string} label - A name that identifies the section of code. */ Q_INVOKABLE void beginProfileRange(const QString& label) const; /**jsdoc + * Finishes timing a section of code in order to send usage data about it to High Fidelity. Shouldn't be used outside of + * the standard scripts. * @function Script.endProfileRange - * @param {string} label + * @param {string} label - A name that identifies the section of code. */ Q_INVOKABLE void endProfileRange(const QString& label) const; @@ -488,9 +544,10 @@ public: // Entity Script Related methods /**jsdoc + * Checks whether an entity has an entity script running. * @function Script.isEntityScriptRunning - * @param {Uuid} entityID - * @returns {boolean} + * @param {Uuid} entityID - The ID of the entity. + * @returns {boolean} true if the entity has an entity script running, false if it doesn't. */ Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) { QReadLocker locker { &_entityScriptsLock }; @@ -524,34 +581,41 @@ public: Q_INVOKABLE void unloadAllEntityScripts(); /**jsdoc + * Calls a method in an entity script. * @function Script.callEntityScriptMethod - * @param {Uuid} entityID - * @param {string} methodName - * @param {string[]} [parameters=[]] - * @param {Uuid} [remoteCallerID=Uuid.NULL] + * @param {Uuid} entityID - The ID of the entity running the entity script. + * @param {string} methodName - The name of the method to call. + * @param {string[]} [parameters=[]] - The parameters to call the specified method with. + * @param {Uuid} [remoteCallerID=Uuid.NULL] - An ID that identifies the caller. */ Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params = QStringList(), const QUuid& remoteCallerID = QUuid()) override; /**jsdoc + * Calls a method in an entity script. * @function Script.callEntityScriptMethod - * @param {Uuid} entityID - * @param {string} methodName - * @param {PointerEvent} event + * @param {Uuid} entityID - Entity ID. + * @param {string} methodName - Method name. + * @param {PointerEvent} event - Pointer event. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event); /**jsdoc + * Calls a method in an entity script. * @function Script.callEntityScriptMethod - * @param {Uuid} entityID - * @param {string} methodName - * @param {Uuid} otherID - * @param {Collision} collision + * @param {Uuid} entityID - Entity ID. + * @param {string} methodName - Method name. + * @param {Uuid} otherID - Other entity ID. + * @param {Collision} collision - Collision. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); /**jsdoc + * Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer + * reachable. * @function Script.requestGarbageCollection */ Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } @@ -625,15 +689,17 @@ signals: /**jsdoc * @function Script.scriptLoaded - * @param {string} filename + * @param {string} filename - File name. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void scriptLoaded(const QString& scriptFilename); /**jsdoc * @function Script.errorLoadingScript - * @param {string} filename + * @param {string} filename - File name. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void errorLoadingScript(const QString& scriptFilename); @@ -685,38 +751,44 @@ signals: void cleanupMenuItem(const QString& menuItemString); /**jsdoc + * Triggered when a script prints a message to the program log via {@link Script.print}, {@link print}, + * {@link console.log}, {@link console.info}, {@link console.warn}, {@link console.error}, or {@link console.debug}. * @function Script.printedMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - The message. + * @param {string} scriptName - The name of the script that generated the message. * @returns {Signal} */ void printedMessage(const QString& message, const QString& scriptName); /**jsdoc + * Triggered when a script generates an error or {@link console.error} is called. * @function Script.errorMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - The error message. + * @param {string} scriptName - The name of the script that generated the error message. * @returns {Signal} */ void errorMessage(const QString& message, const QString& scriptName); /**jsdoc + * Triggered when a script generates a warning or {@link console.warn} is called. * @function Script.warningMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - The warning message. + * @param {string} scriptName - The name of the script that generated the warning message. * @returns {Signal} */ void warningMessage(const QString& message, const QString& scriptName); /**jsdoc + * Triggered when a script generates an information message or {@link console.info} is called. * @function Script.infoMessage - * @param {string} message - * @param {string} scriptName + * @param {string} message - The information message. + * @param {string} scriptName - The name of the script that generated the information message. * @returns {Signal} */ void infoMessage(const QString& message, const QString& scriptName); /**jsdoc + * Triggered when the running state of the script changes, e.g., from running to stopping. * @function Script.runningStateChanged * @returns {Signal} */ @@ -731,21 +803,24 @@ signals: /**jsdoc * @function Script.loadScript - * @param {string} scriptName - * @param {boolean} isUserLoaded + * @param {string} scriptName - Script name. + * @param {boolean} isUserLoaded - Is user loaded. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void loadScript(const QString& scriptName, bool isUserLoaded); /**jsdoc * @function Script.reloadScript - * @param {string} scriptName - * @param {boolean} isUserLoaded + * @param {string} scriptName - Script name. + * @param {boolean} isUserLoaded - Is user loaded. * @returns {Signal} + * @deprecated This signal is deprecated and will be removed. */ void reloadScript(const QString& scriptName, bool isUserLoaded); /**jsdoc + * Triggered when the script has stopped. * @function Script.doneRunning * @returns {Signal} */ @@ -761,9 +836,28 @@ signals: void entityScriptDetailsUpdated(); /**jsdoc + * Triggered when the script starts for the user. See also, {@link Entities.preload}. + *
Available in:Client Entity ScriptsServer Entity Scripts
* @function Script.entityScriptPreloadFinished - * @param {Uuid} entityID + * @param {Uuid} entityID - The ID of the entity that the script is running in. * @returns {Signal} + * @example Get the ID of the entity that a client entity script is running in. + * var entityScript = (function () { + * this.entityID = Uuid.NULL; + * + * Script.entityScriptPreloadFinished.connect(function (entityID) { + * this.entityID = entityID; + * print("Entity ID: " + this.entityID); + * }); + * + * var entityID = Entities.addEntity({ + * type: "Box", + * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })), + * dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + * color: { red: 255, green: 0, blue: 0 }, + * script: "(" + entityScript + ")", // Could host the script on a Web server instead. + * lifetime: 300 // Delete after 5 minutes. + * }); */ // Emitted when an entity script has finished running preload void entityScriptPreloadFinished(const EntityItemID& entityID); diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index 6baa5d3c35..b750c20028 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -33,10 +33,11 @@ public: /**jsdoc * @function Script.lintScript - * @param {string} sourceCode - * @param {string} fileName - * @param {number} [lineNumber=1] - * @returns {object} + * @param {string} sourceCode - Source code. + * @param {string} fileName - File name. + * @param {number} [lineNumber=1] - Line number. + * @returns {object} Object. + * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); @@ -80,9 +81,15 @@ signals: // Script.signalHandlerException is exposed by QScriptEngine. /**jsdoc + * Triggered when a script generates an unhandled exception. * @function Script.unhandledException - * @param {object} exception + * @param {object} exception - The details of the exception. * @returns {Signal} + * @example Report the details of an unhandled exception. + * Script.unhandledException.connect(function (exception) { + * print("Unhandled exception: " + JSON.stringify(exception)); + * }); + * var properties = JSON.parse("{ x: 1"); // Invalid JSON string. */ void unhandledException(const QScriptValue& exception); From 5227b35c6b96295e4655ae1182872c85c7b3cbbc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 May 2019 10:16:01 +1200 Subject: [PATCH 07/40] Revise changes --- libraries/script-engine/src/ScriptEngine.h | 32 +++++++++++----------- libraries/shared/src/BaseScriptEngine.h | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index c6b1135fc6..e58609f01d 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -196,8 +196,8 @@ public: /**jsdoc * @function Script.registerGetterSetter * @param {string} name - Name. - * @param {object} getter - Getter. - * @param {object} setter - Setter. + * @param {function} getter - Getter. + * @param {function} setter - Setter. * @param {string} [parent=""] - Parent. * @deprecated This function is deprecated and will be removed. */ @@ -208,7 +208,7 @@ public: /**jsdoc * @function Script.registerFunction * @param {string} name - Name. - * @param {object} function - Function. + * @param {function} function - Function. * @param {number} [numArguments=-1] - Number of arguments. * @deprecated This function is deprecated and will be removed. */ @@ -219,7 +219,7 @@ public: * @function Script.registerFunction * @param {string} parent - Parent. * @param {string} name - Name. - * @param {object} function - Function. + * @param {function} function - Function. * @param {number} [numArguments=-1] - Number of arguments. * @deprecated This function is deprecated and will be removed. */ @@ -286,20 +286,20 @@ public: /**jsdoc * Checks whether the application was compiled as a debug build. * @function Script.isDebugMode - * @returns {boolean} true if the software was compiled as a debug build, false if it was + * @returns {boolean} true if the application was compiled as a debug build, false if it was * compiled as a release build. */ Q_INVOKABLE bool isDebugMode() const; /**jsdoc - * Checks whether the script content is a client entity script. + * Checks whether the script is running as a client entity script. * @function Script.isEntityClientScript * @returns {boolean} true if the script is running as a client entity script, false if it isn't. */ Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } /**jsdoc - * Checks whether the script context is a server entity script. + * Checks whether the script is running as a server entity script. * @function Script.isEntityServerScript * @returns {boolean} true if the script is running as a server entity script, false if it isn't. */ @@ -317,7 +317,7 @@ public: // NOTE - these are intended to be public interfaces available to scripts /**jsdoc - * Adds a function to the list of functions called upon the occurrence of an entity event on a particular entity. + * Adds a function to the list of functions called when an entity event occurs on a particular entity. * @function Script.addEventHandler * @param {Uuid} entityID - The ID of the entity. * @param {Script.EntityEvent} eventName - The name of the entity event. @@ -340,7 +340,7 @@ public: Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); /**jsdoc - * Removes a function from the list of functions called upon the occurrence of an entity event on a particular entity. + * Removes a function from the list of functions called when an entity event occurs on a particular entity. * @function Script.removeEventHandler * @param {Uuid} entityID - The ID of the entity. * @param {Script.EntityEvent} eventName - The name of the entity event. @@ -412,7 +412,7 @@ public: * Provides access to methods or objects provided in an external JavaScript or JSON file. * See {@link https://docs.highfidelity.com/script/js-tips.html} for further details. * @function Script.require - * @param {string} module - The module to use. May be a JavaScript file or the name of system model such as + * @param {string} module - The module to use. May be a JavaScript file or the name of a system module such as * "sppUi". */ Q_INVOKABLE QScriptValue require(const QString& moduleId); @@ -435,7 +435,7 @@ public: * @function Script.setInterval * @param {function} function - The function to call. This can be either the name of a function or an in-line definition. * @param {number} interval - The interval at which to call the function, in ms. - * @returns {object} A handle to the interval timer. This can be used by {@link Script.clearInterval}. + * @returns {object} A handle to the interval timer. This can be used in {@link Script.clearInterval}. * @example Print a message every second. * Script.setInterval(function () { * print("Interval timer fired"); @@ -448,7 +448,7 @@ public: * @function Script.setTimeout * @param {function} function - The function to call. This can be either the name of a function or an in-line definition. * @param {number} timeout - The delay after which to call the function, in ms. - * @returns {object} A handle to the timeout timer. This can be used by {@link Script.clearTimeout}. + * @returns {object} A handle to the timeout timer. This can be used in {@link Script.clearTimeout}. * @example Print a message once, after a second. * Script.setTimeout(function () { * print("Timeout timer fired"); @@ -559,7 +559,7 @@ public: /**jsdoc * @function Script.loadEntityScript - * @param {Uuid} entityID - Entity IUD. + * @param {Uuid} entityID - Entity ID. * @param {string} script - Script. * @param {boolean} forceRedownload - Force re-download. * @deprecated This function is deprecated and will be removed. @@ -669,7 +669,7 @@ public slots: /**jsdoc * @function Script.callAnimationStateHandler - * @param {function} callback - Callback. + * @param {function} callback - Callback function. * @param {object} parameters - Parameters. * @param {string[]} names - Names. * @param {boolean} useNames - Use names. @@ -867,7 +867,7 @@ protected: /**jsdoc * @function Script.executeOnScriptThread - * @param {object} function - Function. + * @param {function} function - Function. * @param {ConnectionType} [type=2] - Connection type. * @deprecated This function is deprecated and will be removed. */ @@ -904,7 +904,7 @@ protected: * @param {Uuid} entityID - Entity ID. * @param {string} scriptOrURL - Path. * @param {string} contents - Contents. - * @param {boolean} isURL - Is URL. + * @param {boolean} isURL - Is a URL. * @param {boolean} success - Success. * @param {string} status - Status. * @deprecated This function is deprecated and will be removed. diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index b750c20028..443c7b0500 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -44,7 +44,7 @@ public: /**jsdoc * @function Script.makeError * @param {object} [other] - Other. - * @param {string} [type="Error"] - Errorl + * @param {string} [type="Error"] - Error. * @returns {object} Object. * @deprecated This function is deprecated and will be removed. */ From 43874fbfb39ed0e08219959e9db63b7db346a2b7 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 20 May 2019 17:21:10 -0700 Subject: [PATCH 08/40] fix AA toggle --- libraries/render-utils/src/AntialiasingEffect.cpp | 6 ++++-- libraries/render-utils/src/AntialiasingEffect.h | 1 + libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index a445ea2343..180e914d60 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -378,6 +378,8 @@ void JitterSample::configure(const Config& config) { } } else if (config.stop) { _sampleSequence.currentIndex = -1; + } else { + _sampleSequence.currentIndex = config.getIndex(); } _scale = config.scale; } @@ -392,10 +394,10 @@ void JitterSample::run(const render::RenderContextPointer& renderContext, Output } } - jitter.x = 0.0f; - jitter.y = 0.0f; if (current >= 0) { jitter = _sampleSequence.offsets[current]; + } else { + jitter = glm::vec2(0.0f); } } diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 8057601317..7d8bbb44d9 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -107,6 +107,7 @@ public: AntialiasingConfig() : render::Job::Config(true) {} void setDebugFXAA(bool debug) { debugFXAAX = (debug ? 0.0f : 1.0f); emit dirty();} + bool debugFXAA() const { return (debugFXAAX == 0.0f ? true : false); } float blend{ 0.25f }; float sharpen{ 0.05f }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d808823d0c..624869bbf5 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -248,7 +248,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Debugging task is happening in the "over" layer after tone mapping and just before HUD { // Debug the bounds of the rendered items, still look at the zbuffer - const auto extraDebugBuffers = RenderDeferredTaskDebug::ExtraBuffers(linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, ambientOcclusionFramebuffer, scatteringResource, velocityBuffer); + const auto extraDebugBuffers = RenderDeferredTaskDebug::ExtraBuffers(linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, ambientOcclusionUniforms, scatteringResource, velocityBuffer); const auto debugInputs = RenderDeferredTaskDebug::Input(fetchedItems, shadowTaskOutputs, lightingStageInputs, lightClusters, prepareDeferredOutputs, extraDebugBuffers, deferredFrameTransform, jitter, lightingModel).asVarying(); task.addJob("DebugRenderDeferredTask", debugInputs); From d9f164ba3b4b9a15d0096b4229d4853c7206efe5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 May 2019 22:00:26 -0700 Subject: [PATCH 09/40] Add support for application config --- interface/src/main.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 11054d25d0..9d8b733ba7 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -75,6 +75,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption helpOption = parser.addHelpOption(); QCommandLineOption urlOption("url", "", "value"); + QCommandLineOption noLauncherOption("no-launcher", "Do not execute the launcher"); QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater"); QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications"); QCommandLineOption runServerOption("runServer", "Whether to run the server"); @@ -84,6 +85,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts ", "path"); parser.addOption(urlOption); + parser.addOption(noLauncherOption); parser.addOption(noUpdaterOption); parser.addOption(checkMinSpecOption); parser.addOption(runServerOption); @@ -106,6 +108,49 @@ int main(int argc, const char* argv[]) { Q_UNREACHABLE(); } + QString applicationPath; + { + // A temporary application instance is needed to get the location of the running executable + // Tests using high_resolution_clock show that this takes about 30-50 microseconds (on my machine, YMMV) + // If we wanted to avoid the QCoreApplication, we would need to write our own + // cross-platform implementation. + QCoreApplication tempApp(argc, const_cast(argv)); + applicationPath = QCoreApplication::applicationDirPath(); + } + + static const QString APPLICATION_CONFIG_FILENAME = "config.json"; + QDir applicationDir(applicationPath); + QFile configFile(applicationDir.filePath(APPLICATION_CONFIG_FILENAME)); + + if (configFile.exists()) { + if (!configFile.open(QIODevice::ReadOnly)) { + qWarning() << "Found application config, but could not open it"; + } else { + auto contents = configFile.readAll(); + QJsonParseError error; + + auto doc = QJsonDocument::fromJson(contents, &error); + if (error.error) { + qWarning() << "Found application config, but could not parse it: " << error.errorString(); + } else { + static const QString LAUNCHER_PATH_KEY = "launcherPath"; + QString launcherPath = doc.object()[LAUNCHER_PATH_KEY].toString(); + if (!launcherPath.isEmpty()) { + if (!parser.isSet(noLauncherOption)) { + qDebug() << "Found a launcherPath in application config. Starting launcher."; + QProcess launcher; + launcher.setProgram(launcherPath); + launcher.startDetached(); + return 0; + } else { + qDebug() << "Found a launcherPath in application config, but the launcher" + " has been suppressed. Continuing normal execution."; + } + } + } + } + } + // Early check for --traceFile argument auto tracer = DependencyManager::set(); const char * traceFile = nullptr; From 19a7d91aef13baf04d1dc9b3fb113c6ad894d1f0 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Mon, 20 May 2019 22:37:25 -0700 Subject: [PATCH 10/40] testing linux cpu info --- libraries/platform/src/LinuxPlatform.cpp | 46 +++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/libraries/platform/src/LinuxPlatform.cpp b/libraries/platform/src/LinuxPlatform.cpp index aa63eb1e08..03952a8655 100644 --- a/libraries/platform/src/LinuxPlatform.cpp +++ b/libraries/platform/src/LinuxPlatform.cpp @@ -9,15 +9,51 @@ #include "LinuxPlatform.h" #include "platformJsonKeys.h" #include - +#include using namespace platform; + +static void getLCpuId( uint32_t* p, uint32_t ax ) +{ + +#if Q_OS_LINUX + __asm __volatile + ( "movl %%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl %%ebx, %%esi" + : "=a" (p[0]), "=S" (p[1]), + "=c" (p[2]), "=d" (p[3]) + : "0" (ax) + ); +#endif +} + void LinuxInstance::enumerateCpu() { json cpu = {}; + + uint32_t cpuInfo[4]={0,0,0,0}; + char CPUBrandString[16]; + char CPUModelString[16]; + char CPUClockString[16]; + uint32_t nExIds; + getLCpuId(cpuInfo, 0x80000000); + nExIds = cpuInfo[0]; + + for (uint32_t i = 0x80000000; i <= nExIds; ++i) { + getLCpuId(cpuInfo, i); + // Interpret CPU brand string + if (i == 0x80000002) { + memcpy(CPUBrandString, cpuInfo, sizeof(cpuInfo)); + } else if (i == 0x80000003) { + memcpy(CPUModelString, cpuInfo, sizeof(cpuInfo)); + } else if (i == 0x80000004) { + memcpy(CPUClockString, cpuInfo, sizeof(cpuInfo)); + } + } - cpu["cpuBrand"] = ""; - cpu["cpuModel"] = ""; - cpu["cpuClockSpeed"] = ""; - cpu["cpuNumCores"] = ""; + cpu["cpuBrand"] = CPUBrandString; + cpu["cpuModel"] = CPUModelString; + cpu["cpuClockSpeed"] = CPUClockString; + cpu["cpuNumCores"] = std::thread::hardware_concurrency(); _cpu.push_back(cpu); } From 47a612b195dc038118dc3d3eb71c422edb4eeeca Mon Sep 17 00:00:00 2001 From: amerhifi Date: Tue, 21 May 2019 07:46:02 -0700 Subject: [PATCH 11/40] testing gpu ident changes --- libraries/platform/src/LinuxPlatform.cpp | 2 +- libraries/shared/src/GPUIdent.cpp | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libraries/platform/src/LinuxPlatform.cpp b/libraries/platform/src/LinuxPlatform.cpp index 03952a8655..20034a4340 100644 --- a/libraries/platform/src/LinuxPlatform.cpp +++ b/libraries/platform/src/LinuxPlatform.cpp @@ -15,7 +15,7 @@ using namespace platform; static void getLCpuId( uint32_t* p, uint32_t ax ) { -#if Q_OS_LINUX +#ifdef Q_OS_LINUX __asm __volatile ( "movl %%ebx, %%esi\n\t" "cpuid\n\t" diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index 773e40aaee..16c95ff9ce 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -28,6 +28,7 @@ #endif +#include #include #include "SharedLogging.h" @@ -83,7 +84,26 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer) _dedicatedMemoryMB = bestVRAM; CGLDestroyRendererInfo(rendererInfo); - +#elif defined(Q_OS_LINUX) +//get gpu name + FILE* stream = popen("system_profiler SPDisplaysDataType | grep Chipset", "r"); + + std::ostringstream hostStream; + while (!feof(stream) && !ferror(stream)) { + char buf[128]; + int bytesRead = fread(buf, 1, 128, stream); + hostStream.write(buf, bytesRead); + } + + QString result = QString::fromStdString(hostStream.str()); + QStringList parts = result.split('\n'); + std::string name; + + for (int i = 0; i < parts.size(); ++i) { + if (parts[i].toLower().contains("radeon") || parts[i].toLower().contains("nvidia")) { + _name=parts[i]; + } + } #elif defined(Q_OS_WIN) struct ConvertLargeIntegerToQString { From 045b0f7cf83552a46042a00727f85044a64865e3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 21 May 2019 07:49:21 -0700 Subject: [PATCH 12/40] check for unloaded model --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index bf0abe92dd..cc6ba0176b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -363,7 +363,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { ShapeType type = getShapeType(); auto model = getModel(); - if (!model) { + if (!model || !model->isLoaded()) { type = SHAPE_TYPE_NONE; } From 5f8122497668841fcabf771b7338529050372776 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Tue, 21 May 2019 08:59:04 -0700 Subject: [PATCH 13/40] did not work on linux, backing out change --- libraries/shared/src/GPUIdent.cpp | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index 16c95ff9ce..dcbc83cfc1 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -84,26 +84,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer) _dedicatedMemoryMB = bestVRAM; CGLDestroyRendererInfo(rendererInfo); -#elif defined(Q_OS_LINUX) -//get gpu name - FILE* stream = popen("system_profiler SPDisplaysDataType | grep Chipset", "r"); - - std::ostringstream hostStream; - while (!feof(stream) && !ferror(stream)) { - char buf[128]; - int bytesRead = fread(buf, 1, 128, stream); - hostStream.write(buf, bytesRead); - } - - QString result = QString::fromStdString(hostStream.str()); - QStringList parts = result.split('\n'); - std::string name; - - for (int i = 0; i < parts.size(); ++i) { - if (parts[i].toLower().contains("radeon") || parts[i].toLower().contains("nvidia")) { - _name=parts[i]; - } - } + #elif defined(Q_OS_WIN) struct ConvertLargeIntegerToQString { From 4f547040c0187ff55042b9d21ddf9ded0a5ff0e2 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Tue, 21 May 2019 09:01:40 -0700 Subject: [PATCH 14/40] removing include --- libraries/shared/src/GPUIdent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index dcbc83cfc1..d5c2f3ec6c 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -28,9 +28,8 @@ #endif -#include -#include +#include #include "SharedLogging.h" GPUIdent GPUIdent::_instance {}; From 56d8e0123fb70f2efc33a54e4ced1b95f197ab08 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Tue, 21 May 2019 09:19:56 -0700 Subject: [PATCH 15/40] resolving qt moc error with propertie missing for android --- interface/src/ui/Stats.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 1939e7fa0e..8fdced40b3 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -320,6 +320,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, nodeListThreadQueueDepth, -1); #else STATS_PROPERTY(bool, eventQueueDebuggingOn, false) + STATS_PROPERTY(int, mainThreadQueueDepth, 0); + STATS_PROPERTY(int, nodeListThreadQueueDepth, 0); #endif // DEBUG_EVENT_QUEUE public: From b3285050eda7fb8080b023a52391b716b8f7126c Mon Sep 17 00:00:00 2001 From: amerhifi Date: Tue, 21 May 2019 09:43:09 -0700 Subject: [PATCH 16/40] moving the properties out of the define since the values are going to be the same either way --- interface/src/ui/Stats.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 8fdced40b3..cb13945320 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -314,14 +314,13 @@ class Stats : public QQuickItem { STATS_PROPERTY(QVector3D, parabolaPicksUpdated, QVector3D(0, 0, 0)) STATS_PROPERTY(QVector3D, collisionPicksUpdated, QVector3D(0, 0, 0)) -#ifdef DEBUG_EVENT_QUEUE - STATS_PROPERTY(bool, eventQueueDebuggingOn, true) STATS_PROPERTY(int, mainThreadQueueDepth, -1); STATS_PROPERTY(int, nodeListThreadQueueDepth, -1); + +#ifdef DEBUG_EVENT_QUEUE + STATS_PROPERTY(bool, eventQueueDebuggingOn, true) #else STATS_PROPERTY(bool, eventQueueDebuggingOn, false) - STATS_PROPERTY(int, mainThreadQueueDepth, 0); - STATS_PROPERTY(int, nodeListThreadQueueDepth, 0); #endif // DEBUG_EVENT_QUEUE public: From 264051ed6d9dfff8f2867aab414574c39a89b7c8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 21 May 2019 10:40:58 -0700 Subject: [PATCH 17/40] fix myavatar setSkeletonModelURL --- assignment-client/src/avatars/ScriptableAvatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 5 +++++ interface/src/avatar/MyAvatar.h | 2 +- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 2 +- libraries/avatars/src/AvatarData.h | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 54e9fa2fba..34dc25914f 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -138,7 +138,7 @@ public: /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const override; - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; + Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; /**jsdoc * @comment Uses the base class's JSDoc. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 39f2d9f332..7ac2103543 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2367,6 +2367,11 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setSkeletonModelURL", Q_ARG(const QUrl&, skeletonModelURL)); + return; + } + _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index bb5e4c17df..5b12885d1f 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -2409,7 +2409,7 @@ private: void updateEyeContactTarget(float deltaTime); // These are made private for MyAvatar so that you will use the "use" methods instead - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; + Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void updatePalms() override {} void lateUpdatePalms(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 61901d662a..adafca1d1f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -339,7 +339,7 @@ public: */ Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const; - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; + Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void setAttachmentData(const QVector& attachmentData) override; void updateDisplayNameAlpha(bool showDisplayName); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 9219c2c03f..e5131ff94b 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1211,7 +1211,7 @@ public: const QString& getDisplayName() const { return _displayName; } const QString& getSessionDisplayName() const { return _sessionDisplayName; } bool getLookAtSnappingEnabled() const { return _lookAtSnappingEnabled; } - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setDisplayName(const QString& displayName); virtual void setSessionDisplayName(const QString& sessionDisplayName) { From 4b15ee9c3a6377de7da308f44c3ec4f644855485 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 21 May 2019 10:45:48 -0700 Subject: [PATCH 18/40] Always calculate tangents --- libraries/model-baker/src/model-baker/Baker.cpp | 12 +++++------- .../CalculateBlendshapeTangentsTask.cpp | 13 +------------ .../model-baker/CalculateBlendshapeTangentsTask.h | 2 +- .../src/model-baker/CalculateMeshTangentsTask.cpp | 14 +------------- .../src/model-baker/CalculateMeshTangentsTask.h | 2 +- 5 files changed, 9 insertions(+), 34 deletions(-) diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index 70269c6401..c896613df5 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -27,7 +27,7 @@ namespace baker { class GetModelPartsTask { public: using Input = hfm::Model::Pointer; - using Output = VaryingSet6, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, QHash, std::vector>; + using Output = VaryingSet5, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector>; using JobModel = Job::ModelIO; void run(const BakeContextPointer& context, const Input& input, Output& output) { @@ -40,8 +40,7 @@ namespace baker { for (int i = 0; i < hfmModelIn->meshes.size(); i++) { blendshapesPerMesh.push_back(hfmModelIn->meshes[i].blendshapes.toStdVector()); } - output.edit4() = hfmModelIn->materials; - output.edit5() = hfmModelIn->joints.toStdVector(); + output.edit4() = hfmModelIn->joints.toStdVector(); } }; @@ -134,17 +133,16 @@ namespace baker { const auto url = modelPartsIn.getN(1); const auto meshIndicesToModelNames = modelPartsIn.getN(2); const auto blendshapesPerMeshIn = modelPartsIn.getN(3); - const auto materials = modelPartsIn.getN(4); - const auto jointsIn = modelPartsIn.getN(5); + const auto jointsIn = modelPartsIn.getN(4); // Calculate normals and tangents for meshes and blendshapes if they do not exist // Note: Normals are never calculated here for OBJ models. OBJ files optionally define normals on a per-face basis, so for consistency normals are calculated beforehand in OBJSerializer. const auto normalsPerMesh = model.addJob("CalculateMeshNormals", meshesIn); - const auto calculateMeshTangentsInputs = CalculateMeshTangentsTask::Input(normalsPerMesh, meshesIn, materials).asVarying(); + const auto calculateMeshTangentsInputs = CalculateMeshTangentsTask::Input(normalsPerMesh, meshesIn).asVarying(); const auto tangentsPerMesh = model.addJob("CalculateMeshTangents", calculateMeshTangentsInputs); const auto calculateBlendshapeNormalsInputs = CalculateBlendshapeNormalsTask::Input(blendshapesPerMeshIn, meshesIn).asVarying(); const auto normalsPerBlendshapePerMesh = model.addJob("CalculateBlendshapeNormals", calculateBlendshapeNormalsInputs); - const auto calculateBlendshapeTangentsInputs = CalculateBlendshapeTangentsTask::Input(normalsPerBlendshapePerMesh, blendshapesPerMeshIn, meshesIn, materials).asVarying(); + const auto calculateBlendshapeTangentsInputs = CalculateBlendshapeTangentsTask::Input(normalsPerBlendshapePerMesh, blendshapesPerMeshIn, meshesIn).asVarying(); const auto tangentsPerBlendshapePerMesh = model.addJob("CalculateBlendshapeTangents", calculateBlendshapeTangentsInputs); // Build the graphics::MeshPointer for each hfm::Mesh diff --git a/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp b/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp index ba8fd94f09..b807aea38f 100644 --- a/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp +++ b/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp @@ -19,7 +19,6 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte const auto& normalsPerBlendshapePerMesh = input.get0(); const auto& blendshapesPerMesh = input.get1(); const auto& meshes = input.get2(); - const auto& materials = input.get3(); auto& tangentsPerBlendshapePerMeshOut = output; tangentsPerBlendshapePerMeshOut.reserve(normalsPerBlendshapePerMesh.size()); @@ -30,16 +29,6 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte tangentsPerBlendshapePerMeshOut.emplace_back(); auto& tangentsPerBlendshapeOut = tangentsPerBlendshapePerMeshOut[tangentsPerBlendshapePerMeshOut.size()-1]; - // Check if we actually need to calculate the tangents, or just append empty arrays - bool needTangents = false; - for (const auto& meshPart : mesh.parts) { - auto materialIt = materials.find(meshPart.materialID); - if (materialIt != materials.end() && (*materialIt).needTangentSpace()) { - needTangents = true; - break; - } - } - for (size_t j = 0; j < blendshapes.size(); j++) { const auto& blendshape = blendshapes[j]; const auto& tangentsIn = blendshape.tangents; @@ -54,7 +43,7 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte } // Check if we can and should calculate tangents (we need normals to calculate the tangents) - if (normals.empty() || !needTangents) { + if (normals.empty()) { continue; } tangentsOut.resize(normals.size()); diff --git a/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.h b/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.h index c24b41d2d9..4ad8fee036 100644 --- a/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.h +++ b/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.h @@ -18,7 +18,7 @@ // Calculate blendshape tangents if not already present in the blendshape class CalculateBlendshapeTangentsTask { public: - using Input = baker::VaryingSet4, baker::BlendshapesPerMesh, std::vector, QHash>; + using Input = baker::VaryingSet3, baker::BlendshapesPerMesh, std::vector>; using Output = std::vector; using JobModel = baker::Job::ModelIO; diff --git a/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp b/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp index d2144a0e30..58c54c9189 100644 --- a/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp +++ b/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp @@ -13,21 +13,9 @@ #include "ModelMath.h" -bool needTangents(const hfm::Mesh& mesh, const QHash& materials) { - // Check if we actually need to calculate the tangents - for (const auto& meshPart : mesh.parts) { - auto materialIt = materials.find(meshPart.materialID); - if (materialIt != materials.end() && (*materialIt).needTangentSpace()) { - return true; - } - } - return false; -} - void CalculateMeshTangentsTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { const auto& normalsPerMesh = input.get0(); const std::vector& meshes = input.get1(); - const auto& materials = input.get2(); auto& tangentsPerMeshOut = output; tangentsPerMeshOut.reserve(meshes.size()); @@ -42,7 +30,7 @@ void CalculateMeshTangentsTask::run(const baker::BakeContextPointer& context, co // Otherwise confirm if we have the normals needed, and need to calculate the tangents if (!tangentsIn.empty()) { tangentsOut = tangentsIn.toStdVector(); - } else if (!normals.empty() && needTangents(mesh, materials)) { + } else if (!normals.empty()) { tangentsOut.resize(normals.size()); baker::calculateTangents(mesh, [&mesh, &normals, &tangentsOut](int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec2* outTexCoords, glm::vec3& outNormal) { diff --git a/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.h b/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.h index b8fdb7d5f4..2ad5759476 100644 --- a/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.h +++ b/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.h @@ -22,7 +22,7 @@ class CalculateMeshTangentsTask { public: using NormalsPerMesh = std::vector>; - using Input = baker::VaryingSet3, QHash>; + using Input = baker::VaryingSet2>; using Output = baker::TangentsPerMesh; using JobModel = baker::Job::ModelIO; From cb43a0efea91519b12a03ea171fc19e3fa04053b Mon Sep 17 00:00:00 2001 From: amerhifi Date: Tue, 21 May 2019 10:59:33 -0700 Subject: [PATCH 19/40] trying to bypass android error with output constraint --- libraries/platform/src/LinuxPlatform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/platform/src/LinuxPlatform.cpp b/libraries/platform/src/LinuxPlatform.cpp index 20034a4340..e376a45165 100644 --- a/libraries/platform/src/LinuxPlatform.cpp +++ b/libraries/platform/src/LinuxPlatform.cpp @@ -15,7 +15,7 @@ using namespace platform; static void getLCpuId( uint32_t* p, uint32_t ax ) { -#ifdef Q_OS_LINUX +#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) __asm __volatile ( "movl %%ebx, %%esi\n\t" "cpuid\n\t" From dddb171b52040a3e7081424a35a7be56319eb0fd Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Tue, 21 May 2019 11:23:04 -0700 Subject: [PATCH 20/40] BUGZ-223 - Physics was not starting in TheSpot-dev This was caused by two issues involving the SafeLanding system: * Race condition on domain load The domain is hard-reset twice during typical start, first after login completes, and second, when ice/domain renegotiation occurs Entities added during the first reset caused an add to the safe landing system which, because those adds were queued, possibly happened after the second hard reset. Second, Safe landing checks whether physics is ready on entities before letting physics start. Physics is ready when the entities have a physics shape associated with them if they're static meshes. The physics shape is only generated if the entity is in Region 1 or 2. Safe landing, however, was not checking the region of the entity and was therefore waiting on entities that were not in region 1 or 2 --- interface/src/octree/SafeLanding.cpp | 46 +++++++++++++++------------- interface/src/octree/SafeLanding.h | 3 +- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 479c2a5860..26bd3ac41f 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -10,7 +10,6 @@ // #include "SafeLanding.h" - #include #include "EntityTreeRenderer.h" @@ -35,24 +34,26 @@ bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const } void SafeLanding::startEntitySequence(QSharedPointer entityTreeRenderer) { - auto entityTree = entityTreeRenderer->getTree(); - if (entityTree) { - Locker lock(_lock); - _entityTree = entityTree; - _trackedEntities.clear(); - _trackingEntities = true; - _maxTrackedEntityCount = 0; - connect(std::const_pointer_cast(_entityTree).get(), - &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity); - connect(std::const_pointer_cast(_entityTree).get(), - &EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity); + if (!entityTreeRenderer.isNull()) { + auto entityTree = entityTreeRenderer->getTree(); + if (entityTree) { + Locker lock(_lock); + _entityTreeRenderer = entityTreeRenderer; + _trackedEntities.clear(); + _trackingEntities = true; + _maxTrackedEntityCount = 0; + connect(std::const_pointer_cast(entityTree).get(), + &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity, Qt::DirectConnection); + connect(std::const_pointer_cast(entityTree).get(), + &EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity); - _sequenceNumbers.clear(); - _initialStart = INVALID_SEQUENCE; - _initialEnd = INVALID_SEQUENCE; - _startTime = usecTimestampNow(); - EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority); + _sequenceNumbers.clear(); + _initialStart = INVALID_SEQUENCE; + _initialEnd = INVALID_SEQUENCE; + _startTime = usecTimestampNow(); + EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority); + } } } @@ -70,7 +71,7 @@ void SafeLanding::stopEntitySequence() { void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { if (_trackingEntities) { Locker lock(_lock); - EntityItemPointer entity = _entityTree->findEntityByID(entityID); + EntityItemPointer entity = _entityTreeRenderer->getTree()->findEntityByID(entityID); if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) { @@ -111,7 +112,7 @@ bool SafeLanding::isLoadSequenceComplete() { Locker lock(_lock); _initialStart = INVALID_SEQUENCE; _initialEnd = INVALID_SEQUENCE; - _entityTree = nullptr; + _entityTreeRenderer.clear(); _trackingEntities = false; // Don't track anything else that comes in. EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority); } @@ -158,7 +159,7 @@ bool SafeLanding::isSequenceNumbersComplete() { return false; } -bool isEntityPhysicsReady(const EntityItemPointer& entity) { +bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { if (entity && !entity->getCollisionless()) { const auto& entityType = entity->getType(); if (entityType == EntityTypes::Model) { @@ -168,7 +169,10 @@ bool isEntityPhysicsReady(const EntityItemPointer& entity) { bool hasAABox; entity->getAABox(hasAABox); if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) { - return (!entity->shouldBePhysical() || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad()); + auto space = _entityTreeRenderer->getWorkloadSpace(); + uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : workload::Region::INVALID; + bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad()); } } } diff --git a/interface/src/octree/SafeLanding.h b/interface/src/octree/SafeLanding.h index 51357b60ff..428ca15bdc 100644 --- a/interface/src/octree/SafeLanding.h +++ b/interface/src/octree/SafeLanding.h @@ -38,13 +38,14 @@ private slots: private: bool isSequenceNumbersComplete(); + bool isEntityPhysicsReady(const EntityItemPointer& entity); void debugDumpSequenceIDs() const; bool isEntityLoadingComplete(); std::mutex _lock; using Locker = std::lock_guard; bool _trackingEntities { false }; - EntityTreePointer _entityTree; + QSharedPointer _entityTreeRenderer; using EntityMap = std::map; EntityMap _trackedEntities; From 10db88c07b6914d53cd4dde0afe504570e25147b Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Tue, 21 May 2019 12:32:01 -0700 Subject: [PATCH 21/40] Fix ubuntu warning --- interface/src/octree/SafeLanding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 26bd3ac41f..de552b7b84 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -170,7 +170,7 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { entity->getAABox(hasAABox); if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) { auto space = _entityTreeRenderer->getWorkloadSpace(); - uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : workload::Region::INVALID; + uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID; bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad()); } From 5749392e838da5ffccf481f8e30902c58b2c0e7c Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 21 May 2019 14:10:27 -0700 Subject: [PATCH 22/40] New bg color; Final status indicator design; Fixed HMD icon --- .../SimplifiedConstants.qml | 2 +- .../simplifiedUI/topBar/SimplifiedTopBar.qml | 41 +++++++++------- .../hifi/simplifiedUI/topBar/images/focus.svg | 13 +++++ .../AbstractHMDScriptingInterface.h | 2 +- scripts/system/simplifiedUI/simplifiedUI.js | 49 +++++++++++-------- 5 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 interface/resources/qml/hifi/simplifiedUI/topBar/images/focus.svg diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml index 5d71d8bdb2..752c989500 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml @@ -147,7 +147,7 @@ QtObject { } readonly property color darkSeparator: "#595959" - readonly property color darkBackground: "#1A1A1A" + readonly property color darkBackground: "#000000" readonly property color darkBackgroundHighlight: "#575757" readonly property color highlightOnDark: Qt.rgba(1, 1, 1, 0.2) readonly property color white: "#FFFFFF" diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index ae50a746b6..c0511c69a4 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -246,15 +246,17 @@ Rectangle { id: statusButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.left: outputDeviceButtonContainer.right - anchors.leftMargin: 2 - width: 32 + anchors.leftMargin: 8 + width: 36 height: width Rectangle { id: statusButton - property string currentStatus: "" + property string currentStatus anchors.centerIn: parent - width: 20 + anchors.horizontalCenterOffset: 1 + anchors.verticalCenterOffset: 2 + width: 13 height: width radius: width/2 visible: false @@ -262,20 +264,31 @@ Rectangle { ColorOverlay { anchors.fill: statusButton - opacity: statusButtonMouseArea.containsMouse ? 1.0 : 0.7 + opacity: statusButton.currentStatus ? 1 : 0 source: statusButton color: if (statusButton.currentStatus === "busy") { - "red" + "#ff001a" } else if (statusButton.currentStatus === "available") { - "green" - } else { - "yellow" + "#009036" + } else if (statusButton.currentStatus) { + "#ffed00" } } + Image { + id: focusIcon + source: "./images/focus.svg" + opacity: statusButtonMouseArea.containsMouse ? 1.0 : (statusButton.currentStatus === "busy" ? 0.7 : 0.3) + anchors.centerIn: parent + width: 36 + height: 20 + fillMode: Image.PreserveAspectFit + } + MouseArea { id: statusButtonMouseArea anchors.fill: parent + enabled: statusButton.currentStatus hoverEnabled: true onEntered: { Tablet.playSound(TabletEnums.ButtonHover); @@ -330,11 +343,6 @@ Rectangle { Tablet.playSound(TabletEnums.ButtonClick); var displayPluginCount = Window.getDisplayPluginCount(); if (HMD.active) { - // This next line seems backwards and shouldn't be necessary - the NOTIFY handler should - // result in `displayModeImage.source` changing automatically - but that's not working. - // This is working. So, I'm keeping it. - displayModeImage.source = "./images/vrMode.svg"; - // Switch to desktop mode - selects first VR display plugin for (var i = 0; i < displayPluginCount; i++) { if (!Window.isDisplayPluginHmd(i)) { @@ -343,11 +351,6 @@ Rectangle { } } } else { - // This next line seems backwards and shouldn't be necessary - the NOTIFY handler should - // result in `displayModeImage.source` changing automatically - but that's not working. - // This is working. So, I'm keeping it. - displayModeImage.source = "./images/desktopMode.svg"; - // Switch to VR mode - selects first HMD display plugin for (var i = 0; i < displayPluginCount; i++) { if (Window.isDisplayPluginHmd(i)) { diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/focus.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/focus.svg new file mode 100644 index 0000000000..f7950650c6 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/focus.svg @@ -0,0 +1,13 @@ + + + + + + image/svg+xml + + + + + + + diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h index c1253f825f..de6141c9d8 100644 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h +++ b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h @@ -15,7 +15,7 @@ // These properties have JSDoc documentation in HMDScriptingInterface.h. class AbstractHMDScriptingInterface : public QObject { Q_OBJECT - Q_PROPERTY(bool active READ isHMDMode NOTIFY mountedChanged) + Q_PROPERTY(bool active READ isHMDMode NOTIFY displayModeChanged) Q_PROPERTY(float ipd READ getIPD) Q_PROPERTY(float eyeHeight READ getEyeHeight) Q_PROPERTY(float playerHeight READ getPlayerHeight) diff --git a/scripts/system/simplifiedUI/simplifiedUI.js b/scripts/system/simplifiedUI/simplifiedUI.js index f208fcaf1e..fbf9972fc3 100644 --- a/scripts/system/simplifiedUI/simplifiedUI.js +++ b/scripts/system/simplifiedUI/simplifiedUI.js @@ -276,8 +276,21 @@ function setOutputMuted(outputMuted) { } -function toggleStatus() { - +var WAIT_FOR_TOP_BAR_MS = 1000; +function sendLocalStatusToQml() { + var currentStatus = si.getLocalStatus(); + + if (topBarWindow && currentStatus) { + topBarWindow.sendToQml({ + "source": "simplifiedUI.js", + "method": "updateStatusButton", + "data": { + "currentStatus": currentStatus + } + }); + } else { + Script.setTimeout(sendLocalStatusToQml, WAIT_FOR_TOP_BAR_MS); + } } @@ -355,13 +368,19 @@ function loadSimplifiedTopBar() { topBarWindow.fromQml.connect(onMessageFromTopBar); topBarWindow.closed.connect(onTopBarClosed); - topBarWindow.sendToQml({ - "source": "simplifiedUI.js", - "method": "updateOutputMuted", - "data": { - "outputMuted": isOutputMuted() - } - }) + // The eventbridge takes a nonzero time to initialize, so we have to wait a bit + // for the QML to load and for that to happen before updating the UI. + Script.setTimeout(function() { + topBarWindow.sendToQml({ + "source": "simplifiedUI.js", + "method": "updateOutputMuted", + "data": { + "outputMuted": isOutputMuted() + } + }); + + sendLocalStatusToQml(); + }, WAIT_FOR_TOP_BAR_MS); } @@ -446,17 +465,7 @@ function ensureFirstPersonCameraInHMD(isHMDMode) { function onStatusChanged() { - var currentStatus = si.getLocalStatus(); - - if (topBarWindow) { - topBarWindow.sendToQml({ - "source": "simplifiedUI.js", - "method": "updateStatusButton", - "data": { - "currentStatus": currentStatus - } - }); - } + sendLocalStatusToQml(); } From bad421cb59a6b6de53737d8e6a58c432d4380530 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Tue, 21 May 2019 16:58:49 -0700 Subject: [PATCH 23/40] Fix crash when adding a tracked entity to the safe landing code when it's not been fully set up yet. --- interface/src/octree/SafeLanding.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index de552b7b84..2e11de508b 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -71,6 +71,11 @@ void SafeLanding::stopEntitySequence() { void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { if (_trackingEntities) { Locker lock(_lock); + + if (_entityTreeRenderer.isNull() || _entityTreeRenderer->getTree() == nullptr) { + return; + } + EntityItemPointer entity = _entityTreeRenderer->getTree()->findEntityByID(entityID); if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) { From 1f3bffca4aeb32ba61198bbc496e5969020c6c63 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 May 2019 12:08:14 +1200 Subject: [PATCH 24/40] Settings JSDoc polish --- interface/src/scripting/SettingsScriptingInterface.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h index e907e550f3..25a8b627cb 100644 --- a/interface/src/scripting/SettingsScriptingInterface.h +++ b/interface/src/scripting/SettingsScriptingInterface.h @@ -16,7 +16,8 @@ #include /**jsdoc - * The Settings API provides a facility to store and retrieve values that persist between Interface runs. + * The Settings API provides a facility to store and retrieve values that persist between Interface runs. + * * @namespace Settings * * @hifi-interface @@ -33,7 +34,7 @@ public: public slots: /**jsdoc - * Retrieve the value from a named setting. + * Retrieves the value from a named setting. * @function Settings.getValue * @param {string} key - The name of the setting. * @param {string|number|boolean|object} [defaultValue=""] - The value to return if the setting doesn't exist. @@ -50,8 +51,8 @@ public slots: QVariant getValue(const QString& setting, const QVariant& defaultValue); /**jsdoc - * Store a value in a named setting. If the setting already exists its value is overwritten, otherwise a new setting is - * created. If the value is set to null or undefined, the setting is deleted. + * Stores a value in a named setting. If the setting already exists, its value is overwritten. If the value is + * null or undefined, the setting is deleted. * @function Settings.setValue * @param {string} key - The name of the setting. Be sure to use a unique name if creating a new setting. * @param {string|number|boolean|object|undefined} value - The value to store in the setting. If null or From 30da972a14b7bae2793af807c0e3e80c32fedd97 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 May 2019 14:13:42 +1200 Subject: [PATCH 25/40] Snapshot JSDoc --- .../src/scripting/WindowScriptingInterface.h | 9 +++++++-- interface/src/ui/Snapshot.h | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index de2441ae62..5e11d13634 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -313,8 +313,9 @@ public slots: * Takes a snapshot of the current Interface view from the primary camera. When a still image only is captured, * {@link Window.stillSnapshotTaken|stillSnapshotTaken} is emitted; when a still image plus moving images are captured, * {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted} - * are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings > - * General > Snapshots. + * are emitted. + *

Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the + * {@link Snapshot} API.

* * @function Window.takeSnapshot * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} @@ -358,6 +359,8 @@ public slots: /**jsdoc * Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API. + *

Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the + * {@link Snapshot} API.

* @function Window.takeSecondaryCameraSnapshot * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. @@ -372,6 +375,8 @@ public slots: /**jsdoc * Takes a 360° snapshot at a given position for the secondary camera. The secondary camera does not need to have been * set up. + *

Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the + * {@link Snapshot} API.

* @function Window.takeSecondaryCamera360Snapshot * @param {Vec3} cameraPosition - The position of the camera for the snapshot. * @param {boolean} [cubemapOutputFormat=false] - If true then the snapshot is saved as a cube map image, diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index f13f4cd587..73c5a8e3c5 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -38,6 +38,10 @@ private: /**jsdoc + * The Snapshot API provides access to the path that snapshots are saved to. This path is that provided in + * Settings > General > Snapshots. Snapshots may be taken using Window API functions such as + * {@link Window.takeSnapshot}. + * * @namespace Snapshot * * @hifi-interface @@ -64,23 +68,31 @@ public: signals: /**jsdoc + * Triggered when the path that snapshots are saved to is changed. * @function Snapshot.snapshotLocationSet - * @param {string} location + * @param {string} location - The new snapshots location. * @returns {Signal} + * @example Report when the snapshots location is changed. + * // Run this script then change the snapshots location in Settings > General > Snapshots. + * Snapshot.snapshotLocationSet.connect(function (path) { + * print("New snapshot location: " + path); + * }); */ void snapshotLocationSet(const QString& value); public slots: /**jsdoc + * Gets the path that snapshots are saved to. * @function Snapshot.getSnapshotsLocation - * @returns {string} + * @returns {string} The path to save snapshots to. */ Q_INVOKABLE QString getSnapshotsLocation(); /**jsdoc + * Sets the path that snapshots are saved to. * @function Snapshot.setSnapshotsLocation - * @param {String} location + * @param {String} location - The path to save snapshots to. */ Q_INVOKABLE void setSnapshotsLocation(const QString& location); From a246e408156722096b0254112b0afb8bbdbacc61 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 May 2019 14:14:06 +1200 Subject: [PATCH 26/40] Fix taking snapshot example --- interface/src/scripting/WindowScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 5e11d13634..0c2b494b0b 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -352,7 +352,7 @@ public slots: * var notify = true; * var animated = true; * var aspect = 1920 / 1080; - * var filename = ""; + * var filename = "example-snapshot"; * Window.takeSnapshot(notify, animated, aspect, filename); */ void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString()); From 6f7557b00d57cbdad360fd059eb706d42f7071fd Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 09:56:28 -0700 Subject: [PATCH 27/40] Implement BUGZ-305 and BUGZ-306 --- .../simplifiedUI/topBar/SimplifiedTopBar.qml | 4 ++++ .../simplifiedStatusIndicator.js | 19 +++++++++---------- scripts/system/simplifiedUI/simplifiedUI.js | 4 ++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index c0511c69a4..66270cc325 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -230,6 +230,10 @@ Rectangle { Tablet.playSound(TabletEnums.ButtonClick); outputDeviceButton.outputMuted = !outputDeviceButton.outputMuted; + if (outputDeviceButton.outputMuted && !AudioScriptingInterface.muted) { + AudioScriptingInterface.muted = true; + } + sendToScript({ "source": "SimplifiedTopBar.qml", "method": "setOutputMuted", diff --git a/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js index a56e9f3a24..9968260034 100644 --- a/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js +++ b/scripts/system/simplifiedUI/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -57,22 +57,21 @@ function simplifiedStatusIndicator(properties) { that.statusChanged(); } + var queryParamString = "type=heartbeat"; + queryParamString += "&username=" + AccountServices.username; + var displayNameToSend = MyAvatar.sessionDisplayName; - queryParamString += currentStatus; if (displayNameToSend === "") { displayNameToSend = MyAvatar.displayName; } - - var queryParamString = "type=heartbeat"; - queryParamString += "&username=" + AccountServices.username; queryParamString += "&displayName=" + displayNameToSend; - queryParamString += "&status="; - queryParamString += currentStatus; + queryParamString += "&status=" + currentStatus; + queryParamString += "&organization=" + location.hostname; var uri = REQUEST_URL + "?" + queryParamString; if (DEBUG) { - console.log("setStatus: " + uri); + console.log("simplifiedStatusIndicator: setStatus: " + uri); } request({ @@ -95,7 +94,7 @@ function simplifiedStatusIndicator(properties) { var uri = REQUEST_URL + "?" + queryParamString; if (DEBUG) { - console.log("getStatus: " + uri); + console.log("simplifiedStatusIndicator: getStatus: " + uri); } request({ @@ -173,7 +172,7 @@ function simplifiedStatusIndicator(properties) { var uri = REQUEST_URL + "?" + queryParamString; if (DEBUG) { - console.log("simplifiedStatusIndicator onDomainChanged: " + uri); + console.log("simplifiedStatusIndicator: onDomainChanged: " + uri); } request({ @@ -184,7 +183,7 @@ function simplifiedStatusIndicator(properties) { } else { // successfully sent updateLocation if (DEBUG) { - console.log("Successfully updated location after domain change."); + console.log("simplifiedStatusIndicator: Successfully updated location after domain change."); } } }); diff --git a/scripts/system/simplifiedUI/simplifiedUI.js b/scripts/system/simplifiedUI/simplifiedUI.js index fbf9972fc3..94eb9f84fd 100644 --- a/scripts/system/simplifiedUI/simplifiedUI.js +++ b/scripts/system/simplifiedUI/simplifiedUI.js @@ -469,8 +469,8 @@ function onStatusChanged() { } -var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js"); -var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js"); +var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); +var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()); var si; var oldShowAudioTools; var oldShowBubbleTools; From 3849450c6669771cd05d90e6be05d21f512caefa Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Wed, 22 May 2019 11:57:08 -0700 Subject: [PATCH 28/40] Fix crash calculating tangents without texcoords --- .../src/model-baker/CalculateBlendshapeTangentsTask.cpp | 4 ++-- .../model-baker/src/model-baker/CalculateMeshTangentsTask.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp b/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp index b807aea38f..905de9b5a7 100644 --- a/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp +++ b/libraries/model-baker/src/model-baker/CalculateBlendshapeTangentsTask.cpp @@ -42,8 +42,8 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte continue; } - // Check if we can and should calculate tangents (we need normals to calculate the tangents) - if (normals.empty()) { + // Check if we can calculate tangents (we need normals and texcoords to calculate the tangents) + if (normals.empty() || normals.size() != (size_t)mesh.texCoords.size()) { continue; } tangentsOut.resize(normals.size()); diff --git a/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp b/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp index 58c54c9189..297d8cbde7 100644 --- a/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp +++ b/libraries/model-baker/src/model-baker/CalculateMeshTangentsTask.cpp @@ -27,10 +27,10 @@ void CalculateMeshTangentsTask::run(const baker::BakeContextPointer& context, co auto& tangentsOut = tangentsPerMeshOut[tangentsPerMeshOut.size()-1]; // Check if we already have tangents and therefore do not need to do any calculation - // Otherwise confirm if we have the normals needed, and need to calculate the tangents + // Otherwise confirm if we have the normals and texcoords needed if (!tangentsIn.empty()) { tangentsOut = tangentsIn.toStdVector(); - } else if (!normals.empty()) { + } else if (!normals.empty() && mesh.vertices.size() == mesh.texCoords.size()) { tangentsOut.resize(normals.size()); baker::calculateTangents(mesh, [&mesh, &normals, &tangentsOut](int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec2* outTexCoords, glm::vec3& outNormal) { From 30c13fd9882a2453c88474370b566fd346ae40a5 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 12:01:38 -0700 Subject: [PATCH 29/40] Fix environment volume slider (BUGZ-213); optimize sliders --- .../simplifiedUI/settingsApp/audio/Audio.qml | 55 +++++++++++++++---- .../simplifiedControls/Slider.qml | 1 + 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml index da924615e3..3e2e4bf752 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml @@ -68,57 +68,88 @@ Flickable { SimplifiedControls.Slider { id: peopleVolume + property real lastValueSent anchors.left: parent.left anchors.right: parent.right Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin height: 30 labelText: "People Volume" - from: -60 - to: 10 + from: -60.0 + to: 20.0 defaultValue: 0.0 + stepSize: 5.0 value: AudioScriptingInterface.getAvatarGain() live: true + function updatePeopleGain(sliderValue) { + if (AudioScriptingInterface.getAvatarGain() !== sliderValue) { + AudioScriptingInterface.setAvatarGain(sliderValue); + } + } onValueChanged: { - if (AudioScriptingInterface.getAvatarGain() != peopleVolume.value) { - AudioScriptingInterface.setAvatarGain(peopleVolume.value); + updatePeopleGain(value); + } + onPressedChanged: { + if (!pressed) { + updatePeopleGain(value); } } } SimplifiedControls.Slider { id: environmentVolume + property real lastValueSent anchors.left: parent.left anchors.right: parent.right Layout.topMargin: 2 height: 30 labelText: "Environment Volume" - from: -60 - to: 10 + from: -60.0 + to: 20.0 defaultValue: 0.0 + stepSize: 5.0 value: AudioScriptingInterface.getInjectorGain() live: true + function updateEnvironmentGain(sliderValue) { + if (AudioScriptingInterface.getInjectorGain() !== sliderValue) { + AudioScriptingInterface.setInjectorGain(sliderValue); + AudioScriptingInterface.setLocalInjectorGain(sliderValue); + } + } onValueChanged: { - if (AudioScriptingInterface.getInjectorGain() != environmentVolume.value) { - AudioScriptingInterface.setInjectorGain(environmentVolume.value); + updateEnvironmentGain(value); + } + onPressedChanged: { + if (!pressed) { + updateEnvironmentGain(value); } } } SimplifiedControls.Slider { id: systemSoundVolume + property real lastValueSent anchors.left: parent.left anchors.right: parent.right Layout.topMargin: 2 height: 30 labelText: "System Sound Volume" - from: -60 - to: 10 + from: -60.0 + to: 20.0 defaultValue: 0.0 + stepSize: 5.0 value: AudioScriptingInterface.getSystemInjectorGain() live: true + function updateSystemGain(sliderValue) { + if (AudioScriptingInterface.getSystemInjectorGain() !== sliderValue) { + AudioScriptingInterface.setSystemInjectorGain(sliderValue); + } + } onValueChanged: { - if (AudioScriptingInterface.getSystemInjectorGain() != systemSoundVolume.value) { - AudioScriptingInterface.setSystemInjectorGain(systemSoundVolume.value); + updateSystemGain(value); + } + onPressedChanged: { + if (!pressed) { + updateSystemGain(value); } } } diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml index 2b1dc68261..38b114e9d2 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml @@ -30,6 +30,7 @@ Item { property alias live: sliderControl.live property alias stepSize: sliderControl.stepSize property alias snapMode: sliderControl.snapMode + property alias pressed: sliderControl.pressed property real defaultValue: 0.0 HifiStylesUit.GraphikRegular { From 4ca77ba3ac8801b93266e619e3566b65dace8779 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Wed, 22 May 2019 13:51:43 -0700 Subject: [PATCH 30/40] BUGZ-322 - add domain checkin lag logging --- domain-server/src/DomainGatekeeper.cpp | 5 +- domain-server/src/DomainServer.cpp | 6 ++ domain-server/src/DomainServerNodeData.h | 5 +- domain-server/src/NodeConnectionData.cpp | 2 + domain-server/src/NodeConnectionData.h | 1 + libraries/networking/src/NodeList.cpp | 82 ++++++++++++------- .../networking/src/udt/PacketHeaders.cpp | 4 +- libraries/networking/src/udt/PacketHeaders.h | 6 +- 8 files changed, 77 insertions(+), 34 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 29656f4465..75399d1a9b 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -358,7 +358,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo nodeData->setNodeVersion(it->second.getNodeVersion()); nodeData->setHardwareAddress(nodeConnection.hardwareAddress); nodeData->setMachineFingerprint(nodeConnection.machineFingerprint); - + nodeData->setLastDomainCheckinTimestamp(nodeConnection.lastPingTimestamp); nodeData->setWasAssigned(true); // cleanup the PendingAssignedNodeData for this assignment now that it's connecting @@ -499,6 +499,9 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect // set the machine fingerprint passed in the connect request nodeData->setMachineFingerprint(nodeConnection.machineFingerprint); + // set the last ping timestamp passed in the connect request + nodeData->setLastDomainCheckinTimestamp(nodeConnection.lastPingTimestamp); + // also add an interpolation to DomainServerNodeData so that servers can get username in stats nodeData->addOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, uuidStringWithoutCurlyBraces(newNode->getUUID()), username); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 051dd989f5..37643cc372 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1068,6 +1068,8 @@ void DomainServer::processListRequestPacket(QSharedPointer mess // update the connecting hostname in case it has changed nodeData->setPlaceName(nodeRequestData.placeName); + nodeData->setLastDomainCheckinTimestamp(nodeRequestData.lastPingTimestamp); + sendDomainListToNode(sendingNode, message->getSenderSockAddr()); } @@ -1174,6 +1176,10 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); + domainListStream << nodeData->getLastDomainCheckinTimestamp(); + + domainListStream << usecTimestampNow(); + // store the nodeInterestSet on this DomainServerNodeData, in case it has changed auto& nodeInterestSet = nodeData->getNodeInterestSet(); diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index f465cceb96..370886cbce 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -61,6 +61,9 @@ public: void setMachineFingerprint(const QUuid& machineFingerprint) { _machineFingerprint = machineFingerprint; } const QUuid& getMachineFingerprint() { return _machineFingerprint; } + void setLastDomainCheckinTimestamp(quint64 lastDomainCheckinTimestamp) { _lastDomainCheckinTimestamp = lastDomainCheckinTimestamp; } + quint64 getLastDomainCheckinTimestamp() { return _lastDomainCheckinTimestamp; } + void addOverrideForKey(const QString& key, const QString& value, const QString& overrideValue); void removeOverrideForKey(const QString& key, const QString& value); @@ -93,7 +96,7 @@ private: QString _nodeVersion; QString _hardwareAddress; QUuid _machineFingerprint; - + quint64 _lastDomainCheckinTimestamp; QString _placeName; bool _wasAssigned { false }; diff --git a/domain-server/src/NodeConnectionData.cpp b/domain-server/src/NodeConnectionData.cpp index 0a3782d79b..b3ea005bd1 100644 --- a/domain-server/src/NodeConnectionData.cpp +++ b/domain-server/src/NodeConnectionData.cpp @@ -36,6 +36,8 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c // now the machine fingerprint dataStream >> newHeader.machineFingerprint; } + + dataStream >> newHeader.lastPingTimestamp; dataStream >> newHeader.nodeType >> newHeader.publicSockAddr >> newHeader.localSockAddr diff --git a/domain-server/src/NodeConnectionData.h b/domain-server/src/NodeConnectionData.h index dd9ca6b650..96e81839c6 100644 --- a/domain-server/src/NodeConnectionData.h +++ b/domain-server/src/NodeConnectionData.h @@ -22,6 +22,7 @@ public: bool isConnectRequest = true); QUuid connectUUID; + quint64 lastPingTimestamp; NodeType_t nodeType; HifiSockAddr publicSockAddr; HifiSockAddr localSockAddr; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index b3862e4252..11c7ca53b7 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -412,6 +412,8 @@ void NodeList::sendDomainServerCheckIn() { packetStream << FingerprintUtils::getMachineFingerprint(); } + packetStream << usecTimestampNow(); + // pack our data to send to the domain-server including // the hostname information (so the domain-server can see which place name we came in on) packetStream << _ownerType.load() << publicSockAddr << localSockAddr << _nodeTypesOfInterest.toList(); @@ -618,32 +620,14 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer message) { - if (_domainHandler.getSockAddr().isNull()) { - qWarning() << "IGNORING DomainList packet while not connected to a Domain Server"; - // refuse to process this packet if we aren't currently connected to the DS - return; - } - - // this is a packet from the domain server, reset the count of un-replied check-ins - _domainHandler.clearPendingCheckins(); - - // emit our signal so listeners know we just heard from the DS - emit receivedDomainServerList(); - - DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList); + // parse header information QDataStream packetStream(message->getMessage()); // grab the domain's ID from the beginning of the packet QUuid domainUUID; packetStream >> domainUUID; - if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) { - // Recieved packet from different domain. - qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID(); - return; - } - Node::LocalID domainLocalID; packetStream >> domainLocalID; @@ -654,6 +638,57 @@ void NodeList::processDomainServerList(QSharedPointer message) packetStream >> newUUID; packetStream >> newLocalID; + // pull the permissions/right/privileges for this node out of the stream + NodePermissions newPermissions; + packetStream >> newPermissions; + setPermissions(newPermissions); + // Is packet authentication enabled? + bool isAuthenticated; + packetStream >> isAuthenticated; + setAuthenticatePackets(isAuthenticated); + + quint64 connectRequestTimestamp; + quint64 now = usecTimestampNow(); + packetStream >> connectRequestTimestamp; + quint64 pingLagTime = (now - connectRequestTimestamp) / USECS_PER_MSEC; + quint64 domainServerPingReceiveTime; + + packetStream >> domainServerPingReceiveTime; + quint64 domainServerRequestLag = (domainServerPingReceiveTime - connectRequestTimestamp) / USECS_PER_MSEC; + quint64 domainServerResponseLag = (now - domainServerPingReceiveTime) / USECS_PER_MSEC; + + if (_domainHandler.getSockAddr().isNull()) { + qWarning(networking) << "IGNORING DomainList packet while not connected to a Domain Server: sent " << pingLagTime << " msec ago."; + qWarning(networking) << "DomainList request lag (with skew): " << domainServerRequestLag << "msec"; + qWarning(networking) << "DomainList response lag (with skew): " << domainServerResponseLag << "msec"; + // refuse to process this packet if we aren't currently connected to the DS + return; + } + + // warn if ping lag is getting long + if (pingLagTime > MSECS_PER_SECOND) { + qCDebug(networking) << "DomainList ping is lagging: " << pingLagTime << "msec"; + qCDebug(networking) << "DomainList request lag (with skew): " << domainServerRequestLag << "msec"; + qCDebug(networking) << "DomainList response lag (with skew): " << domainServerResponseLag << "msec"; + } + + // this is a packet from the domain server, reset the count of un-replied check-ins + _domainHandler.clearPendingCheckins(); + + // emit our signal so listeners know we just heard from the DS + emit receivedDomainServerList(); + + DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList); + + if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) { + // Recieved packet from different domain. + qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" + << _domainHandler.getUUID() << ": sent " << pingLagTime << " msec ago."; + qWarning(networking) << "DomainList request lag (with skew): " << domainServerRequestLag << "msec"; + qWarning(networking) << "DomainList response lag (with skew): " << domainServerResponseLag << "msec"; + return; + } + // when connected, if the session ID or local ID were not null and changed, we should reset auto currentLocalID = getSessionLocalID(); auto currentSessionID = getSessionUUID(); @@ -684,15 +719,6 @@ void NodeList::processDomainServerList(QSharedPointer message) DependencyManager::get()->lookupShareableNameForDomainID(domainUUID); } - // pull the permissions/right/privileges for this node out of the stream - NodePermissions newPermissions; - packetStream >> newPermissions; - setPermissions(newPermissions); - // Is packet authentication enabled? - bool isAuthenticated; - packetStream >> isAuthenticated; - setAuthenticatePackets(isAuthenticated); - // pull each node in the packet while (packetStream.device()->pos() < message->getSize()) { parseNodeFromPacketStream(packetStream); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index f8574b3b94..566e1e4946 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -27,7 +27,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::StunResponse: return 17; case PacketType::DomainList: - return static_cast(DomainListVersion::AuthenticationOptional); + return static_cast(DomainListVersion::HasTimestamp); case PacketType::EntityAdd: case PacketType::EntityClone: case PacketType::EntityEdit: @@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) { return static_cast(DomainConnectionDeniedVersion::IncludesExtraInfo); case PacketType::DomainConnectRequest: - return static_cast(DomainConnectRequestVersion::AlwaysHasMachineFingerprint); + return static_cast(DomainConnectRequestVersion::HasTimestamp); case PacketType::DomainServerAddedNode: return static_cast(DomainServerAddedNodeVersion::PermissionsGrid); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 5deadd8c43..903c1f4c93 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -344,7 +344,8 @@ enum class DomainConnectRequestVersion : PacketVersion { HasProtocolVersions, HasMACAddress, HasMachineFingerprint, - AlwaysHasMachineFingerprint + AlwaysHasMachineFingerprint, + HasTimestamp }; enum class DomainConnectionDeniedVersion : PacketVersion { @@ -363,7 +364,8 @@ enum class DomainListVersion : PacketVersion { PermissionsGrid, GetUsernameFromUUIDSupport, GetMachineFingerprintFromUUIDSupport, - AuthenticationOptional + AuthenticationOptional, + HasTimestamp }; enum class AudioVersion : PacketVersion { From 3a4bf2e8f7291f914facdcdeda5f3bb01f531950 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 13:57:09 -0700 Subject: [PATCH 31/40] Fix the janky audio output settings UI --- .../simplifiedUI/settingsApp/audio/Audio.qml | 23 +++++----- .../simplifiedUI/topBar/SimplifiedTopBar.qml | 10 ++--- interface/src/scripting/Audio.cpp | 37 ++++++++++++++++ interface/src/scripting/Audio.h | 36 +++++++++++++++ scripts/system/simplifiedUI/simplifiedUI.js | 44 ++++++++----------- 5 files changed, 104 insertions(+), 46 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml index 3e2e4bf752..bb64e835d5 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml @@ -68,7 +68,6 @@ Flickable { SimplifiedControls.Slider { id: peopleVolume - property real lastValueSent anchors.left: parent.left anchors.right: parent.right Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin @@ -78,11 +77,11 @@ Flickable { to: 20.0 defaultValue: 0.0 stepSize: 5.0 - value: AudioScriptingInterface.getAvatarGain() + value: AudioScriptingInterface.avatarGain live: true function updatePeopleGain(sliderValue) { - if (AudioScriptingInterface.getAvatarGain() !== sliderValue) { - AudioScriptingInterface.setAvatarGain(sliderValue); + if (AudioScriptingInterface.avatarGain !== sliderValue) { + AudioScriptingInterface.avatarGain = sliderValue; } } onValueChanged: { @@ -97,7 +96,6 @@ Flickable { SimplifiedControls.Slider { id: environmentVolume - property real lastValueSent anchors.left: parent.left anchors.right: parent.right Layout.topMargin: 2 @@ -107,12 +105,12 @@ Flickable { to: 20.0 defaultValue: 0.0 stepSize: 5.0 - value: AudioScriptingInterface.getInjectorGain() + value: AudioScriptingInterface.serverInjectorGain live: true function updateEnvironmentGain(sliderValue) { - if (AudioScriptingInterface.getInjectorGain() !== sliderValue) { - AudioScriptingInterface.setInjectorGain(sliderValue); - AudioScriptingInterface.setLocalInjectorGain(sliderValue); + if (AudioScriptingInterface.serverInjectorGain !== sliderValue) { + AudioScriptingInterface.serverInjectorGain = sliderValue; + AudioScriptingInterface.localInjectorGain = sliderValue; } } onValueChanged: { @@ -127,7 +125,6 @@ Flickable { SimplifiedControls.Slider { id: systemSoundVolume - property real lastValueSent anchors.left: parent.left anchors.right: parent.right Layout.topMargin: 2 @@ -137,11 +134,11 @@ Flickable { to: 20.0 defaultValue: 0.0 stepSize: 5.0 - value: AudioScriptingInterface.getSystemInjectorGain() + value: AudioScriptingInterface.systemInjectorGain live: true function updateSystemGain(sliderValue) { - if (AudioScriptingInterface.getSystemInjectorGain() !== sliderValue) { - AudioScriptingInterface.setSystemInjectorGain(sliderValue); + if (AudioScriptingInterface.systemInjectorGain !== sliderValue) { + AudioScriptingInterface.systemInjectorGain = sliderValue; } } onValueChanged: { diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 66270cc325..1a85e6fbae 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -203,7 +203,8 @@ Rectangle { Image { id: outputDeviceButton - property bool outputMuted: false + property bool outputMuted: AudioScriptingInterface.avatarGain === -60 && + AudioScriptingInterface.serverInjectorGain === -60 && AudioScriptingInterface.localInjectorGain === -60 && AudioScriptingInterface.systemInjectorGain === -60 source: outputDeviceButton.outputMuted ? "./images/outputDeviceMuted.svg" : "./images/outputDeviceLoud.svg" anchors.centerIn: parent width: 20 @@ -228,7 +229,6 @@ Rectangle { } onClicked: { Tablet.playSound(TabletEnums.ButtonClick); - outputDeviceButton.outputMuted = !outputDeviceButton.outputMuted; if (outputDeviceButton.outputMuted && !AudioScriptingInterface.muted) { AudioScriptingInterface.muted = true; @@ -238,7 +238,7 @@ Rectangle { "source": "SimplifiedTopBar.qml", "method": "setOutputMuted", "data": { - "outputMuted": outputDeviceButton.outputMuted + "outputMuted": !outputDeviceButton.outputMuted } }); } @@ -454,10 +454,6 @@ Rectangle { } break; - case "updateOutputMuted": - outputDeviceButton.outputMuted = message.data.outputMuted; - break; - case "updateStatusButton": statusButton.currentStatus = message.data.currentStatus; break; diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index cb8b211352..6df4729ee0 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -400,10 +400,19 @@ void Audio::setReverbOptions(const AudioEffectOptions* options) { } void Audio::setAvatarGain(float gain) { + bool changed = false; + if (getAvatarGain() != gain) { + changed = true; + } + withWriteLock([&] { // ask the NodeList to set the master avatar gain DependencyManager::get()->setAvatarGain(QUuid(), gain); }); + + if (changed) { + emit avatarGainChanged(gain); + } } float Audio::getAvatarGain() { @@ -413,10 +422,19 @@ float Audio::getAvatarGain() { } void Audio::setInjectorGain(float gain) { + bool changed = false; + if (getInjectorGain() != gain) { + changed = true; + } + withWriteLock([&] { // ask the NodeList to set the audio injector gain DependencyManager::get()->setInjectorGain(gain); }); + + if (changed) { + emit serverInjectorGainChanged(gain); + } } float Audio::getInjectorGain() { @@ -426,6 +444,11 @@ float Audio::getInjectorGain() { } void Audio::setLocalInjectorGain(float gain) { + bool changed = false; + if (getLocalInjectorGain() != gain) { + changed = true; + } + withWriteLock([&] { if (_localInjectorGain != gain) { _localInjectorGain = gain; @@ -436,6 +459,11 @@ void Audio::setLocalInjectorGain(float gain) { DependencyManager::get()->setLocalInjectorGain(gain); } }); + + + if (changed) { + emit localInjectorGainChanged(gain); + } } float Audio::getLocalInjectorGain() { @@ -445,6 +473,11 @@ float Audio::getLocalInjectorGain() { } void Audio::setSystemInjectorGain(float gain) { + bool changed = false; + if (getSystemInjectorGain() != gain) { + changed = true; + } + withWriteLock([&] { if (_systemInjectorGain != gain) { _systemInjectorGain = gain; @@ -455,6 +488,10 @@ void Audio::setSystemInjectorGain(float gain) { DependencyManager::get()->setSystemInjectorGain(gain); } }); + + if (changed) { + emit systemInjectorGainChanged(gain); + } } float Audio::getSystemInjectorGain() { diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index ed54dca5c6..688009645f 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -90,6 +90,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { Q_PROPERTY(bool pushToTalkDesktop READ getPTTDesktop WRITE setPTTDesktop NOTIFY pushToTalkDesktopChanged) Q_PROPERTY(bool pushToTalkHMD READ getPTTHMD WRITE setPTTHMD NOTIFY pushToTalkHMDChanged) Q_PROPERTY(bool pushingToTalk READ getPushingToTalk WRITE setPushingToTalk NOTIFY pushingToTalkChanged) + Q_PROPERTY(float avatarGain READ getAvatarGain WRITE setAvatarGain NOTIFY avatarGainChanged) + Q_PROPERTY(float localInjectorGain READ getLocalInjectorGain WRITE setLocalInjectorGain NOTIFY localInjectorGainChanged) + Q_PROPERTY(float serverInjectorGain READ getInjectorGain WRITE setInjectorGain NOTIFY serverInjectorGainChanged) + Q_PROPERTY(float systemInjectorGain READ getSystemInjectorGain WRITE setSystemInjectorGain NOTIFY systemInjectorGainChanged) public: static QString AUDIO; @@ -412,6 +416,38 @@ signals: */ void pushingToTalkChanged(bool talking); + /**jsdoc + * Triggered when the avatar gain changes. + * @function Audio.avatarGainChanged + * @param {float} gain - The new avatar gain value. + * @returns {Signal} + */ + void avatarGainChanged(float gain); + + /**jsdoc + * Triggered when the local injector gain changes. + * @function Audio.localInjectorGainChanged + * @param {float} gain - The new local injector gain value. + * @returns {Signal} + */ + void localInjectorGainChanged(float gain); + + /**jsdoc + * Triggered when the server injector gain changes. + * @function Audio.serverInjectorGainChanged + * @param {float} gain - The new server injector gain value. + * @returns {Signal} + */ + void serverInjectorGainChanged(float gain); + + /**jsdoc + * Triggered when the system injector gain changes. + * @function Audio.systemInjectorGainChanged + * @param {float} gain - The new system injector gain value. + * @returns {Signal} + */ + void systemInjectorGainChanged(float gain); + public slots: /**jsdoc diff --git a/scripts/system/simplifiedUI/simplifiedUI.js b/scripts/system/simplifiedUI/simplifiedUI.js index 94eb9f84fd..624522730e 100644 --- a/scripts/system/simplifiedUI/simplifiedUI.js +++ b/scripts/system/simplifiedUI/simplifiedUI.js @@ -238,40 +238,40 @@ function updateOutputDeviceMutedOverlay(isMuted) { } -var savedAvatarGain = Audio.getAvatarGain(); -var savedInjectorGain = Audio.getInjectorGain(); -var savedLocalInjectorGain = Audio.getLocalInjectorGain(); -var savedSystemInjectorGain = Audio.getSystemInjectorGain(); +var savedAvatarGain = Audio.avatarGain; +var savedInjectorGain = Audio.serverInjectorGain; +var savedLocalInjectorGain = Audio.localInjectorGain; +var savedSystemInjectorGain = Audio.systemInjectorGain; function setOutputMuted(outputMuted) { updateOutputDeviceMutedOverlay(outputMuted); if (outputMuted) { - savedAvatarGain = Audio.getAvatarGain(); - savedInjectorGain = Audio.getInjectorGain(); - savedLocalInjectorGain = Audio.getLocalInjectorGain(); - savedSystemInjectorGain = Audio.getSystemInjectorGain(); + savedAvatarGain = Audio.avatarGain; + savedInjectorGain = Audio.serverInjectorGain; + savedLocalInjectorGain = Audio.localInjectorGain; + savedSystemInjectorGain = Audio.systemInjectorGain; - Audio.setAvatarGain(-60); - Audio.setInjectorGain(-60); - Audio.setLocalInjectorGain(-60); - Audio.setSystemInjectorGain(-60); + Audio.avatarGain = -60; + Audio.serverInjectorGain = -60; + Audio.localInjectorGain = -60; + Audio.systemInjectorGain = -60; } else { if (savedAvatarGain === -60) { savedAvatarGain = 0; } - Audio.setAvatarGain(savedAvatarGain); + Audio.avatarGain = savedAvatarGain; if (savedInjectorGain === -60) { savedInjectorGain = 0; } - Audio.setInjectorGain(savedInjectorGain); + Audio.serverInjectorGain = savedInjectorGain; if (savedLocalInjectorGain === -60) { savedLocalInjectorGain = 0; } - Audio.setLocalInjectorGain(savedLocalInjectorGain); + Audio.localInjectorGain = savedLocalInjectorGain; if (savedSystemInjectorGain === -60) { savedSystemInjectorGain = 0; } - Audio.setSystemInjectorGain(savedSystemInjectorGain); + Audio.systemInjectorGain = savedSystemInjectorGain; } } @@ -334,7 +334,7 @@ function onTopBarClosed() { function isOutputMuted() { - return Audio.getAvatarGain() === -60 && Audio.getInjectorGain() === -60 && Audio.getLocalInjectorGain() === -60 && Audio.getSystemInjectorGain() === -60; + return Audio.avatarGain === -60 && Audio.serverInjectorGain === -60 && Audio.localInjectorGain === -60 && Audio.systemInjectorGain === -60; } @@ -370,15 +370,7 @@ function loadSimplifiedTopBar() { // The eventbridge takes a nonzero time to initialize, so we have to wait a bit // for the QML to load and for that to happen before updating the UI. - Script.setTimeout(function() { - topBarWindow.sendToQml({ - "source": "simplifiedUI.js", - "method": "updateOutputMuted", - "data": { - "outputMuted": isOutputMuted() - } - }); - + Script.setTimeout(function() { sendLocalStatusToQml(); }, WAIT_FOR_TOP_BAR_MS); } From 0c90b7c4c214123836e623a5451a469ac63aca06 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 14:51:11 -0700 Subject: [PATCH 32/40] JSdocs --- interface/src/scripting/Audio.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index 688009645f..c7ac98402c 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -66,6 +66,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { * @property {boolean} pushToTalkHMD - true if HMD push-to-talk is enabled, otherwise false. * @property {boolean} pushingToTalk - true if the user is currently pushing-to-talk, otherwise * false. + * @property {float} avatarGain - The gain (relative volume) that avatars' voices are played at. This gain is used at the server. + * @property {float} localInjectorGain - The gain (relative volume) that local injectors (local environment sounds) are played at. + * @property {float} serverInjectorGain - The gain (relative volume) that server injectors (server environment sounds) are played at. This gain is used at the server. + * @property {float} systemInjectorGain - The gain (relative volume) that system sounds are played at. * * @comment The following properties are from AudioScriptingInterface.h. * @property {boolean} isStereoInput - true if the input audio is being used in stereo, otherwise From 04573da96b6b53d331136155f7f6ecde7605f476 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 23 May 2019 09:49:32 +1200 Subject: [PATCH 33/40] Selection JSDoc revision --- .../scripting/SelectionScriptingInterface.cpp | 33 +-- .../scripting/SelectionScriptingInterface.h | 225 +++++++++--------- 2 files changed, 128 insertions(+), 130 deletions(-) diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index c15b5cde11..556b17650d 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -44,13 +44,14 @@ SelectionScriptingInterface::SelectionScriptingInterface() { } /**jsdoc + * The type of an item in a selection list. * * * * * - * - * + * + * * *
ValueDescription
"avatar"
"entity"
"avatar"The item is an avatar.
"entity"The item is an entity.
* @typedef {string} Selection.ItemType @@ -245,9 +246,10 @@ void SelectionScriptingInterface::printList(const QString& listName) { } /**jsdoc + * A selection list. * @typedef {object} Selection.SelectedItemsList - * @property {Uuid[]} avatars - The IDs of the avatars in the selection. - * @property {Uuid[]} entities - The IDs of the entities in the selection. + * @property {Uuid[]} avatars - The IDs of the avatars in the selection list. + * @property {Uuid[]} entities - The IDs of the entities in the selection list. */ QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const { QReadLocker lock(&_selectionListsLock); @@ -438,18 +440,19 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) { } /**jsdoc + * The highlighting style of a selection list. * @typedef {object} Selection.HighlightStyle - * @property {Color} outlineUnoccludedColor - Color of the specified highlight region. - * @property {Color} outlineOccludedColor - "" - * @property {Color} fillUnoccludedColor- "" - * @property {Color} fillOccludedColor- "" - * @property {number} outlineUnoccludedAlpha - Alpha value ranging from 0.0 (not visible) to 1.0 - * (fully opaque) for the specified highlight region. - * @property {number} outlineOccludedAlpha - "" - * @property {number} fillUnoccludedAlpha - "" - * @property {number} fillOccludedAlpha - "" - * @property {number} outlineWidth - Width of the outline, in pixels. - * @property {boolean} isOutlineSmooth - true to enable outline smooth fall-off. + * @property {Color} outlineUnoccludedColor=255,178,51 - Unoccluded outline color. + * @property {Color} outlineOccludedColor=255,178,51 - Occluded outline color. + * @property {Color} fillUnoccludedColor=51,178,255 - Unoccluded fill color. + * @property {Color} fillOccludedColor=51,178,255 - Occluded fill color. + * @property {number} outlineUnoccludedAlpha=0.9 - Unoccluded outline alpha, range 0.01.0. + * @property {number} outlineOccludedAlpha=0.9 - Occluded outline alpha, range 0.01.0. + * @property {number} fillUnoccludedAlpha=0.0 - Unoccluded fill alpha, range 0.01.0. + * @property {number} fillOccludedAlpha=0.0 - Occluded fill alpha, range 0.01.0. + * @property {number} outlineWidth=2 - Width of the outline, in pixels. + * @property {boolean} isOutlineSmooth=false - true to fade the outside edge of the outline, false + * to have a sharp edge. */ QVariantMap SelectionHighlightStyle::toVariantMap() const { QVariantMap properties; diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index fcb4090184..921db0e70b 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -77,47 +77,45 @@ protected: }; /**jsdoc - * The Selection API provides a means of grouping together avatars and entities in named lists. + * The Selection API provides a means of grouping together and highlighting avatars and entities in named lists. + * * @namespace Selection * * @hifi-interface * @hifi-client-entity * @hifi-avatar * - * @example Outline an entity when it is grabbed by a controller. - * // Create a box and copy the following text into the entity's "Script URL" field. + * @example Outline an entity when it is grabbed by the mouse or a controller. + * // Create an entity and copy the following script into the entity's "Script URL" field. + * // Move the entity behind another entity to see the occluded outline. * (function () { - * print("Starting highlight script..............."); - * var _this = this; - * var prevID = 0; - * var listName = "contextOverlayHighlightList"; - * var listType = "entity"; - * - * _this.startNearGrab = function(entityID){ - * if (prevID !== entityID) { - * Selection.addToSelectedItemsList(listName, listType, entityID); - * prevID = entityID; - * } + * var LIST_NAME = "SelectionExample", + * ITEM_TYPE = "entity", + * HIGHLIGHT_STYLE = { + * outlineUnoccludedColor: { red: 0, green: 180, blue: 239 }, + * outlineUnoccludedAlpha: 0.5, + * outlineOccludedColor: { red: 239, green: 180, blue: 0 }, + * outlineOccludedAlpha: 0.5, + * outlineWidth: 4 + * }; + * + * Selection.enableListHighlight(LIST_NAME, HIGHLIGHT_STYLE); + * + * this.startNearGrab = function (entityID) { + * Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID); * }; - * - * _this.releaseGrab = function(entityID){ - * if (prevID !== 0) { - * Selection.removeFromSelectedItemsList("contextOverlayHighlightList", listType, prevID); - * prevID = 0; - * } + * + * this.startDistanceGrab = function (entityID) { + * Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID); * }; - * - * var cleanup = function(){ - * Entities.findEntities(MyAvatar.position, 1000).forEach(function(entity) { - * try { - * Selection.removeListFromMap(listName); - * } catch (e) { - * print("Error cleaning up."); - * } - * }); + * + * this.releaseGrab = function (entityID) { + * Selection.removeFromSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID); * }; - * - * Script.scriptEnding.connect(cleanup); + * + * Script.scriptEnding.connect(function () { + * Selection.removeListFromMap(LIST_NAME); + * }); * }); */ class SelectionScriptingInterface : public QObject, public Dependency { @@ -127,121 +125,119 @@ public: SelectionScriptingInterface(); /**jsdoc - * Get the names of all the selection lists. - * @function Selection.getListNames - * @returns {list[]} An array of names of all the selection lists. - */ + * Gets the names of all current selection lists. + * @function Selection.getListNames + * @returns {string[]} The names of all current selection lists. + * @example List all the current selection lists. + * print("Selection lists: " + Selection.getListNames()); + */ Q_INVOKABLE QStringList getListNames() const; /**jsdoc - * Delete a named selection list. - * @function Selection.removeListFromMap - * @param {string} listName - The name of the selection list. - * @returns {boolean} true if the selection existed and was successfully removed, otherwise false. - */ + * Deletes a selection list. + * @function Selection.removeListFromMap + * @param {string} listName - The name of the selection list to delete. + * @returns {boolean} true if the selection existed and was successfully removed, otherwise false. + */ Q_INVOKABLE bool removeListFromMap(const QString& listName); /**jsdoc - * Add an item to a selection list. - * @function Selection.addToSelectedItemsList - * @param {string} listName - The name of the selection list to add the item to. - * @param {Selection.ItemType} itemType - The type of the item being added. - * @param {Uuid} id - The ID of the item to add to the selection. - * @returns {boolean} true if the item was successfully added, otherwise false. - */ + * Adds an item to a selection list. The list is created if it doesn't exist. + * @function Selection.addToSelectedItemsList + * @param {string} listName - The name of the selection list to add the item to. + * @param {Selection.ItemType} itemType - The type of item being added. + * @param {Uuid} itemID - The ID of the item to add. + * @returns {boolean} true if the item was successfully added or already existed in the list, otherwise + * false. + */ Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); + /**jsdoc - * Remove an item from a selection list. - * @function Selection.removeFromSelectedItemsList - * @param {string} listName - The name of the selection list to remove the item from. - * @param {Selection.ItemType} itemType - The type of the item being removed. - * @param {Uuid} id - The ID of the item to remove. - * @returns {boolean} true if the item was successfully removed, otherwise false. - * is returned if the list doesn't contain any data. - */ + * Removes an item from a selection list. + * @function Selection.removeFromSelectedItemsList + * @param {string} listName - The name of the selection list to remove the item from. + * @param {Selection.ItemType} itemType - The type of item being removed. + * @param {Uuid} itemID - The ID of the item to remove. + * @returns {boolean} true if the item was successfully removed or was not in the list, otherwise + * false. + */ Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); + /**jsdoc - * Remove all items from a selection. - * @function Selection.clearSelectedItemsList - * @param {string} listName - The name of the selection list. - * @returns {boolean} true if the item was successfully cleared, otherwise false. - */ + * Removes all items from a selection list. + * @function Selection.clearSelectedItemsList + * @param {string} listName - The name of the selection list. + * @returns {boolean} true zlways. + */ Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); /**jsdoc - * Print out the list of avatars and entities in a selection to the debug log (not the script log). - * @function Selection.printList - * @param {string} listName - The name of the selection list. - */ + * Prints the list of avatars and entities in a selection to the program log (but not the Script Log window). + * @function Selection.printList + * @param {string} listName - The name of the selection list. + */ Q_INVOKABLE void printList(const QString& listName); /**jsdoc - * Get the list of avatars and entities stored in a selection list. - * @function Selection.getSelectedItemsList - * @param {string} listName - The name of the selection list. - * @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function - * returns an empty object with no properties. - */ + * Gets the list of avatars and entities in a selection list. + * @function Selection.getSelectedItemsList + * @param {string} listName - The name of the selection list. + * @returns {Selection.SelectedItemsList} The content of the selection list if the list exists, otherwise an empty object. + */ Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const; /**jsdoc - * Get the names of the highlighted selection lists. - * @function Selection.getHighlightedListNames - * @returns {string[]} An array of names of the selection list currently highlight enabled. - */ + * Gets the names of all current selection lists that have highlighting enabled. + * @function Selection.getHighlightedListNames + * @returns {string[]} The names of the selection lists that currently have highlighting enabled. + */ Q_INVOKABLE QStringList getHighlightedListNames() const; /**jsdoc - * Enable highlighting for a selection list. - * If the selection list doesn't exist, it will be created. - * All objects in the list will be displayed with the highlight effect specified. - * The function can be called several times with different values in the style to modify it.
- * Note: This function implicitly calls {@link Selection.enableListToScene}. - * @function Selection.enableListHighlight - * @param {string} listName - The name of the selection list. - * @param {Selection.HighlightStyle} highlightStyle - The highlight style. - * @returns {boolean} true if the selection was successfully enabled for highlight. - */ + * Enables highlighting for a selection list. All items in or subsequently added to the list are displayed with the + * highlight effect specified. The method can be called multiple times with different values in the style to modify the + * highlighting. + *

Note: This function implicitly calls {@link Selection.enableListToScene|enableListToScene}.

+ * @function Selection.enableListHighlight + * @param {string} listName - The name of the selection list. + * @param {Selection.HighlightStyle} highlightStyle - The highlight style. + * @returns {boolean} true always. + */ Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle); /**jsdoc - * Disable highlighting for the selection list. - * If the selection list doesn't exist or wasn't enabled for highlighting then nothing happens and false is - * returned.
- * Note: This function implicitly calls {@link Selection.disableListToScene}. - * @function Selection.disableListHighlight - * @param {string} listName - The name of the selection list. - * @returns {boolean} true if the selection was successfully disabled for highlight, otherwise - * false. - */ + * Disables highlighting for a selection list. + *

Note: This function implicitly calls {@link Selection.disableListToScene|disableListToScene}.

+ * @function Selection.disableListHighlight + * @param {string} listName - The name of the selection list. + * @returns {boolean} true always. + */ Q_INVOKABLE bool disableListHighlight(const QString& listName); + /**jsdoc - * Enable scene selection for the selection list. - * If the Selection doesn't exist, it will be created. - * All objects in the list will be sent to a scene selection. - * @function Selection.enableListToScene - * @param {string} listName - The name of the selection list. - * @returns {boolean} true if the selection was successfully enabled on the scene, otherwise false. - */ + * Enables scene selection for a selection list. All items in or subsequently added to the list are sent to a scene + * selection in the rendering engine for debugging purposes. + * @function Selection.enableListToScene + * @param {string} listName - The name of the selection list. + * @returns {boolean} true always. + */ Q_INVOKABLE bool enableListToScene(const QString& listName); /**jsdoc - * Disable scene selection for the named selection. - * If the selection list doesn't exist or wasn't enabled on the scene then nothing happens and false is - * returned. - * @function Selection.disableListToScene - * @param {string} listName - The name of the selection list. - * @returns {boolean} true if the selection was successfully disabled on the scene, false otherwise. - */ + * Disables scene selection for a selection list. + * @function Selection.disableListToScene + * @param {string} listName - The name of the selection list. + * @returns {boolean} true always. + */ Q_INVOKABLE bool disableListToScene(const QString& listName); /**jsdoc - * Get the highlight style values for the a selection list. - * If the selection doesn't exist or hasn't been highlight enabled yet, an empty object is returned. - * @function Selection.getListHighlightStyle - * @param {string} listName - The name of the selection list. - * @returns {Selection.HighlightStyle} highlight style - */ + * Gets the current highlighting style for a selection list. + * @function Selection.getListHighlightStyle + * @param {string} listName - The name of the selection list. + * @returns {Selection.HighlightStyle} The highlight style of the selection list if the list exists and highlighting is + * enabled, otherwise an empty object. + */ Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const; @@ -253,7 +249,7 @@ public: signals: /**jsdoc - * Triggered when a list's content changes. + * Triggered when a selection list's content changes or the list is deleted. * @function Selection.selectedItemsListChanged * @param {string} listName - The name of the selection list that changed. * @returns {Signal} @@ -276,7 +272,6 @@ private: void setupHandler(const QString& selectionName); void removeHandler(const QString& selectionName); - }; #endif // hifi_SelectionScriptingInterface_h From 7a88c8362b08502d172f3984e0ca90e0606852a8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 15:01:22 -0700 Subject: [PATCH 34/40] naming CR feedback --- scripts/system/simplifiedUI/simplifiedUI.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/system/simplifiedUI/simplifiedUI.js b/scripts/system/simplifiedUI/simplifiedUI.js index 624522730e..d55663edab 100644 --- a/scripts/system/simplifiedUI/simplifiedUI.js +++ b/scripts/system/simplifiedUI/simplifiedUI.js @@ -239,7 +239,7 @@ function updateOutputDeviceMutedOverlay(isMuted) { var savedAvatarGain = Audio.avatarGain; -var savedInjectorGain = Audio.serverInjectorGain; +var savedServerInjectorGain = Audio.serverInjectorGain; var savedLocalInjectorGain = Audio.localInjectorGain; var savedSystemInjectorGain = Audio.systemInjectorGain; function setOutputMuted(outputMuted) { @@ -247,7 +247,7 @@ function setOutputMuted(outputMuted) { if (outputMuted) { savedAvatarGain = Audio.avatarGain; - savedInjectorGain = Audio.serverInjectorGain; + savedServerInjectorGain = Audio.serverInjectorGain; savedLocalInjectorGain = Audio.localInjectorGain; savedSystemInjectorGain = Audio.systemInjectorGain; @@ -260,10 +260,10 @@ function setOutputMuted(outputMuted) { savedAvatarGain = 0; } Audio.avatarGain = savedAvatarGain; - if (savedInjectorGain === -60) { - savedInjectorGain = 0; + if (savedServerInjectorGain === -60) { + savedServerInjectorGain = 0; } - Audio.serverInjectorGain = savedInjectorGain; + Audio.serverInjectorGain = savedServerInjectorGain; if (savedLocalInjectorGain === -60) { savedLocalInjectorGain = 0; } From b331bb06836975567530d87963ca12ab1be78e4a Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Wed, 22 May 2019 15:03:39 -0700 Subject: [PATCH 35/40] Initialize structure member as per code review suggestion. --- domain-server/src/NodeConnectionData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/NodeConnectionData.h b/domain-server/src/NodeConnectionData.h index 96e81839c6..779411d11e 100644 --- a/domain-server/src/NodeConnectionData.h +++ b/domain-server/src/NodeConnectionData.h @@ -22,7 +22,7 @@ public: bool isConnectRequest = true); QUuid connectUUID; - quint64 lastPingTimestamp; + quint64 lastPingTimestamp{ 0 }; NodeType_t nodeType; HifiSockAddr publicSockAddr; HifiSockAddr localSockAddr; From 2c591ba19673b157f2f40d4d611741d9087e853a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 23 May 2019 10:18:03 +1200 Subject: [PATCH 36/40] Doc review --- interface/src/scripting/SelectionScriptingInterface.cpp | 2 +- interface/src/scripting/SelectionScriptingInterface.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index 556b17650d..5856188868 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -44,7 +44,7 @@ SelectionScriptingInterface::SelectionScriptingInterface() { } /**jsdoc - * The type of an item in a selection list. + * The type of a specific item in a selection list. * * * diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 921db0e70b..4386ee5ee6 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -167,7 +167,7 @@ public: * Removes all items from a selection list. * @function Selection.clearSelectedItemsList * @param {string} listName - The name of the selection list. - * @returns {boolean} true zlways. + * @returns {boolean} true always. */ Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); From 46ee148a69d345326f167bbb15665f5b277fcf12 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 15:24:33 -0700 Subject: [PATCH 37/40] Fix a bug and remove magic numbers --- .../simplifiedUI/settingsApp/audio/Audio.qml | 6 +-- .../SimplifiedConstants.qml | 4 ++ .../simplifiedUI/topBar/SimplifiedTopBar.qml | 8 ++-- scripts/system/simplifiedUI/simplifiedUI.js | 37 +++++++++++++------ 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml index bb64e835d5..9ac72fa3cd 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml @@ -73,7 +73,7 @@ Flickable { Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin height: 30 labelText: "People Volume" - from: -60.0 + from: simplifiedUI.numericConstants.mutedValue to: 20.0 defaultValue: 0.0 stepSize: 5.0 @@ -101,7 +101,7 @@ Flickable { Layout.topMargin: 2 height: 30 labelText: "Environment Volume" - from: -60.0 + from: simplifiedUI.numericConstants.mutedValue to: 20.0 defaultValue: 0.0 stepSize: 5.0 @@ -130,7 +130,7 @@ Flickable { Layout.topMargin: 2 height: 30 labelText: "System Sound Volume" - from: -60.0 + from: simplifiedUI.numericConstants.mutedValue to: 20.0 defaultValue: 0.0 stepSize: 5.0 diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml index 752c989500..1f628b041d 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml @@ -221,4 +221,8 @@ QtObject { } } } + + readonly property QtObject numericConstants: QtObject { + readonly property real mutedValue: -60.0 + } } diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 1a85e6fbae..27a786ece2 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -203,8 +203,10 @@ Rectangle { Image { id: outputDeviceButton - property bool outputMuted: AudioScriptingInterface.avatarGain === -60 && - AudioScriptingInterface.serverInjectorGain === -60 && AudioScriptingInterface.localInjectorGain === -60 && AudioScriptingInterface.systemInjectorGain === -60 + property bool outputMuted: AudioScriptingInterface.avatarGain === simplifiedUI.numericConstants.mutedValue && + AudioScriptingInterface.serverInjectorGain === simplifiedUI.numericConstants.mutedValue && + AudioScriptingInterface.localInjectorGain === simplifiedUI.numericConstants.mutedValue && + AudioScriptingInterface.systemInjectorGain === simplifiedUI.numericConstants.mutedValue source: outputDeviceButton.outputMuted ? "./images/outputDeviceMuted.svg" : "./images/outputDeviceLoud.svg" anchors.centerIn: parent width: 20 @@ -230,7 +232,7 @@ Rectangle { onClicked: { Tablet.playSound(TabletEnums.ButtonClick); - if (outputDeviceButton.outputMuted && !AudioScriptingInterface.muted) { + if (!outputDeviceButton.outputMuted && !AudioScriptingInterface.muted) { AudioScriptingInterface.muted = true; } diff --git a/scripts/system/simplifiedUI/simplifiedUI.js b/scripts/system/simplifiedUI/simplifiedUI.js index d55663edab..351372613b 100644 --- a/scripts/system/simplifiedUI/simplifiedUI.js +++ b/scripts/system/simplifiedUI/simplifiedUI.js @@ -242,33 +242,32 @@ var savedAvatarGain = Audio.avatarGain; var savedServerInjectorGain = Audio.serverInjectorGain; var savedLocalInjectorGain = Audio.localInjectorGain; var savedSystemInjectorGain = Audio.systemInjectorGain; +var MUTED_VALUE_DB = -60; // This should always match `SimplifiedConstants.qml` -> numericConstants -> mutedValue! function setOutputMuted(outputMuted) { - updateOutputDeviceMutedOverlay(outputMuted); - if (outputMuted) { savedAvatarGain = Audio.avatarGain; savedServerInjectorGain = Audio.serverInjectorGain; savedLocalInjectorGain = Audio.localInjectorGain; savedSystemInjectorGain = Audio.systemInjectorGain; - Audio.avatarGain = -60; - Audio.serverInjectorGain = -60; - Audio.localInjectorGain = -60; - Audio.systemInjectorGain = -60; + Audio.avatarGain = MUTED_VALUE_DB; + Audio.serverInjectorGain = MUTED_VALUE_DB; + Audio.localInjectorGain = MUTED_VALUE_DB; + Audio.systemInjectorGain = MUTED_VALUE_DB; } else { - if (savedAvatarGain === -60) { + if (savedAvatarGain === MUTED_VALUE_DB) { savedAvatarGain = 0; } Audio.avatarGain = savedAvatarGain; - if (savedServerInjectorGain === -60) { + if (savedServerInjectorGain === MUTED_VALUE_DB) { savedServerInjectorGain = 0; } Audio.serverInjectorGain = savedServerInjectorGain; - if (savedLocalInjectorGain === -60) { + if (savedLocalInjectorGain === MUTED_VALUE_DB) { savedLocalInjectorGain = 0; } Audio.localInjectorGain = savedLocalInjectorGain; - if (savedSystemInjectorGain === -60) { + if (savedSystemInjectorGain === MUTED_VALUE_DB) { savedSystemInjectorGain = 0; } Audio.systemInjectorGain = savedSystemInjectorGain; @@ -334,7 +333,10 @@ function onTopBarClosed() { function isOutputMuted() { - return Audio.avatarGain === -60 && Audio.serverInjectorGain === -60 && Audio.localInjectorGain === -60 && Audio.systemInjectorGain === -60; + return Audio.avatarGain === MUTED_VALUE_DB && + Audio.serverInjectorGain === MUTED_VALUE_DB && + Audio.localInjectorGain === MUTED_VALUE_DB && + Audio.systemInjectorGain === MUTED_VALUE_DB; } @@ -461,6 +463,11 @@ function onStatusChanged() { } +function maybeUpdateOutputDeviceMutedOverlay() { + updateOutputDeviceMutedOverlay(isOutputMuted()); +} + + var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()); var si; @@ -493,6 +500,10 @@ function startup() { Audio.mutedDesktopChanged.connect(onDesktopInputDeviceMutedChanged); Window.geometryChanged.connect(onGeometryChanged); HMD.displayModeChanged.connect(ensureFirstPersonCameraInHMD); + Audio.avatarGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay); + Audio.localInjectorGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay); + Audio.serverInjectorGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay); + Audio.systemInjectorGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay); oldShowAudioTools = AvatarInputs.showAudioTools; AvatarInputs.showAudioTools = false; @@ -543,6 +554,10 @@ function shutdown() { Audio.mutedDesktopChanged.disconnect(onDesktopInputDeviceMutedChanged); Window.geometryChanged.disconnect(onGeometryChanged); HMD.displayModeChanged.disconnect(ensureFirstPersonCameraInHMD); + Audio.avatarGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay); + Audio.localInjectorGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay); + Audio.serverInjectorGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay); + Audio.systemInjectorGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay); AvatarInputs.showAudioTools = oldShowAudioTools; AvatarInputs.showBubbleTools = oldShowBubbleTools; From 3ed47b4f2345d91602aa98ec4fde1a05f961defd Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 15:45:18 -0700 Subject: [PATCH 38/40] Show error states in Avatar app (BUGZ-310) --- .../hifi/simplifiedUI/avatarApp/AvatarApp.qml | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml index 57bec2250f..cb0da7c0df 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml @@ -58,7 +58,8 @@ Rectangle { if (isLoggedIn) { Commerce.getWalletStatus(); } else { - // Show some error to the user + errorText.text = "There was a problem while retrieving your inventory. " + + "Please try closing and re-opening the Avatar app.\n\nLogin status result: " + isLoggedIn; } } @@ -66,11 +67,17 @@ Rectangle { if (walletStatus === 5) { getInventory(); } else { - // Show some error to the user + errorText.text = "There was a problem while retrieving your inventory. " + + "Please try closing and re-opening the Avatar app.\n\nWallet status result: " + walletStatus; } } onInventoryResult: { + if (result.status !== "success") { + errorText.text = "There was a problem while retrieving your inventory. " + + "Please try closing and re-opening the Avatar app.\n\nInventory status: " + result.status + "\nMessage: " + result.message; + } + avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result); root.updatePreviewUrl(); } @@ -172,7 +179,7 @@ Rectangle { anchors.bottom: parent.bottom AnimatedImage { - visible: !inventoryContentsList.visible + visible: !inventoryContentsList.visible && !errorText.visible anchors.centerIn: parent width: 72 height: width @@ -181,7 +188,7 @@ Rectangle { ListView { id: inventoryContentsList - visible: avatarAppInventoryModel.count !== 0 + visible: avatarAppInventoryModel.count !== 0 && !errorText.visible interactive: contentItem.height > height clip: true model: avatarAppInventoryModel @@ -196,6 +203,18 @@ Rectangle { standaloneIncompatible: model.standalone_incompatible } } + + HifiStylesUit.GraphikRegular { + id: errorText + text: "" + visible: text !== "" + anchors.fill: parent + size: 22 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } } From 8df706abcb33fa6067b8370c7eb619ca4d18fd38 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 22 May 2019 15:51:46 -0700 Subject: [PATCH 39/40] Handle the case when the user doesn't have any avatars yet --- .../resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml index cb0da7c0df..b426f2d986 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml @@ -76,6 +76,8 @@ Rectangle { if (result.status !== "success") { errorText.text = "There was a problem while retrieving your inventory. " + "Please try closing and re-opening the Avatar app.\n\nInventory status: " + result.status + "\nMessage: " + result.message; + } else if (result.data && result.data.assets && result.data.assets.length === 0) { + errorText.text = "You have not created any avatars yet! Create an avatar with the Avatar Creator, then close and re-open the Avatar App." } avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result); From 55f1929de22ee94e03a2e24ac741d723d7ae488b Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 22 May 2019 16:08:26 -0700 Subject: [PATCH 40/40] Fix nodelist reset on logout/username change --- libraries/networking/src/NodeList.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 11c7ca53b7..31576ff8d9 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -91,10 +91,10 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) connect(accountManager.data(), &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn); // clear out NodeList when login is finished and we know our new username - connect(accountManager.data(), SIGNAL(usernameChanged(QString)) , this, SLOT(reset())); + connect(accountManager.data(), &AccountManager::usernameChanged , this, [this]{ reset("Username changed"); }); // clear our NodeList when logout is requested - connect(accountManager.data(), SIGNAL(logoutComplete()) , this, SLOT(reset())); + connect(accountManager.data(), &AccountManager::logoutComplete , this, [this]{ reset("Logged out"); }); // anytime we get a new node we will want to attempt to punch to it connect(this, &LimitedNodeList::nodeAdded, this, &NodeList::startNodeHolePunch);
ValueDescription