diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 3c2e660cbc..6963f4df0d 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -115,11 +115,7 @@ public: uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const; void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time); - QVector& getLastOtherAvatarSentJoints(QUuid otherAvatar) { - auto& lastOtherAvatarSentJoints = _lastOtherAvatarSentJoints[otherAvatar]; - lastOtherAvatarSentJoints.resize(_avatar->getJointCount()); - return lastOtherAvatarSentJoints; - } + QVector& getLastOtherAvatarSentJoints(QUuid otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; } void queuePacket(QSharedPointer message, SharedNodePointer node); int processPackets(); // returns number of packets processed diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index fb4b65726a..6f19b73cc5 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -381,6 +381,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) bool includeThisAvatar = true; auto lastEncodeForOther = nodeData->getLastOtherAvatarEncodeTime(otherNode->getUUID()); QVector& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getUUID()); + + lastSentJointsForOther.resize(otherAvatar->getJointCount()); + bool distanceAdjust = true; glm::vec3 viewerPosition = myPosition; AvatarDataPacket::HasFlags hasFlagsOut; // the result of the toByteArray diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index f2690e0a7d..7bf6f05d9f 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -41,6 +41,9 @@ if (APPLE) elseif (WIN32) set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library") +elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library") else () set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library") diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index 279311f162..cad6d40b49 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC67-v2.zip - URL_MD5 2c69a1df69816b4b0b81630396fbd36e + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC67-v4.zip + URL_MD5 ba32aed18bfeaac4ccaf5ebb8ea3e804 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml b/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml index b1b6de4644..aadd7c88ae 100644 --- a/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml @@ -254,7 +254,7 @@ ModalWindow { text: root.warning; wrapMode: Text.WordWrap; font.italic: true; - maximumLineCount: 2; + maximumLineCount: 3; } HiFiGlyphs { diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index 008ed5b860..0c86b93c4b 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -254,7 +254,7 @@ ModalWindow { text: root.warning; wrapMode: Text.WordWrap; font.italic: true; - maximumLineCount: 2; + maximumLineCount: 3; } HiFiGlyphs { diff --git a/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml b/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml index 623388e9b3..81a2c5c1e0 100644 --- a/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml @@ -282,7 +282,7 @@ TabletModalWindow { text: root.warning; wrapMode: Text.WordWrap; font.italic: true; - maximumLineCount: 2; + maximumLineCount: 3; } HiFiGlyphs { diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 8bf3a22338..c7c72e5f7c 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -258,7 +258,9 @@ Item { anchors.topMargin: 26; anchors.left: parent.left; anchors.leftMargin: 20; - width: paintedWidth; + anchors.right: parent.right; + anchors.rightMargin: 20; + elide: Text.ElideRight; height: 30; // Text size size: 22; @@ -844,7 +846,7 @@ Item { property string selectedRecipientUserName; property string selectedRecipientProfilePic; - visible: root.currentActiveView === "sendAssetStep"; + visible: root.currentActiveView === "sendAssetStep" || paymentSuccess.visible || paymentFailure.visible; anchors.fill: parent; anchors.topMargin: root.parentAppTitleBarHeight; @@ -856,7 +858,9 @@ Item { anchors.topMargin: 26; anchors.left: parent.left; anchors.leftMargin: 20; - width: paintedWidth; + anchors.right: parent.right; + anchors.rightMargin: 20; + elide: Text.ElideRight; height: 30; // Text size size: 22; @@ -907,7 +911,7 @@ Item { // "CHANGE" button HifiControlsUit.Button { id: changeButton; - color: root.assetName === "" ? hifi.buttons.none : hifi.buttons.noneBorderlessGray; + color: root.assetName === "" ? hifi.buttons.none : hifi.buttons.white; colorScheme: hifi.colorSchemes.dark; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter; @@ -1238,7 +1242,7 @@ Item { // Sending Asset Overlay START Rectangle { id: sendingAssetOverlay; - z: 998; + z: 999; visible: root.isCurrentlySendingAsset; anchors.fill: parent; @@ -1281,26 +1285,43 @@ Item { // Payment Success BEGIN Rectangle { id: paymentSuccess; + z: 998; visible: root.currentActiveView === "paymentSuccess"; anchors.fill: parent; color: Qt.rgba(0.0, 0.0, 0.0, 0.8); + // This object is always used in a popup or full-screen Wallet section. + // This MouseArea is used to prevent a user from being + // able to click on a button/mouseArea underneath the popup/section. + MouseArea { + anchors.fill: parent; + propagateComposedEvents: false; + hoverEnabled: true; + } + Rectangle { - anchors.centerIn: parent; - width: parent.width - 30; - height: parent.height - 30; + anchors.top: parent.top; + anchors.topMargin: root.assetName === "" ? 15 : 150; + anchors.left: parent.left; + anchors.leftMargin: root.assetName === "" ? 15 : 50; + anchors.right: parent.right; + anchors.rightMargin: root.assetName === "" ? 15 : 50; + anchors.bottom: parent.bottom; + anchors.bottomMargin: root.assetName === "" ? 15 : 240; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetName === "" ? "Payment Sent" : '"' + root.assetName + '"'; + text: root.assetName === "" ? "Payment Sent" : "Gift Sent"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; anchors.left: parent.left; anchors.leftMargin: 20; - width: paintedWidth; + anchors.right: parent.right; + anchors.rightMargin: 20; + elide: Text.ElideRight; height: 30; // Text size size: 22; @@ -1310,6 +1331,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_paymentSuccess; + visible: root.assetName === ""; text: hifi.glyphs.close; color: hifi.colors.lightGrayText; size: 26; @@ -1375,6 +1397,49 @@ Item { isDisplayingNearby: sendAssetStep.referrer === "nearby"; } } + + + Item { + id: giftContainer_paymentSuccess; + visible: root.assetName !== ""; + anchors.top: sendToContainer_paymentSuccess.bottom; + anchors.topMargin: 8; + anchors.left: parent.left; + anchors.leftMargin: 20; + anchors.right: parent.right; + anchors.rightMargin: 20; + height: 30; + + RalewaySemiBold { + id: gift_paymentSuccess; + text: "Gift:"; + // Anchors + anchors.top: parent.top; + anchors.left: parent.left; + anchors.bottom: parent.bottom; + width: 90; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RalewaySemiBold { + text: root.assetName; + // Anchors + anchors.top: parent.top; + anchors.left: gift_paymentSuccess.right; + anchors.right: parent.right; + height: parent.height; + // Text size + size: 18; + // Style + elide: Text.ElideRight; + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + } Item { id: amountContainer_paymentSuccess; @@ -1433,6 +1498,7 @@ Item { RalewaySemiBold { id: optionalMessage_paymentSuccess; + visible: root.assetName === ""; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentSuccess.visible ? amountContainer_paymentSuccess.bottom : sendToContainer_paymentSuccess.bottom; @@ -1457,7 +1523,7 @@ Item { colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; - anchors.bottomMargin: 80; + anchors.bottomMargin: root.assetName === "" ? 80 : 30; height: 50; width: 120; text: "Close"; @@ -1476,26 +1542,43 @@ Item { // Payment Failure BEGIN Rectangle { id: paymentFailure; + z: 998; visible: root.currentActiveView === "paymentFailure"; anchors.fill: parent; color: Qt.rgba(0.0, 0.0, 0.0, 0.8); + // This object is always used in a popup or full-screen Wallet section. + // This MouseArea is used to prevent a user from being + // able to click on a button/mouseArea underneath the popup/section. + MouseArea { + anchors.fill: parent; + propagateComposedEvents: false; + hoverEnabled: true; + } + Rectangle { - anchors.centerIn: parent; - width: parent.width - 30; - height: parent.height - 30; + anchors.top: parent.top; + anchors.topMargin: root.assetName === "" ? 15 : 150; + anchors.left: parent.left; + anchors.leftMargin: root.assetName === "" ? 15 : 50; + anchors.right: parent.right; + anchors.rightMargin: root.assetName === "" ? 15 : 50; + anchors.bottom: parent.bottom; + anchors.bottomMargin: root.assetName === "" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { id: paymentFailureText; - text: root.assetName === "" ? "Payment Failed" : '"' + root.assetName + '"'; + text: root.assetName === "" ? "Payment Failed" : "Failed"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; anchors.left: parent.left; anchors.leftMargin: 20; - width: paintedWidth; + anchors.right: parent.right; + anchors.rightMargin: 20; + elide: Text.ElideRight; height: 30; // Text size size: 22; @@ -1505,6 +1588,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_paymentFailure; + visible: root.assetName === ""; text: hifi.glyphs.close; color: hifi.colors.lightGrayText; size: 26; @@ -1551,6 +1635,7 @@ Item { Item { id: sendToContainer_paymentFailure; + visible: root.assetName === ""; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1645,7 +1730,8 @@ Item { } RalewaySemiBold { - id: optionalMessage_paymentFailuire; + id: optionalMessage_paymentFailure; + visible: root.assetName === ""; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentFailure.visible ? amountContainer_paymentFailure.bottom : sendToContainer_paymentFailure.bottom; @@ -1663,14 +1749,15 @@ Item { verticalAlignment: Text.AlignTop; } - // "Close" button + // "Cancel" button HifiControlsUit.Button { id: closeButton_paymentFailure; color: hifi.buttons.noneBorderless; colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; - anchors.horizontalCenter: parent.horizontalCenter; + anchors.right: retryButton_paymentFailure.left; + anchors.rightMargin: 12; anchors.bottom: parent.bottom; - anchors.bottomMargin: 80; + anchors.bottomMargin: root.assetName === "" ? 80 : 30; height: 50; width: 120; text: "Cancel"; @@ -1691,7 +1778,7 @@ Item { anchors.right: parent.right; anchors.rightMargin: 12; anchors.bottom: parent.bottom; - anchors.bottomMargin: 80; + anchors.bottomMargin: root.assetName === "" ? 80 : 30; height: 50; width: 120; text: "Retry"; @@ -1768,7 +1855,7 @@ Item { switch (message.method) { case 'selectRecipient': if (message.isSelected) { - chooseRecipientNearby.selectedRecipient = message.id[0]; + chooseRecipientNearby.selectedRecipient = message.id; sendAssetStep.selectedRecipientDisplayName = message.displayName; sendAssetStep.selectedRecipientUserName = message.userName; } else { diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 7d7a882ee0..4db98091c1 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -239,7 +239,6 @@ Item { width: 62; onLoaded: { - item.enabled = (root.purchaseStatus === "confirmed"); item.buttonGlyphText = hifi.glyphs.gift; item.buttonText = "Gift"; item.buttonClicked = function() { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 08e3e7a552..6b48f8d51d 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -124,6 +124,14 @@ Rectangle { root.numUpdatesAvailable = result.data.updates.length; } } + + onAppInstalled: { + root.installedApps = Commerce.getInstalledApps(); + } + + onAppUninstalled: { + root.installedApps = Commerce.getInstalledApps(); + } } Timer { @@ -249,6 +257,145 @@ Rectangle { Commerce.getWalletStatus(); } } + + Item { + id: installedAppsContainer; + z: 998; + visible: false; + anchors.top: titleBarContainer.bottom; + anchors.topMargin: -titleBarContainer.additionalDropdownHeight; + anchors.left: parent.left; + anchors.bottom: parent.bottom; + width: parent.width; + + RalewayRegular { + id: installedAppsHeader; + anchors.top: parent.top; + anchors.topMargin: 10; + anchors.left: parent.left; + anchors.leftMargin: 12; + height: 80; + width: paintedWidth; + text: "All Installed Marketplace Apps"; + color: hifi.colors.black; + size: 22; + } + + ListView { + id: installedAppsList; + clip: true; + model: installedAppsModel; + snapMode: ListView.SnapToItem; + // Anchors + anchors.top: installedAppsHeader.bottom; + anchors.left: parent.left; + anchors.bottom: sideloadAppButton.top; + width: parent.width; + delegate: Item { + width: parent.width; + height: 40; + + RalewayRegular { + text: model.appUrl; + // Text size + size: 16; + // Anchors + anchors.left: parent.left; + anchors.leftMargin: 12; + height: parent.height; + anchors.right: sideloadAppOpenButton.left; + anchors.rightMargin: 8; + elide: Text.ElideRight; + // Style + color: hifi.colors.black; + // Alignment + verticalAlignment: Text.AlignVCenter; + + MouseArea { + anchors.fill: parent; + onClicked: { + Window.copyToClipboard((model.appUrl).slice(0, -9)); + } + } + } + + HifiControlsUit.Button { + id: sideloadAppOpenButton; + text: "OPEN"; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.dark; + anchors.top: parent.top; + anchors.topMargin: 2; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 2; + anchors.right: uninstallGlyph.left; + anchors.rightMargin: 8; + width: 80; + onClicked: { + Commerce.openApp(model.appUrl); + } + } + + HiFiGlyphs { + id: uninstallGlyph; + text: hifi.glyphs.close; + color: hifi.colors.black; + size: 22; + anchors.top: parent.top; + anchors.right: parent.right; + anchors.rightMargin: 6; + width: 35; + height: parent.height; + horizontalAlignment: Text.AlignHCenter; + MouseArea { + anchors.fill: parent; + hoverEnabled: true; + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + onExited: { + parent.text = hifi.glyphs.close; + } + onClicked: { + Commerce.uninstallApp(model.appUrl); + } + } + } + } + } + HifiControlsUit.Button { + id: sideloadAppButton; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.dark; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 8; + anchors.left: parent.left; + anchors.leftMargin: 8; + anchors.right: closeAppListButton.left; + anchors.rightMargin: 8; + height: 40; + text: "SIDELOAD APP FROM LOCAL DISK"; + onClicked: { + Window.browseChanged.connect(onFileOpenChanged); + Window.browseAsync("Locate your app's .app.json file", "", "*.app.json"); + } + } + HifiControlsUit.Button { + id: closeAppListButton; + color: hifi.buttons.white; + colorScheme: hifi.colorSchemes.dark; + anchors.bottom: parent.bottom; + anchors.bottomMargin: 8; + anchors.right: parent.right; + anchors.rightMargin: 8; + width: 100; + height: 40; + text: "BACK"; + onClicked: { + installedAppsContainer.visible = false; + } + } + } HifiWallet.NeedsLogIn { id: needsLogIn; @@ -317,7 +464,7 @@ Rectangle { // Item { id: purchasesContentsContainer; - visible: root.activeView === "purchasesMain"; + visible: root.activeView === "purchasesMain" && !installedAppsList.visible; // Anchors anchors.left: parent.left; anchors.right: parent.right; @@ -959,6 +1106,39 @@ Rectangle { } } + Keys.onPressed: { + if ((event.key == Qt.Key_F) && (event.modifiers & Qt.ControlModifier)) { + installedAppsContainer.visible = !installedAppsContainer.visible; + console.log("User changed visibility of installedAppsContainer to " + installedAppsContainer.visible); + } + } + function onFileOpenChanged(filename) { + // disconnect the event, otherwise the requests will stack up + try { // Not all calls to onFileOpenChanged() connect an event. + Window.browseChanged.disconnect(onFileOpenChanged); + } catch (e) { + console.log('Purchases.qml ignoring', e); + } + if (filename) { + Commerce.installApp(filename); + } + } + ListModel { + id: installedAppsModel; + } + onInstalledAppsChanged: { + installedAppsModel.clear(); + var installedAppsArray = root.installedApps.split(","); + var installedAppsObject = []; + // "- 1" because the last app string ends with "," + for (var i = 0; i < installedAppsArray.length - 1; i++) { + installedAppsObject[i] = { + "appUrl": installedAppsArray[i] + } + } + installedAppsModel.append(installedAppsObject); + } + // // Function Name: fromScript() // diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f19422c442..577b498ce0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -145,6 +145,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "AudioClient.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" @@ -1060,6 +1070,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (steamClient) { qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID(); } + setCrashAnnotation("steam", property(hifi::properties::STEAM).toBool() ? "1" : "0"); + qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion()); qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION; qCDebug(interfaceapp) << "[VERSION] VERSION:" << BuildInfo::VERSION; @@ -1145,6 +1157,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl))); + connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){ + setCrashAnnotation("domain", domainURL.toString().toStdString()); + }); connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle())); connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle())); @@ -1190,6 +1205,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto dialogsManager = DependencyManager::get(); connect(accountManager.data(), &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog); connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle); + connect(accountManager.data(), &AccountManager::usernameChanged, [](QString username){ + setCrashAnnotation("username", username.toStdString()); + }); // set the account manager's root URL and trigger a login request if we don't have the access token accountManager->setIsAgent(true); @@ -1207,6 +1225,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount); connect(this, &Application::activeDisplayPluginChanged, this, [](){ qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode()); + auto displayPlugin = qApp->getActiveDisplayPlugin(); + setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString()); + setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0"); }); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode); @@ -1214,6 +1235,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(myAvatar.get(), &MyAvatar::positionGoneTo, DependencyManager::get().data(), &AddressManager::storeCurrentAddress); + connect(myAvatar.get(), &MyAvatar::skeletonModelURLChanged, [](){ + QUrl avatarURL = qApp->getMyAvatar()->getSkeletonModelURL(); + setCrashAnnotation("avatar", avatarURL.toString().toStdString()); + }); + + // Inititalize sample before registering _sampleSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/sample.wav")); @@ -1306,6 +1333,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Needs to happen AFTER the render engine initialization to access its configuration initializeUi(); + updateVerboseLogging(); + init(); qCDebug(interfaceapp, "init() complete."); @@ -1322,49 +1351,48 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Make sure we don't time out during slow operations at startup updateHeartbeat(); - // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. - // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. - static const QString TESTER = "HIFI_TESTER"; - auto gpuIdent = GPUIdent::getInstance(); - auto glContextData = getGLContextData(); - QJsonObject properties = { - { "version", applicationVersion() }, - { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) }, - { "previousSessionCrashed", _previousSessionCrashed }, - { "previousSessionRuntime", sessionRunTime.get() }, - { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, - { "kernel_type", QSysInfo::kernelType() }, - { "kernel_version", QSysInfo::kernelVersion() }, - { "os_type", QSysInfo::productType() }, - { "os_version", QSysInfo::productVersion() }, - { "gpu_name", gpuIdent->getName() }, - { "gpu_driver", gpuIdent->getDriver() }, - { "gpu_memory", static_cast(gpuIdent->getMemory()) }, - { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, - { "gl_version", glContextData["version"] }, - { "gl_vender", glContextData["vendor"] }, - { "gl_sl_version", glContextData["sl_version"] }, - { "gl_renderer", glContextData["renderer"] }, - { "ideal_thread_count", QThread::idealThreadCount() } - }; - auto macVersion = QSysInfo::macVersion(); - if (macVersion != QSysInfo::MV_None) { - properties["os_osx_version"] = QSysInfo::macVersion(); - } - auto windowsVersion = QSysInfo::windowsVersion(); - if (windowsVersion != QSysInfo::WV_None) { - properties["os_win_version"] = QSysInfo::windowsVersion(); + constexpr auto INSTALLER_INI_NAME = "installer.ini"; + auto iniPath = QDir(applicationDirPath()).filePath(INSTALLER_INI_NAME); + QFile installerFile { iniPath }; + std::unordered_map installerKeyValues; + if (installerFile.open(QIODevice::ReadOnly)) { + while (!installerFile.atEnd()) { + auto line = installerFile.readLine(); + if (!line.isEmpty()) { + auto index = line.indexOf("="); + if (index >= 0) { + installerKeyValues[line.mid(0, index).trimmed()] = line.mid(index + 1).trimmed(); + } + } + } } - ProcessorInfo procInfo; - if (getProcessorInfo(procInfo)) { - properties["processor_core_count"] = procInfo.numProcessorCores; - properties["logical_processor_count"] = procInfo.numLogicalProcessors; - properties["processor_l1_cache_count"] = procInfo.numProcessorCachesL1; - properties["processor_l2_cache_count"] = procInfo.numProcessorCachesL2; - properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3; + // In practice we shouldn't run across installs that don't have a known installer type. + // Client or Client+Server installs should always have the installer.ini next to their + // respective interface.exe, and Steam installs will be detected as such. If a user were + // to delete the installer.ini, though, and as an example, we won't know the context of the + // original install. + constexpr auto INSTALLER_KEY_TYPE = "type"; + constexpr auto INSTALLER_KEY_CAMPAIGN = "campaign"; + constexpr auto INSTALLER_TYPE_UNKNOWN = "unknown"; + constexpr auto INSTALLER_TYPE_STEAM = "steam"; + + auto typeIt = installerKeyValues.find(INSTALLER_KEY_TYPE); + QString installerType = INSTALLER_TYPE_UNKNOWN; + if (typeIt == installerKeyValues.end()) { + if (property(hifi::properties::STEAM).toBool()) { + installerType = INSTALLER_TYPE_STEAM; + } + } else { + installerType = typeIt->second; } + auto campaignIt = installerKeyValues.find(INSTALLER_KEY_CAMPAIGN); + QString installerCampaign = campaignIt != installerKeyValues.end() ? campaignIt->second : ""; + + qDebug() << "Detected installer type:" << installerType; + qDebug() << "Detected installer campaign:" << installerCampaign; + // add firstRun flag from settings to launch event Setting::Handle firstRun { Settings::firstRun, true }; @@ -1377,6 +1405,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo userActivityLogger.disable(false); } + QString machineFingerPrint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + if (userActivityLogger.isEnabled()) { // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. @@ -1386,6 +1416,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QJsonObject properties = { { "version", applicationVersion() }, { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) }, + { "installer_campaign", installerCampaign }, + { "installer_type", installerType }, { "previousSessionCrashed", _previousSessionCrashed }, { "previousSessionRuntime", sessionRunTime.get() }, { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, @@ -1424,11 +1456,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["first_run"] = firstRun.get(); // add the user's machine ID to the launch event - properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + properties["machine_fingerprint"] = machineFingerPrint; userActivityLogger.logAction("launch", properties); } + setCrashAnnotation("machine_fingerprint", machineFingerPrint.toStdString()); + _entityEditSender.setMyAvatar(myAvatar.get()); // The entity octree will have to know about MyAvatar for the parentJointName import @@ -1705,7 +1739,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater"; bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1; if (!noUpdater) { + constexpr auto INSTALLER_TYPE_CLIENT_ONLY = "client_only"; + auto applicationUpdater = DependencyManager::get(); + + AutoUpdater::InstallerType type = installerType == INSTALLER_TYPE_CLIENT_ONLY + ? AutoUpdater::InstallerType::CLIENT_ONLY : AutoUpdater::InstallerType::FULL; + + applicationUpdater->setInstallerType(type); + applicationUpdater->setInstallerCampaign(installerCampaign); connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); applicationUpdater->checkForUpdate(); } @@ -2165,6 +2207,46 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); } +void Application::updateVerboseLogging() { + bool enable = Menu::getInstance()->isOptionChecked(MenuOption::VerboseLogging); + + const_cast(&animation())->setEnabled(QtDebugMsg, enable); + const_cast(&animation())->setEnabled(QtInfoMsg, enable); + + const_cast(&avatars())->setEnabled(QtDebugMsg, enable); + const_cast(&avatars())->setEnabled(QtInfoMsg, enable); + + const_cast(&scriptengine())->setEnabled(QtDebugMsg, enable); + const_cast(&scriptengine())->setEnabled(QtInfoMsg, enable); + + const_cast(&modelformat())->setEnabled(QtDebugMsg, enable); + const_cast(&modelformat())->setEnabled(QtInfoMsg, enable); + + const_cast(&controllers())->setEnabled(QtDebugMsg, enable); + const_cast(&controllers())->setEnabled(QtInfoMsg, enable); + + const_cast(&resourceLog())->setEnabled(QtDebugMsg, enable); + const_cast(&resourceLog())->setEnabled(QtInfoMsg, enable); + + const_cast(&networking())->setEnabled(QtDebugMsg, enable); + const_cast(&networking())->setEnabled(QtInfoMsg, enable); + + const_cast(&asset_client())->setEnabled(QtDebugMsg, enable); + const_cast(&asset_client())->setEnabled(QtInfoMsg, enable); + + const_cast(&messages_client())->setEnabled(QtDebugMsg, enable); + const_cast(&messages_client())->setEnabled(QtInfoMsg, enable); + + const_cast(&storagelogging())->setEnabled(QtDebugMsg, enable); + const_cast(&storagelogging())->setEnabled(QtInfoMsg, enable); + + const_cast(&uiLogging())->setEnabled(QtDebugMsg, enable); + const_cast(&uiLogging())->setEnabled(QtInfoMsg, enable); + + const_cast(&glLogging())->setEnabled(QtDebugMsg, enable); + const_cast(&glLogging())->setEnabled(QtInfoMsg, enable); +} + void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { DomainHandler::ConnectionRefusedReason reasonCode = static_cast(reasonCodeInt); @@ -3036,7 +3118,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { PROFILE_RANGE(render, __FUNCTION__); bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll()); - qDebug() << "HandleSandboxStatus" << sandboxIsRunning; enum HandControllerType { Vive, diff --git a/interface/src/Application.h b/interface/src/Application.h index 38254ec81b..2a7b9d2a7b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -403,6 +403,8 @@ public slots: Q_INVOKABLE bool askBeforeSetAvatarUrl(const QString& avatarUrl) { return askToSetAvatarUrl(avatarUrl); } + void updateVerboseLogging(); + private slots: void onDesktopRootItemCreated(QQuickItem* qmlContext); void onDesktopRootContextCreated(QQmlContext* qmlContext); diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 228d78333a..177e6e493e 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -16,7 +16,8 @@ #include "Bookmarks.h" /**jsdoc - * This API helps manage adding and deleting Avatar bookmarks + * This API helps manage adding and deleting avatar bookmarks. + * @namespace AvatarBookmarks */ class AvatarBookmarks: public Bookmarks, public Dependency { @@ -27,16 +28,12 @@ public: AvatarBookmarks(); void setupMenus(Menu* menubar, MenuWrapper* menu) override; -/**jsdoc - * Add the current Avatar to your Avatar Bookmarks - * @function AvatarBookmarks.addBookMark - */ - -/**jsdoc - * @function AvatarBookmarks.deleteBookMark - */ public slots: + /**jsdoc + * Add the current Avatar to your avatar bookmarks. + * @function AvatarBookmarks.addBookMark + */ void addBookmark(); protected: diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index 99e5911591..7bd32ce7f1 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -49,7 +49,6 @@ protected: protected slots: /**jsdoc - * Delete * @function AvatarBookmarks.deleteBookmark */ void deleteBookmark(); diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index fcb1908994..8deddbda82 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -43,12 +43,10 @@ void ConnectionMonitor::init() { } void ConnectionMonitor::startTimer() { - qDebug() << "ConnectionMonitor: Starting timer"; _timer.start(DISPLAY_AFTER_DISCONNECTED_FOR_X_MS); } void ConnectionMonitor::stopTimer() { - qDebug() << "ConnectionMonitor: Stopping timer"; _timer.stop(); DependencyManager::get()->setDomainConnectionFailureVisibility(false); } diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp index 27da619af1..e39cd42d81 100644 --- a/interface/src/Crashpad.cpp +++ b/interface/src/Crashpad.cpp @@ -15,6 +15,8 @@ #if HAS_CRASHPAD +#include + #include #include @@ -23,8 +25,8 @@ #include #include #include -// #include -// #include +#include +#include using namespace crashpad; @@ -35,32 +37,19 @@ static std::wstring gIPCPipe; extern QString qAppFileName(); -// crashpad::AnnotationList* crashpadAnnotations { nullptr }; +std::mutex annotationMutex; +crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr }; #include LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { - static const DWORD EXTERNAL_EXCEPTION_CODE{ 0xe06d7363 }; - static const DWORD HEAP_CORRUPTION_CODE{ 0xc0000374 }; - - auto exceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode; - if (exceptionCode == EXTERNAL_EXCEPTION_CODE) { - return EXCEPTION_CONTINUE_SEARCH; - } - - if (exceptionCode == HEAP_CORRUPTION_CODE) { - qCritical() << "VectoredExceptionHandler: Heap corruption:" << QString::number(exceptionCode, 16); - + if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION || + pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN) { CrashpadClient client; if (gIPCPipe.length()) { - bool rc = client.SetHandlerIPCPipe(gIPCPipe); - qCritical() << "SetHandlerIPCPipe = " << rc; - } else { - qCritical() << "No IPC Pipe was previously defined for crash handler."; + client.SetHandlerIPCPipe(gIPCPipe); } - qCritical() << "Calling DumpAndCrash()"; client.DumpAndCrash(pExceptionInfo); - return EXCEPTION_CONTINUE_SEARCH; } return EXCEPTION_CONTINUE_SEARCH; @@ -116,12 +105,14 @@ bool startCrashHandler() { } void setCrashAnnotation(std::string name, std::string value) { - // if (!crashpadAnnotations) { - // crashpadAnnotations = new crashpad::AnnotationList(); // don't free this, let it leak - // crashpad::CrashpadInfo* crashpad_info = crashpad::GetCrashpadInfo(); - // crashpad_info->set_simple_annotations(crashpadAnnotations); - // } - // crashpadAnnotations->SetKeyValue(name, value); + std::lock_guard guard(annotationMutex); + if (!crashpadAnnotations) { + crashpadAnnotations = new crashpad::SimpleStringDictionary(); // don't free this, let it leak + crashpad::CrashpadInfo* crashpad_info = crashpad::CrashpadInfo::GetCrashpadInfo(); + crashpad_info->set_simple_annotations(crashpadAnnotations); + } + std::replace(value.begin(), value.end(), ',', ';'); + crashpadAnnotations->SetKeyValue(name, value); } #else diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 33cfc481d7..b3c059de7f 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -20,6 +20,7 @@ #include #include +#include "Crashpad.h" #include "DiscoverabilityManager.h" #include "Menu.h" @@ -127,10 +128,12 @@ void DiscoverabilityManager::updateLocation() { QNetworkAccessManager::PutOperation, callbackParameters); } - // Update Steam + // Update Steam and crash logger + QUrl currentAddress = addressManager->currentFacingPublicAddress(); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { - steamClient->updateLocation(domainHandler.getHostname(), addressManager->currentFacingPublicAddress()); + steamClient->updateLocation(domainHandler.getHostname(), currentAddress); } + setCrashAnnotation("address", currentAddress.toString().toStdString()); } void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index fa87a6c61b..e8737d92ae 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -49,21 +49,18 @@ public: * @function LODManager.setAutomaticLODAdjust * @param {boolean} value */ - Q_INVOKABLE void setAutomaticLODAdjust(bool value) { _automaticLODAdjust = value; } /**jsdoc * @function LODManager.getAutomaticLODAdjust * @returns {boolean} */ - Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; } /**jsdoc * @function LODManager.setDesktopLODDecreaseFPS - * @param {float} value + * @param {number} value */ - Q_INVOKABLE void setDesktopLODDecreaseFPS(float value); /**jsdoc @@ -77,28 +74,25 @@ public: * @function LODManager.getDesktopLODIncreaseFPS * @returns {number} */ - Q_INVOKABLE float getDesktopLODIncreaseFPS() const; /**jsdoc * @function LODManager.setHMDLODDecreaseFPS * @param {number} value */ - + Q_INVOKABLE void setHMDLODDecreaseFPS(float value); /**jsdoc * @function LODManager.getHMDLODDecreaseFPS * @returns {number} */ - Q_INVOKABLE float getHMDLODDecreaseFPS() const; /**jsdoc * @function LODManager.getHMDLODIncreaseFPS * @returns {number} */ - Q_INVOKABLE float getHMDLODIncreaseFPS() const; // User Tweakable LOD Items @@ -106,61 +100,54 @@ public: * @function LODManager.getLODFeedbackText * @returns {string} */ - Q_INVOKABLE QString getLODFeedbackText(); /**jsdoc * @function LODManager.setOctreeSizeScale * @param {number} sizeScale */ - Q_INVOKABLE void setOctreeSizeScale(float sizeScale); /**jsdoc * @function LODManager.getOctreeSizeScale * @returns {number} */ - Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; } /**jsdoc * @function LODManager.setBoundaryLevelAdjust * @param {number} boundaryLevelAdjust */ - Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust); /**jsdoc * @function LODManager.getBoundaryLevelAdjust * @returns {number} */ - Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } /**jsdoc * @function LODManager.getLODDecreaseFPS * @returns {number} */ - Q_INVOKABLE float getLODDecreaseFPS() const; /**jsdoc * @function LODManager.getLODIncreaseFPS * @returns {number} */ - Q_INVOKABLE float getLODIncreaseFPS() const; /**jsdoc * @namespace LODManager - * @property presentTime {number} - * @property engineRunTime {number} - * @property gpuTime {number} - * @property avgRenderTime {number} - * @property fps {number} - * @property lodLevel {number} - * @property lodDecreaseFPS {number} - * @property lodIncreaseFPS {number} + * @property {number} presentTime Read-only. + * @property {number} engineRunTime Read-only. + * @property {number} gpuTime Read-only. + * @property {number} avgRenderTime Read-only. + * @property {number} fps Read-only. + * @property {number} lodLevel Read-only. + * @property {number} lodDecreaseFPS Read-only. + * @property {number} lodIncreaseFPS Read-only. */ Q_PROPERTY(float presentTime READ getPresentTime) @@ -195,14 +182,12 @@ signals: * @function LODManager.LODIncreased * @returns {Signal} */ - void LODIncreased(); /**jsdoc * @function LODManager.LODDecreased * @returns {Signal} */ - void LODDecreased(); private: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 4384635147..50ff65ad1a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -810,6 +810,9 @@ Menu::Menu() { scriptEngines->loadScript(defaultScriptsLoc.toString()); }); + addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VerboseLogging, 0, false, + qApp, SLOT(updateVerboseLogging())); + #if 0 /// -------------- REMOVED FOR NOW -------------- addDisabledActionAndSeparator(navigateMenu, "History"); QAction* backAction = addActionToQMenuAndActionHash(navigateMenu, MenuOption::Back, 0, addressManager.data(), SLOT(goBack())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index bba70a6a89..c8c8ee42df 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -142,6 +142,7 @@ namespace MenuOption { const QString Pair = "Pair"; const QString PhysicsShowHulls = "Draw Collision Shapes"; const QString PhysicsShowOwned = "Highlight Simulation Ownership"; + const QString VerboseLogging = "Verbose Logging"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "General..."; const QString Quit = "Quit"; diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index 4fde25ecb8..ff8bfda6dd 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -28,12 +28,12 @@ class AudioScope : public QObject, public Dependency { /**jsdoc * The AudioScope API helps control the Audio Scope features in Interface * @namespace AudioScope - * @property {int} scopeInput - * @property {int} scopeOutputLeft - * @property {int} scopeOutputRight - * @property {int} triggerInput - * @property {int} triggerOutputLeft - * @property {int} triggerOutputRight + * @property {number} scopeInput Read-only. + * @property {number} scopeOutputLeft Read-only. + * @property {number} scopeOutputRight Read-only. + * @property {number} triggerInput Read-only. + * @property {number} triggerOutputLeft Read-only. + * @property {number} triggerOutputRight Read-only. */ Q_PROPERTY(QVector scopeInput READ getScopeInput) @@ -55,62 +55,52 @@ public slots: /**jsdoc * @function AudioScope.toggle */ - void toggle() { setVisible(!_isEnabled); } /**jsdoc * @function AudioScope.setVisible * @param {boolean} visible */ - void setVisible(bool visible); /**jsdoc * @function AudioScope.getVisible - * @param {boolean} visible * @returns {boolean} */ - bool getVisible() const { return _isEnabled; } /**jsdoc * @function AudioScope.togglePause */ - void togglePause() { setPause(!_isPaused); } /**jsdoc * @function AudioScope.setPause - * @param {boolean} + * @param {boolean} paused */ - void setPause(bool paused) { _isPaused = paused; emit pauseChanged(); } /**jsdoc * @function AudioScope.getPause * @returns {boolean} */ - bool getPause() { return _isPaused; } /**jsdoc * @function AudioScope.toggleTrigger */ - void toggleTrigger() { _autoTrigger = !_autoTrigger; } /**jsdoc * @function AudioScope.getAutoTrigger * @returns {boolean} */ - bool getAutoTrigger() { return _autoTrigger; } /**jsdoc * @function AudioScope.setAutoTrigger * @param {boolean} autoTrigger */ - void setAutoTrigger(bool autoTrigger) { _isTriggered = false; _autoTrigger = autoTrigger; } /**jsdoc @@ -118,109 +108,93 @@ public slots: * @param {number} x * @param {number} y */ - void setTriggerValues(int x, int y) { _triggerValues.x = x; _triggerValues.y = y; } /**jsdoc * @function AudioScope.setTriggered * @param {boolean} triggered */ - void setTriggered(bool triggered) { _isTriggered = triggered; } /**jsdoc * @function AudioScope.getTriggered * @returns {boolean} */ - bool getTriggered() { return _isTriggered; } /**jsdoc * @function AudioScope.getFramesPerSecond * @returns {number} */ - float getFramesPerSecond(); /**jsdoc * @function AudioScope.getFramesPerScope * @returns {number} */ - int getFramesPerScope() { return _framesPerScope; } /**jsdoc * @function AudioScope.selectAudioScopeFiveFrames */ - void selectAudioScopeFiveFrames(); /**jsdoc * @function AudioScope.selectAudioScopeTwentyFrames */ - void selectAudioScopeTwentyFrames(); /**jsdoc * @function AudioScope.selectAudioScopeFiftyFrames */ - void selectAudioScopeFiftyFrames(); /**jsdoc * @function AudioScope.getScopeInput - * @returns {number} + * @returns {number[]} */ - QVector getScopeInput() { return _scopeInputData; }; /**jsdoc * @function AudioScope.getScopeOutputLeft - * @returns {number} + * @returns {number[]} */ - QVector getScopeOutputLeft() { return _scopeOutputLeftData; }; /**jsdoc * @function AudioScope.getScopeOutputRight - * @returns {number} + * @returns {number[]} */ - QVector getScopeOutputRight() { return _scopeOutputRightData; }; /**jsdoc * @function AudioScope.getTriggerInput - * @returns {number} + * @returns {number[]} */ - QVector getTriggerInput() { return _triggerInputData; }; /**jsdoc * @function AudioScope.getTriggerOutputLeft - * @returns {number} + * @returns {number[]} */ - QVector getTriggerOutputLeft() { return _triggerOutputLeftData; }; /**jsdoc * @function AudioScope.getTriggerOutputRight - * @returns {number} + * @returns {number[]} */ - QVector getTriggerOutputRight() { return _triggerOutputRightData; }; /**jsdoc * @function AudioScope.setLocalEcho - * @parm {boolean} serverEcho + * @parm {boolean} localEcho */ - - void setLocalEcho(bool serverEcho); + void setLocalEcho(bool localEcho); /**jsdoc * @function AudioScope.setServerEcho * @parm {boolean} serverEcho */ - void setServerEcho(bool serverEcho); signals: @@ -229,14 +203,12 @@ signals: * @function AudioScope.pauseChanged * @returns {Signal} */ - void pauseChanged(); /**jsdoc * @function AudioScope.triggered * @returns {Signal} */ - void triggered(); protected: diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 192f183f30..d2655914d2 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -38,75 +38,6 @@ class AvatarManager : public AvatarHashMap { public: - // JSDOCS Copied over from AvatarHashMap (see AvatarHashMap.h for reason) - - /**jsdoc - * @function AvatarManager.getAvatarIdentifiers - */ - - /**jsdoc - * @function AvatarManager.getAvatarsInRange - * @param {Vec3} position - * @param {float} rangeMeters - * @returns {string[]} - */ - - /**jsdoc - * @function AvatarManager.getAvatar - * @param {string} avatarID - * @returns {ScriptAvatarData} - */ - - /**jsdoc - * @function AvatarManager.avatarAddedEvent - * @param {string} sessionUUID - * @returns {Signal} - */ - - /**jsdoc - * @function AvatarManager.avatarRemovedEvent - * @param {string} sessionUUID - * @returns {Signal} - */ - - /**jsdoc - * @function AvatarManager.avatarSessionChangedEvent - * @param {string} sessionUUID - * @param {string} oldUUID - * @returns {Signal} - */ - - /**jsdoc - * @function AvatarManager.isAvatarInRange - * @param {string} position - * @param {string} range - * @returns {boolean} - */ - - /**jsdoc - * @function AvatarManager.sessionUUIDChanged - * @param {string} sessionUUID - * @param {string} oldUUID - */ - - /**jsdoc - * @function AvatarManager.processAvatarDataPacket - * @param {} message - * @param {} sendingNode - */ - - /**jsdoc - * @function AvatarManager.processAvatarIdentityPacket - * @param {} message - * @param {} sendingNode - */ - - /**jsdoc - * @function AvatarManager.processKillAvatar - * @param {} message - * @param {} sendingNode - */ - /// Registers the script types associated with the avatar manager. static void registerMetaTypes(QScriptEngine* engine); @@ -119,10 +50,9 @@ public: /**jsdoc * @function AvatarManager.getAvatar - * @param {string} avatarID - * @returns {} + * @param {Uuid} avatarID + * @returns {AvatarData} */ - // Null/Default-constructed QUuids will return MyAvatar Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) override { return new ScriptAvatar(getAvatarBySessionID(avatarID)); } @@ -148,16 +78,15 @@ public: /**jsdoc * @function AvatarManager.getAvatarDataRate - * @param {string} sessionID + * @param {Uuid} sessionID * @param {string} [rateName=""] * @returns {number} */ - Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")) const; /**jsdoc * @function AvatarManager.getAvatarUpdateRate - * @param {string} sessionID + * @param {Uuid} sessionID * @param {string} [rateName=""] * @returns {number} */ @@ -166,51 +95,47 @@ public: /**jsdoc * @function AvatarManager.getAvatarSimulationRate - * @param {string} sessionID + * @param {Uuid} sessionID * @param {string} [rateName=""] * @returns {number} */ - + Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")) const; /**jsdoc * @function AvatarManager.findRayIntersection * @param {PickRay} ray - * @param {} avatarIdsToInclude - * @param {} avatarIdsToDiscard + * @param {Uuid[]} [avatarsToInclude=[]] + * @param {Uuid[]} [avatarsToDiscard=[]] * @returns {RayToAvatarIntersectionResult} */ - Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue()); /**jsdoc * @function AvatarManager.findRayIntersectionVector * @param {PickRay} ray - * @param {} avatarsToInclude - * @param {} avatarIdsToDiscard + * @param {Uuid[]} avatarsToInclude + * @param {Uuid[]} avatarsToDiscard * @returns {RayToAvatarIntersectionResult} */ - Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray, const QVector& avatarsToInclude, const QVector& avatarsToDiscard); - // TODO: remove this HACK once we settle on optimal default sort coefficients /**jsdoc * @function AvatarManager.getAvatarSortCoefficient * @param {string} name * @returns {number} */ - + // TODO: remove this HACK once we settle on optimal default sort coefficients Q_INVOKABLE float getAvatarSortCoefficient(const QString& name); /**jsdoc * @function AvatarManager.setAvatarSortCoefficient * @param {string} name - * @param {string} value + * @param {number} value */ - Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value); float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } @@ -221,7 +146,6 @@ public slots: * @function AvatarManager.updateAvatarRenderStatus * @param {boolean} shouldRenderAvatars */ - void updateAvatarRenderStatus(bool shouldRenderAvatars); private: diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a6d637d184..74f7a3c89f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -60,6 +60,10 @@ class MyAvatar : public Avatar { * change the avatar's position within the domain, or manage the avatar's collisions with other objects. * * @namespace MyAvatar + * + * @hifi-interface + * @hifi-client-entity + * * @property {Vec3} qmlPosition - A synonym for position for use by QML. * @property {boolean} shouldRenderLocally=true - If true then your avatar is rendered for you in Interface, * otherwise it is not rendered for you (but it is still rendered for other users). diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 37ebf9159d..d4af0bbd37 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -67,13 +67,11 @@ public slots: * @function FaceTracker.setEnabled * @param {boolean} enabled */ - void setEnabled(bool enabled) override; /**jsdoc * @function FaceTracker.calibrate */ - void calibrate(); private slots: diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 288d3008bb..f2cd9287a5 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -109,7 +109,7 @@ public: * * @typedef {Object} Picks.RayPickResult * @property {number} type The intersection type. - * @property {bool} intersects If there was a valid intersection (type != INTERSECTED_NONE) + * @property {boolean} intersects If there was a valid intersection (type != INTERSECTED_NONE) * @property {Uuid} objectID The ID of the intersected object. Uuid.NULL for the HUD or invalid intersections. * @property {float} distance The distance to the intersection point from the origin of the ray. * @property {Vec3} intersection The intersection point in world-space. @@ -123,7 +123,7 @@ public: * * @typedef {Object} Picks.StylusPickResult * @property {number} type The intersection type. - * @property {bool} intersects If there was a valid intersection (type != INTERSECTED_NONE) + * @property {boolean} intersects If there was a valid intersection (type != INTERSECTED_NONE) * @property {Uuid} objectID The ID of the intersected object. Uuid.NULL for the HUD or invalid intersections. * @property {float} distance The distance to the intersection point from the origin of the ray. * @property {Vec3} intersection The intersection point in world-space. diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index 65c083b8e4..d38a84d8fa 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -39,10 +39,10 @@ class AccountServicesScriptingInterface : public QObject { * The AccountServices API contains helper functions related to user connectivity * * @namespace AccountServices - * @property {string} username - * @property {boolean} loggedIn + * @property {string} username Read-only. + * @property {boolean} loggedIn Read-only. * @property {string} findableBy - * @property {string} metaverseServerURL + * @property {string} metaverseServerURL Read-only. */ Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged) @@ -63,33 +63,28 @@ public slots: * @function AccountServices.getDownloadInfo * @returns {DownloadInfoResult} */ - DownloadInfoResult getDownloadInfo(); /**jsdoc * @function AccountServices.updateDownloadInfo */ - void updateDownloadInfo(); /**jsdoc * @function AccountServices.isLoggedIn * @returns {boolean} */ - bool isLoggedIn(); /**jsdoc * @function AccountServices.checkAndSignalForAccessToken * @returns {boolean} */ - bool checkAndSignalForAccessToken(); /**jsdoc * @function AccountServices.logOut */ - void logOut(); private slots: @@ -108,47 +103,41 @@ signals: * @function AccountServices.connected * @returns {Signal} */ - void connected(); /**jsdoc * @function AccountServices.disconnected - * @params {string} reason + * @param {string} reason * @returns {Signal} */ - void disconnected(const QString& reason); /**jsdoc * @function AccountServices.myUsernameChanged - * @params {string} username + * @param {string} username * @returns {Signal} */ - void myUsernameChanged(const QString& username); /**jsdoc * @function AccountServices.downloadInfoChanged - * @params {} info + * @param {} info * @returns {Signal} */ - void downloadInfoChanged(DownloadInfoResult info); /**jsdoc * @function AccountServices.findableByChanged - * @params {string} discoverabilityMode + * @param {string} discoverabilityMode * @returns {Signal} */ - void findableByChanged(const QString& discoverabilityMode); /**jsdoc * @function AccountServices.loggedInChanged - * @params {boolean} loggedIn + * @param {boolean} loggedIn * @returns {Signal} */ - void loggedInChanged(bool loggedIn); private: diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index b7cd3067be..c77d1522b5 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -31,10 +31,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { * @namespace Audio * @property {boolean} muted * @property {boolean} noiseReduction - * @property {boolean} inputVolume - * @property {boolean} inputLevel - * @property {string} context - * @property {} devices + * @property {number} inputVolume + * @property {number} inputLevel Read-only. + * @property {string} context Read-only. + * @property {} devices Read-only. */ Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) @@ -66,7 +66,6 @@ public: * @param {} device * @param {boolean} isHMD */ - Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device, bool isHMD); /**jsdoc @@ -74,40 +73,36 @@ public: * @param {} device * @param {boolean} isHMD */ - Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device, bool isHMD); /**jsdoc * @function Audio.setReverb * @param {boolean} enable */ - Q_INVOKABLE void setReverb(bool enable); /**jsdoc * @function Audio.setReverbOptions * @param {} options */ - Q_INVOKABLE void setReverbOptions(const AudioEffectOptions* options); /**jsdoc - * @function Audio.setReverbOptions + * @function Audio.startRecording * @param {string} filename + * @returns {boolean} */ - Q_INVOKABLE bool startRecording(const QString& filename); /**jsdoc * @function Audio.stopRecording */ - Q_INVOKABLE void stopRecording(); /**jsdoc * @function Audio.getRecording + * @returns {boolean} */ - Q_INVOKABLE bool getRecording(); signals: @@ -116,39 +111,34 @@ signals: * @function Audio.nop * @returns {Signal} */ - void nop(); /**jsdoc - * @function Audio.nop - * @param {bool} isMuted + * @function Audio.mutedChanged + * @param {boolean} isMuted * @returns {Signal} */ - void mutedChanged(bool isMuted); /**jsdoc * @function Audio.noiseReductionChanged - * @param {bool} isEnabled + * @param {boolean} isEnabled * @returns {Signal} */ - void noiseReductionChanged(bool isEnabled); /**jsdoc * @function Audio.inputVolumeChanged - * @param {float} volume + * @param {number} volume * @returns {Signal} */ - void inputVolumeChanged(float volume); /**jsdoc * @function Audio.inputLevelChanged - * @param {float} level + * @param {number} level * @returns {Signal} */ - void inputLevelChanged(float level); /**jsdoc @@ -156,7 +146,6 @@ signals: * @param {string} context * @returns {Signal} */ - void contextChanged(const QString& context); public slots: @@ -165,7 +154,6 @@ public slots: * @function Audio.onContextChanged * @returns {Signal} */ - void onContextChanged(); private slots: diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index ee615cde20..a3c80bf1b6 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -108,11 +108,9 @@ AudioDeviceList::~AudioDeviceList() { // store the selected device foreach(std::shared_ptr adevice, _devices) { if (adevice->selectedDesktop) { - qDebug() << "Saving Desktop for" << _mode << "name" << adevice->info.deviceName(); settingDesktop.set(adevice->info.deviceName()); } if (adevice->selectedHMD) { - qDebug() << "Saving HMD for" << _mode << "name" << adevice->info.deviceName(); settingHMD.set(adevice->info.deviceName()); } } @@ -311,7 +309,6 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) { } } - qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode; newDevices.push_back(newDevice(device)); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index f19caa8478..4fceda3b04 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -28,7 +28,7 @@ class ScriptEngine; /**jsdoc * The Controller API provides facilities to interact with computer and controller hardware. * - *
Functions:
+ *
Functions
* *

Properties

*
    @@ -143,6 +143,61 @@ class ScriptEngine; *
  • {@link Controller.stopInputPlayback|stopInputPlayback}
  • *
* + *
Entity Methods:
+ * + *

The default scripts implement hand controller actions that use {@link Entities.callEntityMethod} to call entity script + * methods, if present in the entity being interacted with.

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Method NameDescriptionExample
startFarTrigger
continueFarTrigger
stopFarTrigger
These methods are called when a user is more than 0.3m away from the entity, the entity is triggerable, and the + * user starts, continues, or stops squeezing the trigger.A light switch that can be toggled on and off from a distance.
startNearTrigger
continueNearTrigger
stopNearTrigger
These methods are called when a user is less than 0.3m away from the entity, the entity is triggerable, and the + * user starts, continues, or stops squeezing the trigger.A doorbell that can be rung when a user is near.
startDistanceGrab
continueDistanceGrab
These methods are called when a user is more than 0.3m away from the entity, the entity is either cloneable, or + * grabbable and not locked, and the user starts or continues to squeeze the trigger.A comet that emits icy particle trails when a user is dragging it through the sky.
startNearGrab
continueNearGrab
These methods are called when a user is less than 0.3m away from the entity, the entity is either cloneable, or + * grabbable and not locked, and the user starts or continues to squeeze the trigger.A ball that glows when it's being held close.
releaseGrabThis method is called when a user releases the trigger when having been either distance or near grabbing an + * entity.Turn off the ball glow or comet trail with the user finishes grabbing it.
startEquip
continueEquip
releaseEquip
These methods are called when a user starts, continues, or stops equipping an entity.A glass that stays in the user's hand after the trigger is clicked.
+ *

All the entity methods are called with the following two arguments:

+ *
    + *
  • The entity ID.
  • + *
  • A string, "hand,userID" — where "hand" is "left" or "right", and "userID" + * is the user's {@link MyAvatar|MyAvatar.sessionUUID}.
  • + *
+ * * @namespace Controller * * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 55d2236ec1..5c37b394fa 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -32,7 +32,6 @@ public slots: * @function GooglePoly.setAPIKey * @param {string} key */ - void setAPIKey(const QString& key); /**jsdoc @@ -42,7 +41,6 @@ public slots: * @param {string} format * @returns {string} */ - QString getAssetList(const QString& keyword, const QString& category, const QString& format); /**jsdoc @@ -51,7 +49,6 @@ public slots: * @param {string} category * @returns {string} */ - QString getFBX(const QString& keyword, const QString& category); /**jsdoc @@ -60,7 +57,6 @@ public slots: * @param {string} category * @returns {string} */ - QString getOBJ(const QString& keyword, const QString& category); /**jsdoc @@ -69,7 +65,6 @@ public slots: * @param {string} category * @returns {string} */ - QString getBlocks(const QString& keyword, const QString& category); /**jsdoc @@ -78,7 +73,6 @@ public slots: * @param {string} category * @returns {string} */ - QString getGLTF(const QString& keyword, const QString& category); /**jsdoc @@ -87,7 +81,6 @@ public slots: * @param {string} category * @returns {string} */ - QString getGLTF2(const QString& keyword, const QString& category); /**jsdoc @@ -96,7 +89,6 @@ public slots: * @param {string} category * @returns {string} */ - QString getTilt(const QString& keyword, const QString& category); /**jsdoc @@ -104,7 +96,6 @@ public slots: * @param {string} input * @returns {string} */ - QString getModelInfo(const QString& input); private: diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 8a8dc61ba8..0b766d2097 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -87,7 +87,7 @@ public slots: * Display a dialog with the specified message and an "OK" button. The dialog is non-modal; the script continues without * waiting for a user response. * @function Window.alert - * @param {string} message="" - The message to display. + * @param {string} [message=""] - The message to display. * @example Display a friendly greeting. * Window.alert("Welcome!"); * print("Script continues without waiting"); @@ -98,7 +98,7 @@ public slots: * Prompt the user to confirm something. Displays a modal dialog with a message plus "Yes" and "No" buttons. * responds. * @function Window.confirm - * @param {string} message="" - The question to display. + * @param {string} [message=""] - The question to display. * @returns {boolean} true if the user selects "Yes", otherwise false. * @example Ask the user a question requiring a yes/no answer. * var answer = Window.confirm("Are you sure?"); @@ -128,8 +128,8 @@ public slots: * buttons. A {@link Window.promptTextChanged|promptTextChanged} signal is emitted when the user OKs the dialog; no signal * is emitted if the user cancels the dialog. * @function Window.promptAsync - * @param {string} message - The question to display. - * @param {string} defaultText - The default answer text. + * @param {string} [message=""] - The question to display. + * @param {string} [defaultText=""] - The default answer text. * @example Ask the user a question requiring a text answer without waiting for the answer. * function onPromptTextChanged(text) { * print("User answer: " + text); @@ -144,8 +144,8 @@ public slots: /**jsdoc * Prompt the user to choose a directory. Displays a modal dialog that navigates the directory tree. * @function Window.browseDir - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. * @returns {string} The path of the directory if one is chosen, otherwise null. * @example Ask the user to choose a directory. * var directory = Window.browseDir("Select Directory", Paths.resources); @@ -158,8 +158,8 @@ public slots: * {@link Window.browseDirChanged|browseDirChanged} signal is emitted when a directory is chosen; no signal is emitted if * the user cancels the dialog. * @function Window.browseDirAsync - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. * @example Ask the user to choose a directory without waiting for the answer. * function onBrowseDirChanged(directory) { * print("Directory: " + directory); @@ -174,9 +174,9 @@ public slots: /**jsdoc * Prompt the user to choose a file. Displays a modal dialog that navigates the directory tree. * @function Window.browse - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. - * @param {string} nameFilter="" - The types of files to display. Examples: "*.json" and + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. + * @param {string} [nameFilter=""] - The types of files to display. Examples: "*.json" and * "Images (*.png *.jpg *.svg)". All files are displayed if a filter isn't specified. * @returns {string} The path and name of the file if one is chosen, otherwise null. * @example Ask the user to choose an image file. @@ -190,9 +190,9 @@ public slots: * {@link Window.browseChanged|browseChanged} signal is emitted when a file is chosen; no signal is emitted if the user * cancels the dialog. * @function Window.browseAsync - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. - * @param {string} nameFilter="" - The types of files to display. Examples: "*.json" and + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. + * @param {string} [nameFilter=""] - The types of files to display. Examples: "*.json" and * "Images (*.png *.jpg *.svg)". All files are displayed if a filter isn't specified. * @example Ask the user to choose an image file without waiting for the answer. * function onBrowseChanged(filename) { @@ -209,9 +209,9 @@ public slots: * Prompt the user to specify the path and name of a file to save to. Displays a model dialog that navigates the directory * tree and allows the user to type in a file name. * @function Window.save - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. - * @param {string} nameFilter="" - The types of files to display. Examples: "*.json" and + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. + * @param {string} [nameFilter=""] - The types of files to display. Examples: "*.json" and * "Images (*.png *.jpg *.svg)". All files are displayed if a filter isn't specified. * @returns {string} The path and name of the file if one is specified, otherwise null. If a single file type * is specified in the nameFilter, that file type extension is automatically appended to the result when appropriate. @@ -226,9 +226,9 @@ public slots: * directory tree and allows the user to type in a file name. A {@link Window.saveFileChanged|saveFileChanged} signal is * emitted when a file is specified; no signal is emitted if the user cancels the dialog. * @function Window.saveAsync - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. - * @param {string} nameFilter="" - The types of files to display. Examples: "*.json" and + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. + * @param {string} [nameFilter=""] - The types of files to display. Examples: "*.json" and * "Images (*.png *.jpg *.svg)". All files are displayed if a filter isn't specified. * @example Ask the user to specify a file to save to without waiting for an answer. * function onSaveFileChanged(filename) { @@ -245,9 +245,9 @@ public slots: * Prompt the user to choose an Asset Server item. Displays a modal dialog that navigates the tree of assets on the Asset * Server. * @function Window.browseAssets - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. - * @param {string} nameFilter="" - The types of files to display. Examples: "*.json" and + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. + * @param {string} [nameFilter=""] - The types of files to display. Examples: "*.json" and * "Images (*.png *.jpg *.svg)". All files are displayed if a filter isn't specified. * @returns {string} The path and name of the asset if one is chosen, otherwise null. * @example Ask the user to select an FBX asset. @@ -261,9 +261,9 @@ public slots: * Asset Server. A {@link Window.assetsDirChanged|assetsDirChanged} signal is emitted when an asset is chosen; no signal is * emitted if the user cancels the dialog. * @function Window.browseAssetsAsync - * @param {string} title="" - The title to display at the top of the dialog. - * @param {string} directory="" - The initial directory to start browsing at. - * @param {string} nameFilter="" - The types of files to display. Examples: "*.json" and + * @param {string} [title=""] - The title to display at the top of the dialog. + * @param {string} [directory=""] - The initial directory to start browsing at. + * @param {string} [nameFilter=""] - The types of files to display. Examples: "*.json" and * "Images (*.png *.jpg *.svg)". All files are displayed if a filter isn't specified. * @example * function onAssetsDirChanged(asset) { @@ -280,7 +280,7 @@ public slots: * Open the Asset Browser dialog. If a file to upload is specified, the user is prompted to enter the folder and name to * map the file to on the asset server. * @function Window.showAssetServer - * @param {string} uploadFile="" - The path and name of a file to upload to the asset server. + * @param {string} [uploadFile=""] - The path and name of a file to upload to the asset server. * @example Upload a file to the asset server. * var filename = Window.browse("Select File to Add to Asset Server", Paths.resources); * print("File: " + filename); @@ -317,14 +317,14 @@ public slots: * NOTE: to provide a non-default value - all previous parameters must be provided. * General > Snapshots. * @function Window.takeSnapshot - * @param {boolean} notify=true - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} + * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {boolean} includeAnimated=false - If true, a moving image is captured as an animated GIF in addition + * @param {boolean} [includeAnimated=false] - If true, a moving image is captured as an animated GIF in addition * to a still image. - * @param {number} aspectRatio=0 - The width/height ratio of the snapshot required. If the value is 0 the + * @param {number} [aspectRatio=0] - The width/height ratio of the snapshot required. If the value is 0 the * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. - * @param {string} filename="" - If this parameter is not given, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. + * @param {string} [filename=""] - If this parameter is not given, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. * If this parameter is "" then the image will be saved as ".jpg". * Otherwise, the image will be saved to this filename, with an appended ".jpg". * @@ -358,7 +358,7 @@ public slots: * Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API. * NOTE: to provide a non-default value - all previous parameters must be provided. * @function Window.takeSecondaryCameraSnapshot - * @param {string} filename="" - If this parameter is not given, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. + * @param {string} [filename=""] - If this parameter is not given, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. * If this parameter is "" then the image will be saved as ".jpg". * Otherwise, the image will be saved to this filename, with an appended ".jpg". * @@ -397,7 +397,7 @@ public slots: * has been prepared. * @function Window.shareSnapshot * @param {string} path - The path and name of the image file to share. - * @param {string} href="" - The metaverse location where the snapshot was taken. + * @param {string} [href=""] - The metaverse location where the snapshot was taken. */ void shareSnapshot(const QString& path, const QUrl& href = QUrl("")); diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h index c34542735e..a9d1509770 100644 --- a/interface/src/ui/AvatarInputs.h +++ b/interface/src/ui/AvatarInputs.h @@ -26,10 +26,10 @@ class AvatarInputs : public QObject { /**jsdoc * API to help manage your Avatar's input * @namespace AvatarInputs - * @param {boolean} cameraEnabled - * @param {boolean} cameraMuted - * @param {boolean} isHMD - * @param {boolean} showAudioTools + * @property {boolean} cameraEnabled Read-only. + * @property {boolean} cameraMuted Read-only. + * @property {boolean} isHMD Read-only. + * @property {boolean} showAudioTools */ AI_PROPERTY(bool, cameraEnabled, false) @@ -46,8 +46,8 @@ public: * @param {number} loudness * @returns {number} */ - Q_INVOKABLE float loudnessToAudioLevel(float loudness); + AvatarInputs(QObject* parent = nullptr); void update(); bool showAudioTools() const { return _showAudioTools; } @@ -58,7 +58,6 @@ public slots: * @function AvatarInputs.setShowAudioTools * @param {boolean} showAudioTools */ - void setShowAudioTools(bool showAudioTools); signals: @@ -67,14 +66,12 @@ signals: * @function AvatarInputs.cameraEnabledChanged * @returns {Signal} */ - void cameraEnabledChanged(); /**jsdoc * @function AvatarInputs.cameraMutedChanged * @returns {Signal} */ - void cameraMutedChanged(); /**jsdoc @@ -89,7 +86,6 @@ signals: * @param {boolean} show * @returns {Signal} */ - void showAudioToolsChanged(bool show); protected: @@ -97,13 +93,11 @@ protected: /**jsdoc * @function AvatarInputs.resetSensors */ - Q_INVOKABLE void resetSensors(); /**jsdoc * @function AvatarInputs.toggleCameraMute */ - Q_INVOKABLE void toggleCameraMute(); private: diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 310a4cc1cd..d01e7d6671 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -80,7 +80,6 @@ void DialogsManager::showFeed() { } void DialogsManager::setDomainConnectionFailureVisibility(bool visible) { - qDebug() << "DialogsManager::setDomainConnectionFailureVisibility: visible" << visible; auto tabletScriptingInterface = DependencyManager::get(); auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); diff --git a/libraries/animation/src/AnimExpression.cpp b/libraries/animation/src/AnimExpression.cpp index 79004a72a6..9777e9c6af 100644 --- a/libraries/animation/src/AnimExpression.cpp +++ b/libraries/animation/src/AnimExpression.cpp @@ -588,6 +588,7 @@ void AnimExpression::evalUnaryMinus(const AnimVariantMap& map, std::stack #include -/**jsdoc - * API to manage Animation Cache resources - * @namespace AnimationCache - */ - class Animation; typedef QSharedPointer AnimationPointer; @@ -35,79 +30,67 @@ class AnimationCache : public ResourceCache, public Dependency { SINGLETON_DEPENDENCY public: - // Copied over from ResourceCache (see ResourceCache.h for reason) + + // Properties are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc + * API to manage animation cache resources. * @namespace AnimationCache - * @property numTotal {number} total number of total resources - * @property numCached {number} total number of cached resource - * @property sizeTotal {number} size in bytes of all resources - * @property sizeCached {number} size in bytes of all cached resources + * + * @property {number} numTotal - Total number of total resources. Read-only. + * @property {number} numCached - Total number of cached resource. Read-only. + * @property {number} sizeTotal - Size in bytes of all resources. Read-only. + * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. */ - /**jsdoc - * Returns the total number of resources - * @function AnimationCache.getNumTotalResources - * @returns {number} - */ + // Functions are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc - * Returns the total size in bytes of all resources - * @function AnimationCache.getSizeTotalResources - * @returns {number} - */ - - /**jsdoc - * Returns the total number of cached resources - * @function AnimationCache.getNumCachedResources - * @returns {number} - */ - - /**jsdoc - * Returns the total size in bytes of cached resources - * @function AnimationCache.getSizeCachedResources - * @returns {number} - */ - - /**jsdoc - * Returns list of all resource urls + /**jsdoc + * Get the list of all resource URLs. * @function AnimationCache.getResourceList - * @returns {string[]} + * @return {string[]} */ - /**jsdoc - * Asynchronously loads a resource from the spedified URL and returns it. - * @param url {string} url of resource to load - * @param fallback {string} fallback URL if load of the desired url fails - * @function AnimationCache.getResource - * @returns {Resource} - */ - - /**jsdoc - * Prefetches a resource. - * @param url {string} url of resource to load - * @function AnimationCache.prefetch - * @returns {Resource} - */ - - /**jsdoc - * @param {number} deltaSize - * @function AnimationCache.updateTotalSize - * @returns {Resource} - */ - - /**jsdoc + /**jsdoc * @function AnimationCache.dirty - * @returns {Signal} + * @returns {Signal} */ + /**jsdoc + * @function AnimationCache.updateTotalSize + * @param {number} deltaSize + */ + + /**jsdoc + * @function AnimationCache.prefetch + * @param {string} url + * @param {object} extra + * @returns {object} + */ + + /**jsdoc + * Asynchronously loads a resource from the specified URL and returns it. + * @function AnimationCache.getResource + * @param {string} url - URL of the resource to load. + * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. + * @param {} [extra=null] + * @return {Resource} + */ + + /**jsdoc + * Prefetches a resource. + * @function AnimationCache.prefetch + * @param {string} url - URL of the resource to prefetch. + * @return {Resource} + */ + + /**jsdoc - * Returns animation resource for particular animation + * Returns animation resource for particular animation. * @function AnimationCache.getAnimation - * @param url {string} url to load + * @param {string} url - URL to load. * @returns {Resource} animation */ - Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); } Q_INVOKABLE AnimationPointer getAnimation(const QUrl& url); diff --git a/libraries/audio-client/src/AudioIOStats.h b/libraries/audio-client/src/AudioIOStats.h index dd97f1fe9e..89db4942ec 100644 --- a/libraries/audio-client/src/AudioIOStats.h +++ b/libraries/audio-client/src/AudioIOStats.h @@ -40,65 +40,135 @@ class AudioStreamStatsInterface : public QObject { Q_OBJECT /**jsdoc - * Audio stats from the Audio Mixer - * @namespace AudioStats.mixerStream - * @param {number} lossRate - * @param {number} lossCount - * @param {number} lossRateWindow - * @param {number} lossCountWindow - * @param {number} framesDesired - * @param {number} framesAvailable - * @param {number} framesAvailableAvg - * @param {number} unplayedMsMax - * @param {number} starveCount - * @param {number} lastStarveDurationCount - * @param {number} dropCount - * @param {number} overflowCount - * @param {number} timegapMsMax - * @param {number} timegapMsAvg - * @param {number} timegapMsMaxWindow - * @param {number} timegapMsAvgWindow + * @class AudioStats.AudioStreamStats + * @property {number} lossRate Read-only. + * @property {number} lossCount Read-only. + * @property {number} lossRateWindow Read-only. + * @property {number} lossCountWindow Read-only. + * @property {number} framesDesired Read-only. + * @property {number} framesAvailable Read-only. + * @property {number} framesAvailableAvg Read-only. + * @property {number} unplayedMsMax Read-only. + * @property {number} starveCount Read-only. + * @property {number} lastStarveDurationCount Read-only. + * @property {number} dropCount Read-only. + * @property {number} overflowCount Read-only. + * @property {number} timegapMsMax Read-only. + * @property {number} timegapMsAvg Read-only. + * @property {number} timegapMsMaxWindow Read-only. + * @property {number} timegapMsAvgWindow Read-only. */ /**jsdoc - * Audio stats from the Client Mixer - * @namespace AudioStats.clientMixer + * @function AudioStats.AudioStreamStats.lossRateChanged * @param {number} lossRate - * @param {number} lossCount - * @param {number} lossRateWindow - * @param {number} lossCountWindow - * @param {number} framesDesired - * @param {number} framesAvailable - * @param {number} framesAvailableAvg - * @param {number} unplayedMsMax - * @param {number} starveCount - * @param {number} lastStarveDurationCount - * @param {number} dropCount - * @param {number} overflowCount - * @param {number} timegapMsMax - * @param {number} timegapMsAvg - * @param {number} timegapMsMaxWindow - * @param {number} timegapMsAvgWindow + * @returns {Signal} */ - AUDIO_PROPERTY(float, lossRate) + + /**jsdoc + * @function AudioStats.AudioStreamStats.lossCountChanged + * @param {number} lossCount + * @returns {Signal} + */ AUDIO_PROPERTY(float, lossCount) + + /**jsdoc + * @function AudioStats.AudioStreamStats.lossRateWindowChanged + * @param {number} lossRateWindow + * @returns {Signal} + */ AUDIO_PROPERTY(float, lossRateWindow) + + /**jsdoc + * @function AudioStats.AudioStreamStats.lossCountWindowChanged + * @param {number} lossCountWindow + * @returns {Signal} + */ AUDIO_PROPERTY(float, lossCountWindow) + /**jsdoc + * @function AudioStats.AudioStreamStats.framesDesiredChanged + * @param {number} framesDesired + * @returns {Signal} + */ AUDIO_PROPERTY(int, framesDesired) + + /**jsdoc + * @function AudioStats.AudioStreamStats.framesAvailableChanged + * @param {number} framesAvailable + * @returns {Signal} + */ AUDIO_PROPERTY(int, framesAvailable) + + /**jsdoc + * @function AudioStats.AudioStreamStats.framesAvailableAvgChanged + * @param {number} framesAvailableAvg + * @returns {Signal} + */ AUDIO_PROPERTY(int, framesAvailableAvg) + + /**jsdoc + * @function AudioStats.AudioStreamStats.unplayedMsMaxChanged + * @param {number} unplayedMsMax + * @returns {Signal} + */ AUDIO_PROPERTY(float, unplayedMsMax) + /**jsdoc + * @function AudioStats.AudioStreamStats.starveCountChanged + * @param {number} starveCount + * @returns {Signal} + */ AUDIO_PROPERTY(int, starveCount) + + /**jsdoc + * @function AudioStats.AudioStreamStats.lastStarveDurationCountChanged + * @param {number} lastStarveDurationCount + * @returns {Signal} + */ AUDIO_PROPERTY(int, lastStarveDurationCount) + + /**jsdoc + * @function AudioStats.AudioStreamStats.dropCountChanged + * @param {number} dropCount + * @returns {Signal} + */ AUDIO_PROPERTY(int, dropCount) + + /**jsdoc + * @function AudioStats.AudioStreamStats.overflowCountChanged + * @param {number} overflowCount + * @returns {Signal} + */ AUDIO_PROPERTY(int, overflowCount) + /**jsdoc + * @function AudioStats.AudioStreamStats.timegapMsMaxChanged + * @param {number} timegapMsMax + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, timegapMsMax) + + /**jsdoc + * @function AudioStats.AudioStreamStats.timegapMsAvgChanged + * @param {number} timegapMsAvg + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, timegapMsAvg) + + /**jsdoc + * @function AudioStats.AudioStreamStats.timegapMsMaxWindowChanged + * @param {number} timegapMsMaxWindow + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, timegapMsMaxWindow) + + /**jsdoc + * @function AudioStats.AudioStreamStats.timegapMsAvgWindowChanged + * @param {number} timegapMsAvgWindow + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, timegapMsAvgWindow) public: @@ -113,31 +183,82 @@ class AudioStatsInterface : public QObject { Q_OBJECT /**jsdoc - * Audio stats from the client + * Audio stats from the client. * @namespace AudioStats - * @param {number} pingMs - * @param {number} inputReadMsMax - * @param {number} inputUnplayedMsMax - * @param {number} outputUnplayedMsMax - * @param {number} sentTimegapMsMax - * @param {number} sentTimegapMsAvg - * @param {number} sentTimegapMsMaxWindow - * @param {number} sentTimegapMsAvgWindow + * @property {number} pingMs Read-only. + * @property {number} inputReadMsMax Read-only. + * @property {number} inputUnplayedMsMax Read-only. + * @property {number} outputUnplayedMsMax Read-only. + * @property {number} sentTimegapMsMax Read-only. + * @property {number} sentTimegapMsAvg Read-only. + * @property {number} sentTimegapMsMaxWindow Read-only. + * @property {number} sentTimegapMsAvgWindow Read-only. + * @property {AudioStats.AudioStreamStats} clientStream Read-only. + * @property {AudioStats.AudioStreamStats} mixerStream Read-only. */ + /**jsdoc + * @function AudioStats.pingMsChanged + * @param {number} pingMs + * @returns {Signal} + */ AUDIO_PROPERTY(float, pingMs); + + /**jsdoc + * @function AudioStats.inputReadMsMaxChanged + * @param {number} inputReadMsMax + * @returns {Signal} + */ AUDIO_PROPERTY(float, inputReadMsMax); + + /**jsdoc + * @function AudioStats.inputUnplayedMsMaxChanged + * @param {number} inputUnplayedMsMax + * @returns {Signal} + */ AUDIO_PROPERTY(float, inputUnplayedMsMax); + + /**jsdoc + * @function AudioStats.outputUnplayedMsMaxChanged + * @param {number} outputUnplayedMsMax + * @returns {Signal} + */ AUDIO_PROPERTY(float, outputUnplayedMsMax); + + /**jsdoc + * @function AudioStats.sentTimegapMsMaxChanged + * @param {number} sentTimegapMsMax + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, sentTimegapMsMax); + + /**jsdoc + * @function AudioStats.sentTimegapMsAvgChanged + * @param {number} sentTimegapMsAvg + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, sentTimegapMsAvg); + + /**jsdoc + * @function AudioStats.sentTimegapMsMaxWindowChanged + * @param {number} sentTimegapMsMaxWindow + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, sentTimegapMsMaxWindow); + + /**jsdoc + * @function AudioStats.sentTimegapMsAvgWindowChanged + * @param {number} sentTimegapMsAvgWindow + * @returns {Signal} + */ AUDIO_PROPERTY(quint64, sentTimegapMsAvgWindow); Q_PROPERTY(AudioStreamStatsInterface* mixerStream READ getMixerStream NOTIFY mixerStreamChanged); Q_PROPERTY(AudioStreamStatsInterface* clientStream READ getClientStream NOTIFY clientStreamChanged); + + // FIXME: The injectorStreams property isn't available in JavaScript but the notification signal is. Q_PROPERTY(QObject* injectorStreams READ getInjectorStreams NOTIFY injectorStreamsChanged); public: @@ -159,21 +280,18 @@ signals: * @function AudioStats.mixerStreamChanged * @returns {Signal} */ - void mixerStreamChanged(); /**jsdoc * @function AudioStats.clientStreamChanged * @returns {Signal} */ - void clientStreamChanged(); /**jsdoc * @function AudioStats.injectorStreamsChanged * @returns {Signal} */ - void injectorStreamsChanged(); private: diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index 6f36605025..a43833610a 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -10,6 +10,7 @@ // Inline functions to implement audio dynamics processing // +#include #include #include diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h index bdb9e106d0..d8c52635e0 100644 --- a/libraries/audio/src/SoundCache.h +++ b/libraries/audio/src/SoundCache.h @@ -16,84 +16,32 @@ #include "Sound.h" -/**jsdoc - * API to manage Sound Cache resources - * @namespace SoundCache - */ - - /// Scriptable interface for sound loading. class SoundCache : public ResourceCache, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: - // Copied over from ResourceCache (see ResourceCache.h for reason) + + // Properties are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc + * API to manage sound cache resources. * @namespace SoundCache - * @property numTotal {number} total number of total resources - * @property numCached {number} total number of cached resource - * @property sizeTotal {number} size in bytes of all resources - * @property sizeCached {number} size in bytes of all cached resources + * + * @property {number} numTotal - Total number of total resources. Read-only. + * @property {number} numCached - Total number of cached resource. Read-only. + * @property {number} sizeTotal - Size in bytes of all resources. Read-only. + * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. */ - /**jsdoc - * Returns the total number of resources - * @function SoundCache.getNumTotalResources - * @returns {number} - */ + + // Functions are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc - * Returns the total size in bytes of all resources - * @function SoundCache.getSizeTotalResources - * @returns {number} - */ - - /**jsdoc - * Returns the total number of cached resources - * @function SoundCache.getNumCachedResources - * @returns {number} - */ - - /**jsdoc - * Returns the total size in bytes of cached resources - * @function SoundCache.getSizeCachedResources - * @returns {number} - */ - - /**jsdoc - * Returns list of all resource urls + * Get the list of all resource URLs. * @function SoundCache.getResourceList - * @returns {string[]} - */ - - /**jsdoc - * Returns animation resource for particular animation - * @function SoundCache.getAnimation - * @param url {string} url to load - * @returns {Resource} animation - */ - - /**jsdoc - * Asynchronously loads a resource from the spedified URL and returns it. - * @param url {string} url of resource to load - * @param fallback {string} fallback URL if load of the desired url fails - * @function SoundCache.getResource - * @returns {Resource} - */ - - /**jsdoc - * Prefetches a resource. - * @param url {string} url of resource to load - * @function SoundCache.prefetch - * @returns {Resource} - */ - - /**jsdoc - * @param {number} deltaSize - * @function SoundCache.updateTotalSize - * @returns {Resource} + * @return {string[]} */ /**jsdoc @@ -101,12 +49,40 @@ public: * @returns {Signal} */ + /**jsdoc + * @function SoundCache.updateTotalSize + * @param {number} deltaSize + */ + + /**jsdoc + * @function SoundCache.prefetch + * @param {string} url + * @param {object} extra + * @returns {object} + */ + + /**jsdoc + * Asynchronously loads a resource from the specified URL and returns it. + * @function SoundCache.getResource + * @param {string} url - URL of the resource to load. + * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. + * @param {} [extra=null] + * @return {Resource} + */ + + /**jsdoc + * Prefetches a resource. + * @function SoundCache.prefetch + * @param {string} url - URL of the resource to prefetch. + * @return {Resource} + */ + + /**jsdoc * @function SoundCache.getSound * @param {string} url - * @returns {} + * @returns {object} */ - Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url); protected: virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, diff --git a/libraries/auto-updater/src/AutoUpdater.cpp b/libraries/auto-updater/src/AutoUpdater.cpp index 43563b1d71..e58ac067a6 100644 --- a/libraries/auto-updater/src/AutoUpdater.cpp +++ b/libraries/auto-updater/src/AutoUpdater.cpp @@ -13,6 +13,7 @@ #include #include +#include AutoUpdater::AutoUpdater() { #if defined Q_OS_WIN32 @@ -43,63 +44,114 @@ void AutoUpdater::parseLatestVersionData() { QNetworkReply* sender = qobject_cast(QObject::sender()); QXmlStreamReader xml(sender); + + struct InstallerURLs { + QString full; + QString clientOnly; + }; - int version; + int version { 0 }; QString downloadUrl; QString releaseTime; QString releaseNotes; QString commitSha; QString pullRequestNumber; - while (!xml.atEnd() && !xml.hasError()) { - if (xml.name().toString() == "project" && - xml.attributes().hasAttribute("name") && - xml.attributes().value("name").toString() == "interface") { - xml.readNext(); - - while (!xml.atEnd() && !xml.hasError() && xml.name().toString() != "project") { - if (xml.name().toString() == "platform" && + while (xml.readNextStartElement()) { + if (xml.name() == "projects") { + while (xml.readNextStartElement()) { + if (xml.name().toString() == "project" && xml.attributes().hasAttribute("name") && - xml.attributes().value("name").toString() == _operatingSystem) { - xml.readNext(); - while (!xml.atEnd() && !xml.hasError() && - xml.name().toString() != "platform") { - - if (xml.name().toString() == "build" && xml.tokenType() != QXmlStreamReader::EndElement) { - xml.readNext(); - version = xml.readElementText().toInt(); - xml.readNext(); - downloadUrl = xml.readElementText(); - xml.readNext(); - releaseTime = xml.readElementText(); - xml.readNext(); - if (xml.name().toString() == "notes" && xml.tokenType() != QXmlStreamReader::EndElement) { - xml.readNext(); - while (!xml.atEnd() && !xml.hasError() && xml.name().toString() != "notes") { - if (xml.name().toString() == "note" && xml.tokenType() != QXmlStreamReader::EndElement) { - releaseNotes = releaseNotes + "\n" + xml.readElementText(); + xml.attributes().value("name").toString() == "interface") { + + while (xml.readNextStartElement()) { + + if (xml.name().toString() == "platform" && + xml.attributes().hasAttribute("name") && + xml.attributes().value("name").toString() == _operatingSystem) { + + while (xml.readNextStartElement()) { + if (xml.name() == "build") { + QHash campaignInstallers; + + while (xml.readNextStartElement()) { + if (xml.name() == "version") { + version = xml.readElementText().toInt(); + } else if (xml.name() == "url") { + downloadUrl = xml.readElementText(); + } else if (xml.name() == "installers") { + while (xml.readNextStartElement()) { + QString campaign = xml.name().toString(); + QString full; + QString clientOnly; + while (xml.readNextStartElement()) { + if (xml.name() == "full") { + full = xml.readElementText(); + } else if (xml.name() == "client_only") { + clientOnly = xml.readElementText(); + } else { + xml.skipCurrentElement(); + } + } + campaignInstallers[campaign] = { full, clientOnly }; + } + } else if (xml.name() == "timestamp") { + releaseTime = xml.readElementText(); + } else if (xml.name() == "notes") { + while (xml.readNextStartElement()) { + if (xml.name() == "note") { + releaseNotes = releaseNotes + "\n" + xml.readElementText(); + } else { + xml.skipCurrentElement(); + } + } + } else if (xml.name() == "sha") { + commitSha = xml.readElementText(); + } else if (xml.name() == "pull_request") { + pullRequestNumber = xml.readElementText(); + } else { + xml.skipCurrentElement(); + } } - xml.readNext(); + + static const QString DEFAULT_INSTALLER_CAMPAIGN_NAME = "standard"; + for (auto& campaign : { _installerCampaign, DEFAULT_INSTALLER_CAMPAIGN_NAME }) { + auto it = campaignInstallers.find(campaign); + if (it != campaignInstallers.end()) { + auto& urls = *it; + if (_installerType == InstallerType::CLIENT_ONLY) { + if (!urls.clientOnly.isEmpty()) { + downloadUrl = urls.clientOnly; + break; + } + } else { + if (!urls.full.isEmpty()) { + downloadUrl = urls.full; + break; + } + } + } + } + + appendBuildData(version, downloadUrl, releaseTime, releaseNotes, pullRequestNumber); + releaseNotes = ""; + } else { + xml.skipCurrentElement(); } } - xml.readNext(); - commitSha = xml.readElementText(); - xml.readNext(); - pullRequestNumber = xml.readElementText(); - appendBuildData(version, downloadUrl, releaseTime, releaseNotes, pullRequestNumber); - releaseNotes = ""; + } else { + xml.skipCurrentElement(); } - - xml.readNext(); } + } else { + xml.skipCurrentElement(); } - xml.readNext(); } - } else { - xml.readNext(); + xml.skipCurrentElement(); } } + sender->deleteLater(); emit latestVersionDataParsed(); } diff --git a/libraries/auto-updater/src/AutoUpdater.h b/libraries/auto-updater/src/AutoUpdater.h index 1e62ce0283..f56d7993e9 100644 --- a/libraries/auto-updater/src/AutoUpdater.h +++ b/libraries/auto-updater/src/AutoUpdater.h @@ -36,10 +36,17 @@ class AutoUpdater : public QObject, public Dependency { public: AutoUpdater(); + + enum class InstallerType { + CLIENT_ONLY = 0, + FULL + }; void checkForUpdate(); const QMap>& getBuildData() { return _builds; } void performAutoUpdate(int version); + void setInstallerType(InstallerType type) { _installerType = type; } + void setInstallerCampaign(QString campaign) { _installerCampaign = campaign; } signals: void latestVersionDataParsed(); @@ -49,6 +56,8 @@ signals: private: QMap> _builds; QString _operatingSystem; + InstallerType _installerType { InstallerType::FULL }; + QString _installerCampaign { "" }; void getLatestVersionData(); void downloadUpdateVersion(int version); diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 77e0b1e5c7..dc3f40c5d3 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -30,15 +30,6 @@ #include "AvatarData.h" -/**jsdoc - * The AvatarHashMap API deals with functionality related to Avatar information and connectivity - * @namespace AvatarHashMap - */ - -// JSDoc 3.5.5 doesn't augment @property definitions. -// These functions are being copied into Avatar classes which inherit the AvatarHashMap - - class AvatarHashMap : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -51,26 +42,20 @@ public: // Currently, your own avatar will be included as the null avatar id. /**jsdoc - * @function AvatarHashMap.getAvatarIdentifiers + * @function AvatarManager.getAvatarIdentifiers + * @returns {Uuid[]} */ - Q_INVOKABLE QVector getAvatarIdentifiers(); /**jsdoc - * @function AvatarHashMap.getAvatarsInRange + * @function AvatarManager.getAvatarsInRange * @param {Vec3} position - * @param {float} rangeMeters - * @returns {string[]} + * @param {number} range + * @returns {Uuid[]} */ - Q_INVOKABLE QVector getAvatarsInRange(const glm::vec3& position, float rangeMeters) const; - /**jsdoc - * @function AvatarHashMap.getAvatar - * @param {string} avatarID - * @returns {ScriptAvatarData} - */ - + // No JSDod because it's documwented in AvatarManager. // Null/Default-constructed QUuids will return MyAvatar Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } @@ -80,73 +65,65 @@ public: signals: /**jsdoc - * @function AvatarHashMap.avatarAddedEvent - * @param {string} sessionUUID + * @function AvatarManager.avatarAddedEvent + * @param {Uuid} sessionUUID * @returns {Signal} */ - void avatarAddedEvent(const QUuid& sessionUUID); /**jsdoc - * @function AvatarHashMap.avatarRemovedEvent - * @param {string} sessionUUID + * @function AvatarManager.avatarRemovedEvent + * @param {Uuid} sessionUUID * @returns {Signal} */ - void avatarRemovedEvent(const QUuid& sessionUUID); /**jsdoc - * @function AvatarHashMap.avatarSessionChangedEvent - * @param {string} sessionUUID - * @param {string} oldUUID + * @function AvatarManager.avatarSessionChangedEvent + * @param {Uuid} sessionUUID + * @param {Uuid} oldSessionUUID * @returns {Signal} */ - void avatarSessionChangedEvent(const QUuid& sessionUUID,const QUuid& oldUUID); public slots: /**jsdoc - * @function AvatarHashMap.isAvatarInRange + * @function AvatarManager.isAvatarInRange * @param {string} position * @param {string} range * @returns {boolean} */ - bool isAvatarInRange(const glm::vec3 & position, const float range); protected slots: /**jsdoc - * @function AvatarHashMap.sessionUUIDChanged - * @param {string} sessionUUID - * @param {string} oldUUID + * @function AvatarManager.sessionUUIDChanged + * @param {Uuid} sessionUUID + * @param {Uuid} oldSessionUUID */ - void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID); /**jsdoc - * @function AvatarHashMap.processAvatarDataPacket + * @function AvatarManager.processAvatarDataPacket * @param {} message * @param {} sendingNode */ - void processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode); /**jsdoc - * @function AvatarHashMap.processAvatarIdentityPacket + * @function AvatarManager.processAvatarIdentityPacket * @param {} message * @param {} sendingNode */ - void processAvatarIdentityPacket(QSharedPointer message, SharedNodePointer sendingNode); /**jsdoc - * @function AvatarHashMap.processKillAvatar + * @function AvatarManager.processKillAvatar * @param {} message * @param {} sendingNode */ - void processKillAvatar(QSharedPointer message, SharedNodePointer sendingNode); protected: diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 86a43c0c13..3c3858e2ba 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -39,7 +39,9 @@ class UserInputMapper; * methods. *
  • Use {@link Controller.parseMapping} or {@link Controller.loadMapping} to load a {@link Controller.MappingJSON}.
  • * - *

    Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take effect. + * + *

    Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take + * effect.

    * *

    Mappings and their routes are applied according to the following rules:

    *
      @@ -49,7 +51,7 @@ class UserInputMapper; * output that already has a route the new route is ignored. *
    • New mappings override previous mappings: each output is processed using the route in the most recently enabled * mapping that contains that output.
    • - *

      + *
    * * @class MappingObject */ diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 0336638068..d33f3e3383 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -29,7 +29,8 @@ class ScriptingInterface; *

    A route in a {@link MappingObject} used by the {@link Controller} API.

    * *

    Create a route using {@link MappingObject} methods and apply this object's methods to process it, terminating with - * {@link RouteObject#to} to apply it to a Standard control, action, or script function.

    + * {@link RouteObject#to} to apply it to a Standard control, action, or script function. Note: Loops are not + * permitted.

    * *

    Some methods apply to routes with number data, some apply routes with {@link Pose} data, and some apply to both route * types.

    diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c9fa50932a..5e76d18515 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -390,17 +390,18 @@ public slots: /**jsdoc * Find all entities of a particular name that intersect a sphere defined by a center point and radius. * @function Entities.findEntitiesByName - * @param {Entities.EntityType} entityName - The name of the entity to search for. + * @param {string} entityName - The name of the entity to search for. * @param {Vec3} center - The point about which to search. * @param {number} radius - The radius within which to search. - * @param {bool} caseSensitiveSearch - Choose whether to to return case sensitive results back. - * @returns {Uuid[]} An array of entity IDs of the specified type that intersect the search sphere. The array is empty if - * no entities could be found. - * @example Get back a list of entities + * @param {boolean} [caseSensitive=false] - If true then the search is case-sensitive. + * @returns {Uuid[]} An array of entity IDs that have the specified name and intersect the search sphere. The array is empty + * if no entities could be found. + * @example Report the number of entities with the name, "Light-Target". * var entityIDs = Entities.findEntitiesByName("Light-Target", MyAvatar.position, 10, false); - * print("Number of Entities with the name Light-Target " + entityIDs.length); + * print("Number of entities with the name "Light-Target": " + entityIDs.length); */ - Q_INVOKABLE QVector findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch = false ) const; + Q_INVOKABLE QVector findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, + bool caseSensitiveSearch = false ) const; /**jsdoc * Find the first entity intersected by a {@link PickRay}. Light and Zone entities are not diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index cf879f9aee..8fd240aca2 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1180,16 +1180,6 @@ void EntityTree::startChallengeOwnershipTimer(const EntityItemID& entityItemID) _challengeOwnershipTimeoutTimer->start(5000); } -void EntityTree::startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { - qCDebug(entities) << "'transfer_status' is 'pending', checking again in 90 seconds..." << entityItemID; - QTimer* transferStatusRetryTimer = new QTimer(this); - connect(transferStatusRetryTimer, &QTimer::timeout, this, [=]() { - validatePop(certID, entityItemID, senderNode, true); - }); - transferStatusRetryTimer->setSingleShot(true); - transferStatusRetryTimer->start(90000); -} - QByteArray EntityTree::computeNonce(const QString& certID, const QString ownerKey) { QUuid nonce = QUuid::createUuid(); //random, 5-hex value, separated by "-" QByteArray nonceBytes = nonce.toByteArray(); @@ -1329,7 +1319,7 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, c nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(QUuid::fromRfc4122(nodeToChallenge)))); } -void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation) { +void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { // Start owner verification. auto nodeList = DependencyManager::get(); // First, asynchronously hit "proof_of_purchase_status?transaction_type=transfer" endpoint. @@ -1360,30 +1350,13 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt withWriteLock([&] { deleteEntity(entityItemID, true); }); - } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { - if (isRetryingValidation) { - qCDebug(entities) << "'transfer_status' is 'pending' after retry, deleting entity" << entityItemID; - withWriteLock([&] { - deleteEntity(entityItemID, true); - }); - } else { - if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "startPendingTransferStatusTimer", - Q_ARG(const QString&, certID), - Q_ARG(const EntityItemID&, entityItemID), - Q_ARG(const SharedNodePointer&, senderNode)); - return; - } else { - startPendingTransferStatusTimer(certID, entityItemID, senderNode); - } - } } else { // Second, challenge ownership of the PoP cert + // (ignore pending status; a failure will be cleaned up during DDV) sendChallengeOwnershipPacket(certID, jsonObject["transfer_recipient_key"].toString(), entityItemID, senderNode); - } } else { qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << entityItemID @@ -1627,7 +1600,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c // Delete the entity we just added if it doesn't pass static certificate verification deleteEntity(entityItemID, true); } else { - validatePop(properties.getCertificateID(), entityItemID, senderNode, false); + validatePop(properties.getCertificateID(), entityItemID, senderNode); } } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 750d44da3d..10919c6eac 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -399,12 +399,11 @@ protected: QHash _entitiesToAdd; Q_INVOKABLE void startChallengeOwnershipTimer(const EntityItemID& entityItemID); - Q_INVOKABLE void startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); private: void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); - void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); + void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); std::shared_ptr _myAvatar{ nullptr }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1e59646795..86422ef70c 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -996,14 +996,12 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QByteArray filename = subobject.properties.at(0).toByteArray(); QByteArray filepath = filename.replace('\\', '/'); filename = fileOnUrl(filepath, url); - qDebug() << "Filename" << filepath << filename; _textureFilepaths.insert(getID(object.properties), filepath); _textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) { // trim the name from the timestamp QString name = QString(subobject.properties.at(0).toByteArray()); name = name.left(name.indexOf('[')); - qDebug() << "Filename" << name; _textureNames.insert(getID(object.properties), name); } else if (subobject.name == "Texture_Alpha_Source" && subobject.properties.length() >= TEXTURE_ALPHA_SOURCE_MIN_SIZE) { tex.assign(tex.alphaSource, subobject.properties.at(0).value()); diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 369d972a7d..9532f39ce0 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -21,11 +21,6 @@ #include "FBXReader.h" #include "TextureCache.h" -/**jsdoc -* API to manage Model Cache resources -* @namespace ModelCache -*/ - // Alias instead of derive to avoid copying class NetworkTexture; @@ -141,72 +136,62 @@ class ModelCache : public ResourceCache, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY - public: - /**jsdoc - * @namespace ModelCache - * @property numTotal {number} total number of total resources - * @property numCached {number} total number of cached resource - * @property sizeTotal {number} size in bytes of all resources - * @property sizeCached {number} size in bytes of all cached resources - */ + // Properties are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc - * Returns the total number of resources - * @function ModelCache.getNumTotalResources - * @returns {number} - */ + * API to manage model cache resources. + * @namespace ModelCache + * + * @property {number} numTotal - Total number of total resources. Read-only. + * @property {number} numCached - Total number of cached resource. Read-only. + * @property {number} sizeTotal - Size in bytes of all resources. Read-only. + * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. + */ + + + // Functions are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc - * Returns the total size in bytes of all resources - * @function ModelCache.getSizeTotalResources - * @returns {number} - */ + * Get the list of all resource URLs. + * @function ModelCache.getResourceList + * @return {string[]} + */ /**jsdoc - * Returns the total number of cached resources - * @function ModelCache.getNumCachedResources - * @returns {number} - */ + * @function ModelCache.dirty + * @returns {Signal} + */ /**jsdoc - * Returns the total size in bytes of cached resources - * @function ModelCache.getSizeCachedResources - * @returns {number} - */ + * @function ModelCache.updateTotalSize + * @param {number} deltaSize + */ /**jsdoc - * Returns list of all resource urls - * @function ModelCache.getResourceList - * @returns {string[]} - */ + * @function ModelCache.prefetch + * @param {string} url + * @param {object} extra + * @returns {object} + */ /**jsdoc - * Asynchronously loads a resource from the spedified URL and returns it. - * @param url {string} url of resource to load - * @param fallback {string} fallback URL if load of the desired url fails - * @function ModelCache.getResource - * @returns {Resource} - */ + * Asynchronously loads a resource from the specified URL and returns it. + * @function ModelCache.getResource + * @param {string} url - URL of the resource to load. + * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. + * @param {} [extra=null] + * @return {Resource} + */ /**jsdoc - * Prefetches a resource. - * @param url {string} url of resource to load - * @function ModelCache.prefetch - * @returns {Resource} - */ + * Prefetches a resource. + * @function ModelCache.prefetch + * @param {string} url - URL of the resource to prefetch. + * @return {Resource} + */ - /**jsdoc - * @param {number} deltaSize - * @function ModelCache.updateTotalSize - * @returns {Resource} - */ - - /**jsdoc - * @function ModelCache.dirty - * @returns {Signal} - */ GeometryResource::Pointer getGeometryResource(const QUrl& url, const QVariantHash& mapping = QVariantHash(), diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 174a25fee2..3f46dc3074 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -137,10 +137,6 @@ using NetworkTexturePointer = QSharedPointer; Q_DECLARE_METATYPE(QWeakPointer) -/**jsdoc - * API to manage Texture Cache resources - * @namespace TextureCache - */ /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache, public Dependency { @@ -148,78 +144,61 @@ class TextureCache : public ResourceCache, public Dependency { SINGLETON_DEPENDENCY public: - // Copied over from ResourceCache (see ResourceCache.h for reason) + + // Properties are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc - * @namespace TextureCache - * @property numTotal {number} total number of total resources - * @property numCached {number} total number of cached resource - * @property sizeTotal {number} size in bytes of all resources - * @property sizeCached {number} size in bytes of all cached resources - */ + * API to manage texture cache resources. + * @namespace TextureCache + * + * @property {number} numTotal - Total number of total resources. Read-only. + * @property {number} numCached - Total number of cached resource. Read-only. + * @property {number} sizeTotal - Size in bytes of all resources. Read-only. + * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. + */ - /**jsdoc - * Returns the total number of resources - * @function TextureCache.getNumTotalResources - * @returns {number} - */ - /**jsdoc - * Returns the total size in bytes of all resources - * @function TextureCache.getSizeTotalResources - * @returns {number} - */ + // Functions are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc - * Returns the total number of cached resources - * @function TextureCache.getNumCachedResources - * @returns {number} - */ + /**jsdoc + * Get the list of all resource URLs. + * @function TextureCache.getResourceList + * @return {string[]} + */ - /**jsdoc - * Returns the total size in bytes of cached resources - * @function TextureCache.getSizeCachedResources - * @returns {number} - */ + /**jsdoc + * @function TextureCache.dirty + * @returns {Signal} + */ - /**jsdoc - * Returns list of all resource urls - * @function TextureCache.getResourceList - * @returns {string[]} - */ + /**jsdoc + * @function TextureCache.updateTotalSize + * @param {number} deltaSize + */ - /**jsdoc - * Returns animation resource for particular animation - * @function TextureCache.getAnimation - * @param url {string} url to load - * @returns {Resource} animation - */ + /**jsdoc + * @function TextureCache.prefetch + * @param {string} url + * @param {object} extra + * @returns {object} + */ - /**jsdoc - * Asynchronously loads a resource from the spedified URL and returns it. - * @param url {string} url of resource to load - * @param fallback {string} fallback URL if load of the desired url fails - * @function TextureCache.getResource - * @returns {Resource} - */ + /**jsdoc + * Asynchronously loads a resource from the specified URL and returns it. + * @function TextureCache.getResource + * @param {string} url - URL of the resource to load. + * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. + * @param {} [extra=null] + * @return {Resource} + */ - /**jsdoc - * Prefetches a resource. - * @param url {string} url of resource to load - * @function TextureCache.prefetch - * @returns {Resource} - */ + /**jsdoc + * Prefetches a resource. + * @function TextureCache.prefetch + * @param {string} url - URL of the resource to prefetch. + * @return {Resource} + */ - /**jsdoc - * @param {number} deltaSize - * @function TextureCache.updateTotalSize - * @returns {Resource} - */ - - /**jsdoc - * @function TextureCache.dirty - * @returns {Signal} - */ /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and @@ -265,6 +244,13 @@ signals: void spectatorCameraFramebufferReset(); protected: + + /**jsdoc + * @function TextureCache.prefect + * @param {string} url + * @param {number} type + * @param {number} [maxNumPixels=67108864] + */ // Overload ResourceCache::prefetch to allow specifying texture type for loads Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 9a96364de2..055d94c3b3 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -333,12 +333,14 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { return false; } +static const QString LOCALHOST = "localhost"; + bool isPossiblePlaceName(QString possiblePlaceName) { bool result { false }; int length = possiblePlaceName.length(); static const int MINIMUM_PLACENAME_LENGTH = 1; static const int MAXIMUM_PLACENAME_LENGTH = 64; - if (possiblePlaceName.toLower() != "localhost" && + if (possiblePlaceName.toLower() != LOCALHOST && length >= MINIMUM_PLACENAME_LENGTH && length <= MAXIMUM_PLACENAME_LENGTH) { const QRegExp PLACE_NAME_REGEX = QRegExp("^[0-9A-Za-z](([0-9A-Za-z]|-(?!-))*[^\\W_]$|$)"); result = PLACE_NAME_REGEX.indexIn(possiblePlaceName) == 0; @@ -358,7 +360,7 @@ void AddressManager::handleLookupString(const QString& lookupString, bool fromSu sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX); lookupURL = QUrl(sanitizedString); - if (lookupURL.scheme().isEmpty()) { + if (lookupURL.scheme().isEmpty() || lookupURL.scheme().toLower() == LOCALHOST) { lookupURL = QUrl("hifi://" + sanitizedString); } } else { @@ -607,7 +609,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri if (ipAddressRegex.indexIn(lookupString) != -1) { QString domainIPString = ipAddressRegex.cap(1); - quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + quint16 domainPort = 0; if (!ipAddressRegex.cap(2).isEmpty()) { domainPort = (quint16) ipAddressRegex.cap(2).toInt(); } @@ -629,7 +631,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri if (hostnameRegex.indexIn(lookupString) != -1) { QString domainHostname = hostnameRegex.cap(1); - quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + quint16 domainPort = 0; if (!hostnameRegex.cap(2).isEmpty()) { domainPort = (quint16)hostnameRegex.cap(2).toInt(); diff --git a/libraries/networking/src/BaseAssetScriptingInterface.h b/libraries/networking/src/BaseAssetScriptingInterface.h index 336f3f81db..497f627421 100644 --- a/libraries/networking/src/BaseAssetScriptingInterface.h +++ b/libraries/networking/src/BaseAssetScriptingInterface.h @@ -31,12 +31,54 @@ public: BaseAssetScriptingInterface(QObject* parent = nullptr); public slots: + + /**jsdoc + * @function Assets.isValidPath + * @param {string} input + * @returns {boolean} + */ bool isValidPath(QString input) { return AssetUtils::isValidPath(input); } + + /**jsdoc + * @function Assets.isValidFilePath + * @param {string} input + * @returns {boolean} + */ bool isValidFilePath(QString input) { return AssetUtils::isValidFilePath(input); } + + /**jsdoc + * @function Assets.getATPUrl + * @param {string} input + * @returns {string} + */ QUrl getATPUrl(QString input) { return AssetUtils::getATPUrl(input); } + + /**jsdoc + * @function Assets.extractAssetHash + * @param {string} input + * @returns {string} + */ QString extractAssetHash(QString input) { return AssetUtils::extractAssetHash(input); } + + /**jsdoc + * @function Assets.isValidHash + * @param {string} input + * @returns {boolean} + */ bool isValidHash(QString input) { return AssetUtils::isValidHash(input); } + + /**jsdoc + * @function Assets.hashData + * @param {} data + * @returns {object} + */ QByteArray hashData(const QByteArray& data) { return AssetUtils::hashData(data); } + + /**jsdoc + * @function Assets.hashDataHex + * @param {} data + * @returns {string} + */ QString hashDataHex(const QByteArray& data) { return hashData(data).toHex(); } protected: diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index cd8064c4c0..871dc26899 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -166,7 +166,12 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { } } - if (_domainURL != domainURL || _sockAddr.getPort() != domainURL.port()) { + auto domainPort = domainURL.port(); + if (domainPort == -1) { + domainPort = DEFAULT_DOMAIN_SERVER_PORT; + } + + if (_domainURL != domainURL || _sockAddr.getPort() != domainPort) { // re-set the domain info so that auth information is reloaded hardReset(); @@ -192,12 +197,10 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { emit domainURLChanged(_domainURL); - if (_sockAddr.getPort() != domainURL.port()) { - qCDebug(networking) << "Updated domain port to" << domainURL.port(); + if (_sockAddr.getPort() != domainPort) { + qCDebug(networking) << "Updated domain port to" << domainPort; + _sockAddr.setPort(domainPort); } - - // grab the port by reading the string after the colon - _sockAddr.setPort(domainURL.port()); } } diff --git a/libraries/networking/src/EntityScriptClient.cpp b/libraries/networking/src/EntityScriptClient.cpp index 75ae7369fb..1eab5bf2d7 100644 --- a/libraries/networking/src/EntityScriptClient.cpp +++ b/libraries/networking/src/EntityScriptClient.cpp @@ -192,8 +192,6 @@ void EntityScriptClient::handleNodeClientConnectionReset(SharedNodePointer node) return; } - //qCDebug(entity_script_client) << "EntityScriptClient detected client connection reset handshake with Asset Server - failing any pending requests"; - forceFailureOfPendingRequests(node); } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 92385e99b0..31500be682 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -715,10 +715,11 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t // insert the new node and release our read lock #if defined(Q_OS_ANDROID) || (defined(__clang__) && defined(Q_OS_LINUX)) _nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer)); + _localIDMap.insert(std::pair(localID, newNodePointer)); #else _nodeHash.emplace(newNode->getUUID(), newNodePointer); -#endif _localIDMap.emplace(localID, newNodePointer); +#endif readLocker.unlock(); qCDebug(networking) << "Added" << *newNode; diff --git a/libraries/networking/src/NetworkLogging.h b/libraries/networking/src/NetworkLogging.h index 518c600efe..30116ff405 100644 --- a/libraries/networking/src/NetworkLogging.h +++ b/libraries/networking/src/NetworkLogging.h @@ -17,7 +17,6 @@ Q_DECLARE_LOGGING_CATEGORY(resourceLog) Q_DECLARE_LOGGING_CATEGORY(networking) Q_DECLARE_LOGGING_CATEGORY(asset_client) -Q_DECLARE_LOGGING_CATEGORY(entity_script_client) Q_DECLARE_LOGGING_CATEGORY(messages_client) #endif // hifi_NetworkLogging_h diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index ddea7c51cf..609483bc56 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -89,14 +89,13 @@ class ScriptableResource : public QObject { /**jsdoc * @constructor Resource - * @property url {string} url of this resource - * @property state {Resource.State} current loading state + * @property {string} url - URL of this resource. + * @property {Resource.State} state - Current loading state. */ Q_OBJECT Q_PROPERTY(QUrl url READ getURL) Q_PROPERTY(int state READ getState NOTIFY stateChanged) - public: @@ -104,11 +103,11 @@ public: /**jsdoc * @name Resource.State * @static - * @property QUEUED {int} The resource is queued up, waiting to be loaded. - * @property LOADING {int} The resource is downloading - * @property LOADED {int} The resource has finished downloaded by is not complete - * @property FINISHED {int} The resource has completly finished loading and is ready. - * @property FAILED {int} Downloading the resource has failed. + * @property {number} QUEUED - The resource is queued up, waiting to be loaded. + * @property {number} LOADING - The resource is downloading. + * @property {number} LOADED - The resource has finished downloaded by is not complete. + * @property {number} FINISHED - The resource has completely finished loading and is ready. + * @property {number} FAILED - Downloading the resource has failed. */ enum State { @@ -124,7 +123,7 @@ public: virtual ~ScriptableResource() = default; /**jsdoc - * Release this resource + * Release this resource. * @function Resource#release */ Q_INVOKABLE void release(); @@ -139,18 +138,18 @@ public: signals: /**jsdoc - * Signaled when download progress for this resource has changed + * Triggered when download progress for this resource has changed. * @function Resource#progressChanged - * @param bytesReceived {int} bytes downloaded so far - * @param bytesTotal {int} total number of bytes in the resource + * @param {number} bytesReceived - Byytes downloaded so far. + * @param {number} bytesTotal - Total number of bytes in the resource. * @returns {Signal} */ void progressChanged(uint64_t bytesReceived, uint64_t bytesTotal); /**jsdoc - * Signaled when resource loading state has changed + * Triggered when resource loading state has changed. * @function Resource#stateChanged - * @param bytesReceived {Resource.State} new state + * @param {Resource.State} state - New state. * @returns {Signal} */ void stateChanged(int state); @@ -185,14 +184,15 @@ Q_DECLARE_METATYPE(ScriptableResource*); /// Base class for resource caches. class ResourceCache : public QObject { Q_OBJECT - // JSDoc 3.5.5 doesn't augment @property definitions. - // These functions are being copied into the different exposed cache classes + + // JSDoc 3.5.5 doesn't augment namespaces with @property or @function definitions. + // The ResourceCache properties and functions are copied to the different exposed cache classes. + /**jsdoc - * @namespace ResourceCache - * @property numTotal {number} total number of total resources - * @property numCached {number} total number of cached resource - * @property sizeTotal {number} size in bytes of all resources - * @property sizeCached {number} size in bytes of all cached resources + * @property {number} numTotal - Total number of total resources. Read-only. + * @property {number} numCached - Total number of cached resource. Read-only. + * @property {number} sizeTotal - Size in bytes of all resources. Read-only. + * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. */ Q_PROPERTY(size_t numTotal READ getNumTotalResources NOTIFY dirty) Q_PROPERTY(size_t numCached READ getNumCachedResources NOTIFY dirty) @@ -200,36 +200,14 @@ class ResourceCache : public QObject { Q_PROPERTY(size_t sizeCached READ getSizeCachedResources NOTIFY dirty) public: - /**jsdoc - * Returns the total number of resources - * @function ResourceCache.getNumTotalResources - * @return {number} - */ + size_t getNumTotalResources() const { return _numTotalResources; } - - /**jsdoc - * Returns the total size in bytes of all resources - * @function ResourceCache.getSizeTotalResources - * @return {number} - */ size_t getSizeTotalResources() const { return _totalResourcesSize; } - - /**jsdoc - * Returns the total number of cached resources - * @function ResourceCache.getNumCachedResources - * @return {number} - */ size_t getNumCachedResources() const { return _numUnusedResources; } - - /**jsdoc - * Returns the total size in bytes of cached resources - * @function ResourceCache.getSizeCachedResources - * @return {number} - */ size_t getSizeCachedResources() const { return _unusedResourcesSize; } /**jsdoc - * Returns list of all resource urls + * Get the list of all resource URLs. * @function ResourceCache.getResourceList * @return {string[]} */ @@ -257,28 +235,45 @@ public: void clearUnusedResources(); signals: + + /**jsdoc + * @function ResourceCache.dirty + * @returns {Signal} + */ void dirty(); protected slots: + + /**jsdoc + * @function ResourceCache.updateTotalSize + * @param {number} deltaSize + */ void updateTotalSize(const qint64& deltaSize); + /**jsdoc + * @function ResourceCache.prefetch + * @param {string} url + * @param {object} extra + * @returns {object} + */ // Prefetches a resource to be held by the QScriptEngine. // Left as a protected member so subclasses can overload prefetch // and delegate to it (see TextureCache::prefetch(const QUrl&, int). ScriptableResource* prefetch(const QUrl& url, void* extra); + /**jsdoc + * Asynchronously loads a resource from the specified URL and returns it. + * @function ResourceCache.getResource + * @param {string} url - URL of the resource to load. + * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. + * @param {} [extra=null] + * @return {Resource} + */ /// Loads a resource from the specified URL and returns it. /// If the caller is on a different thread than the ResourceCache, /// returns an empty smart pointer and loads its asynchronously. /// \param fallback a fallback URL to load if the desired one is unavailable /// \param extra extra data to pass to the creator, if appropriate - /**jsdoc - * Asynchronously loads a resource from the spedified URL and returns it. - * @param url {string} url of resource to load - * @param fallback {string} fallback URL if load of the desired url fails - * @function ResourceCache.getResource - * @return {Resource} - */ QSharedPointer getResource(const QUrl& url, const QUrl& fallback = QUrl(), void* extra = NULL); @@ -292,8 +287,8 @@ protected: // the QScriptEngine will delete the pointer when it is garbage collected. /**jsdoc * Prefetches a resource. - * @param url {string} url of resource to load * @function ResourceCache.prefetch + * @param {string} url - URL of the resource to prefetch. * @return {Resource} */ Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); } diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 18e4593c91..8b6de7da11 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -84,7 +84,8 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy _domainServerTimer.start(); // start sending stats packet once we connect to the domain - connect(&nodeList->getDomainHandler(), SIGNAL(connectedToDomain(const QString&)), &_statsTimer, SLOT(start())); + connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, + &_statsTimer, static_cast(&QTimer::start)); // stop sending stats if we disconnect connect(&nodeList->getDomainHandler(), &DomainHandler::disconnectedFromDomain, &_statsTimer, &QTimer::stop); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 35db43e5e7..2efd32f2e8 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -795,9 +795,10 @@ QString getMarketplaceID(const QString& urlString) { } bool Octree::readFromURL(const QString& urlString) { - QString marketplaceID = getMarketplaceID(urlString); + QString trimmedUrl = urlString.trimmed(); + QString marketplaceID = getMarketplaceID(trimmedUrl); auto request = - std::unique_ptr(DependencyManager::get()->createResourceRequest(this, urlString)); + std::unique_ptr(DependencyManager::get()->createResourceRequest(this, trimmedUrl)); if (!request) { return false; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 22737afe30..c680c60c39 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -159,6 +159,8 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { // remove the objects (aka MotionStates) from physics _physicsEngine->removeSetOfObjects(_physicalObjects); + clearOwnershipData(); + // delete the MotionStates for (auto stateItr : _physicalObjects) { EntityMotionState* motionState = static_cast(&(*stateItr)); @@ -171,7 +173,6 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { _physicalObjects.clear(); // clear all other lists specific to this derived class - clearOwnershipData(); _entitiesToRemoveFromPhysics.clear(); _entitiesToAddToPhysics.clear(); _incomingChanges.clear(); diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 90424b04b2..7086b65f4c 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -16,6 +16,7 @@ #include "AbstractViewStateInterface.h" #include "RenderUtilsLogging.h" #include "DebugDraw.h" +#include "StencilMaskPass.h" #include "animdebugdraw_vert.h" #include "animdebugdraw_frag.h" @@ -70,7 +71,7 @@ public: typedef render::Payload AnimDebugDrawPayload; namespace render { - template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::opaqueShape() : ItemKey::Builder::opaqueShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); } + template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::transparentShape() : ItemKey::Builder::transparentShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); } template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return data->_bound; } template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) { data->render(args); @@ -104,6 +105,7 @@ AnimDebugDraw::AnimDebugDraw() : state->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + PrepareStencil::testMaskDrawShape(*state.get()); auto vertShader = animdebugdraw_vert::getShader(); auto fragShader = animdebugdraw_frag::getShader(); auto program = gpu::Shader::createProgram(vertShader, fragShader); diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index e620fc2d61..dd4bda2e37 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -198,7 +198,7 @@ Antialiasing::~Antialiasing() { _antialiasingTextures[1].reset(); } -const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { +const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline(const render::RenderContextPointer& renderContext) { if (!_antialiasingPipeline) { @@ -207,17 +207,6 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("taaParamsBuffer"), AntialiasingPass_ParamsSlot)); - - slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), AntialiasingPass_FrameTransformSlot)); - - slotBindings.insert(gpu::Shader::Binding(std::string("historyMap"), AntialiasingPass_HistoryMapSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), AntialiasingPass_SourceMapSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("velocityMap"), AntialiasingPass_VelocityMapSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), AntialiasingPass_DepthMapSlot)); - - - gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -225,6 +214,21 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { // Good to go add the brand new pipeline _antialiasingPipeline = gpu::Pipeline::create(program, state); + + gpu::doInBatch("SurfaceGeometryPass::CurvaturePipeline", renderContext->args->_context, [program](gpu::Batch& batch) { + batch.runLambda([program]() { + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("taaParamsBuffer"), AntialiasingPass_ParamsSlot)); + + slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), AntialiasingPass_FrameTransformSlot)); + + slotBindings.insert(gpu::Shader::Binding(std::string("historyMap"), AntialiasingPass_HistoryMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), AntialiasingPass_SourceMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("velocityMap"), AntialiasingPass_VelocityMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), AntialiasingPass_DepthMapSlot)); + gpu::Shader::makeProgram(*program, slotBindings); + }); + }); } return _antialiasingPipeline; @@ -347,7 +351,7 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const batch.setViewportTransform(args->_viewport); // TAA step - getAntialiasingPipeline(); + getAntialiasingPipeline(renderContext); batch.setResourceFramebufferSwapChainTexture(AntialiasingPass_HistoryMapSlot, _antialiasingBuffers, 0); batch.setResourceTexture(AntialiasingPass_SourceMapSlot, sourceBuffer->getRenderBuffer(0)); batch.setResourceTexture(AntialiasingPass_VelocityMapSlot, velocityBuffer->getVelocityTexture()); @@ -358,7 +362,7 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const batch.setUniformBuffer(AntialiasingPass_FrameTransformSlot, deferredFrameTransform->getFrameTransformBuffer()); batch.setFramebufferSwapChain(_antialiasingBuffers, 1); - batch.setPipeline(getAntialiasingPipeline()); + batch.setPipeline(getAntialiasingPipeline(renderContext)); batch.draw(gpu::TRIANGLE_STRIP, 4); // Blend step diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index a89666f58b..9f62fd76c1 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -174,7 +174,7 @@ public: void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); - const gpu::PipelinePointer& getAntialiasingPipeline(); + const gpu::PipelinePointer& getAntialiasingPipeline(const render::RenderContextPointer& renderContext); const gpu::PipelinePointer& getBlendPipeline(); const gpu::PipelinePointer& getDebugBlendPipeline(); diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index d3bf3ab198..51046f10b3 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -168,7 +168,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con outputs.edit4() = halfNormalTexture; auto linearDepthPipeline = getLinearDepthPipeline(renderContext); - auto downsamplePipeline = getDownsamplePipeline(); + auto downsamplePipeline = getDownsamplePipeline(renderContext); auto depthViewport = args->_viewport; auto halfViewport = depthViewport >> 1; @@ -241,19 +241,12 @@ const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline(const render } -const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline() { +const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline(const render::RenderContextPointer& renderContext) { if (!_downsamplePipeline) { auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = surfaceGeometry_downsampleDepthNormal_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DepthLinearPass_FrameTransformSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), DepthLinearPass_DepthMapSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), DepthLinearPass_NormalMapSlot)); - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); PrepareStencil::testShape(*state); @@ -261,6 +254,16 @@ const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline() { // Good to go add the brand new pipeline _downsamplePipeline = gpu::Pipeline::create(program, state); + + gpu::doInBatch("LinearDepthPass::run", renderContext->args->_context, [program](gpu::Batch& batch) { + batch.runLambda([program]() { + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", DepthLinearPass_FrameTransformSlot)); + slotBindings.insert(gpu::Shader::Binding("linearDepthMap", DepthLinearPass_DepthMapSlot)); + slotBindings.insert(gpu::Shader::Binding("normalMap", DepthLinearPass_NormalMapSlot)); + gpu::Shader::makeProgram(*program, slotBindings); + }); + }); } return _downsamplePipeline; diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h index 501cf3fa87..367f599f67 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.h +++ b/libraries/render-utils/src/SurfaceGeometryPass.h @@ -84,7 +84,7 @@ private: const gpu::PipelinePointer& getLinearDepthPipeline(const render::RenderContextPointer& renderContext); gpu::PipelinePointer _linearDepthPipeline; - const gpu::PipelinePointer& getDownsamplePipeline(); + const gpu::PipelinePointer& getDownsamplePipeline(const render::RenderContextPointer& renderContext); gpu::PipelinePointer _downsamplePipeline; gpu::RangeTimerPointer _gpuTimer; diff --git a/libraries/render-utils/src/VelocityBufferPass.cpp b/libraries/render-utils/src/VelocityBufferPass.cpp index 78471d48af..3f7da4cdcd 100644 --- a/libraries/render-utils/src/VelocityBufferPass.cpp +++ b/libraries/render-utils/src/VelocityBufferPass.cpp @@ -113,7 +113,7 @@ void VelocityBufferPass::run(const render::RenderContextPointer& renderContext, outputs.edit1() = velocityFBO; outputs.edit2() = velocityTexture; - auto cameraMotionPipeline = getCameraMotionPipeline(); + auto cameraMotionPipeline = getCameraMotionPipeline(renderContext); auto fullViewport = args->_viewport; @@ -143,18 +143,12 @@ void VelocityBufferPass::run(const render::RenderContextPointer& renderContext, } -const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline() { +const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline(const render::RenderContextPointer& renderContext) { if (!_cameraMotionPipeline) { auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = velocityBuffer_cameraMotion_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), VelocityBufferPass_FrameTransformSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), VelocityBufferPass_DepthMapSlot)); - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); // Stencil test the curvature pass for objects pixels only, not the background @@ -164,6 +158,16 @@ const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline() { // Good to go add the brand new pipeline _cameraMotionPipeline = gpu::Pipeline::create(program, state); + + gpu::doInBatch("VelocityBufferPass::CameraMotionPipeline", renderContext->args->_context, + [program](gpu::Batch& batch) { + batch.runLambda([program]() { + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), VelocityBufferPass_FrameTransformSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), VelocityBufferPass_DepthMapSlot)); + gpu::Shader::makeProgram(*program, slotBindings); + }); + }); } return _cameraMotionPipeline; diff --git a/libraries/render-utils/src/VelocityBufferPass.h b/libraries/render-utils/src/VelocityBufferPass.h index fb2b729368..50b994f6db 100644 --- a/libraries/render-utils/src/VelocityBufferPass.h +++ b/libraries/render-utils/src/VelocityBufferPass.h @@ -79,7 +79,7 @@ private: VelocityFramebufferPointer _velocityFramebuffer; - const gpu::PipelinePointer& getCameraMotionPipeline(); + const gpu::PipelinePointer& getCameraMotionPipeline(const render::RenderContextPointer& renderContext); gpu::PipelinePointer _cameraMotionPipeline; gpu::RangeTimerPointer _gpuTimer; diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index c01550e1fc..5cb1136b74 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -25,7 +25,7 @@ #include /**jsdoc - * The Assets API allows you to communicate with the Asset Browser + * The Assets API allows you to communicate with the Asset Browser. * @namespace Assets */ class AssetScriptingInterface : public BaseAssetScriptingInterface, QScriptable { @@ -41,14 +41,12 @@ public: * @param data {string} content to upload * @param callback {Assets~uploadDataCallback} called when upload is complete */ - /**jsdoc * Called when uploadData is complete * @callback Assets~uploadDataCallback * @param {string} url * @param {string} hash */ - Q_INVOKABLE void uploadData(QString data, QScriptValue callback); /**jsdoc @@ -57,13 +55,11 @@ public: * @param url {string} URL of asset to download, must be ATP scheme URL. * @param callback {Assets~downloadDataCallback} */ - /**jsdoc * Called when downloadData is complete * @callback Assets~downloadDataCallback * @param data {string} content that was downloaded */ - Q_INVOKABLE void downloadData(QString url, QScriptValue downloadComplete); /**jsdoc @@ -73,13 +69,11 @@ public: * @param hash {string} * @param callback {Assets~setMappingCallback} */ - /**jsdoc * Called when setMapping is complete * @callback Assets~setMappingCallback * @param {string} error */ - Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback); /**jsdoc @@ -88,21 +82,12 @@ public: * @param path {string} * @param callback {Assets~getMappingCallback} */ - /**jsdoc * Called when getMapping is complete. * @callback Assets~getMappingCallback * @param assetID {string} hash value if found, else an empty string * @param error {string} error description if the path could not be resolved; otherwise a null value. */ - - /**jsdoc - * Called when getMapping is complete. - * @callback Assets~getMappingCallback - * @param assetID {string} hash value if found, else an empty string - * @param error {string} error description if the path could not be resolved; otherwise a null value. - */ - Q_INVOKABLE void getMapping(QString path, QScriptValue callback); /**jsdoc @@ -111,7 +96,10 @@ public: * @param enabled {boolean} * @param callback {} */ - + /**jsdoc + * Called when setBakingEnabled is complete. + * @callback Assets~setBakingEnabledCallback + */ Q_INVOKABLE void setBakingEnabled(QString path, bool enabled, QScriptValue callback); #if (PR_BUILD || DEV_BUILD) @@ -122,13 +110,14 @@ public: * Request Asset data from the ATP Server * @function Assets.getAsset * @param {URL|Assets.GetOptions} options An atp: style URL, hash, or relative mapped path; or an {@link Assets.GetOptions} object with request parameters - * @param {Assets~getAssetCallback} scope[callback] A scope callback function to receive (error, results) values + * @param {Assets~getAssetCallback} scope A scope callback function to receive (error, results) values + * @param {function} [callback=undefined] */ /**jsdoc * A set of properties that can be passed to {@link Assets.getAsset}. * @typedef {Object} Assets.GetOptions - * @property {URL} [url] an "atp:" style URL, hash, or relative mapped path to fetch + * @property {string} [url] an "atp:" style URL, hash, or relative mapped path to fetch * @property {string} [responseType=text] the desired reponse type (text | arraybuffer | json) * @property {boolean} [decompress=false] whether to attempt gunzip decompression on the fetched data * See: {@link Assets.putAsset} and its .compress=true option @@ -144,7 +133,7 @@ public: /**jsdoc * Result value returned by {@link Assets.getAsset}. * @typedef {Object} Assets~getAssetResult - * @property {url} [url] the resolved "atp:" style URL for the fetched asset + * @property {string} [url] the resolved "atp:" style URL for the fetched asset * @property {string} [hash] the resolved hash for the fetched asset * @property {string|ArrayBuffer|Object} [response] response data (possibly converted per .responseType value) * @property {string} [responseType] response type (text | arraybuffer | json) @@ -160,6 +149,7 @@ public: * @function Assets.putAsset * @param {Assets.PutOptions} options A PutOptions object with upload parameters * @param {Assets~putAssetCallback} scope[callback] A scoped callback function invoked with (error, results) + * @param {function} [callback=undefined] */ /**jsdoc @@ -180,7 +170,7 @@ public: /**jsdoc * Result value returned by {@link Assets.putAsset}. * @typedef {Object} Assets~putAssetResult - * @property {url} [url] the resolved "atp:" style URL for the uploaded asset (based on .path if specified, otherwise on the resulting ATP hash) + * @property {string} [url] the resolved "atp:" style URL for the uploaded asset (based on .path if specified, otherwise on the resulting ATP hash) * @property {string} [path] the uploaded asset's resulting ATP path (or undefined if no path mapping was assigned) * @property {string} [hash] the uploaded asset's resulting ATP hash * @property {boolean} [compressed] flag indicating whether the data was compressed before upload @@ -243,7 +233,7 @@ public: /**jsdoc * @function Assets.getCacheStatus * @property {} scope - * @property {} [callback = ""] + * @property {} [callback=undefined] */ Q_INVOKABLE void getCacheStatus(QScriptValue scope, QScriptValue callback = QScriptValue()) { @@ -254,7 +244,7 @@ public: * @function Assets.queryCacheMeta * @property {} options * @property {} scope - * @property {} [callback = ""] + * @property {} [callback=undefined] */ Q_INVOKABLE void queryCacheMeta(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); @@ -263,7 +253,7 @@ public: * @function Assets.loadFromCache * @property {} options * @property {} scope - * @property {} [callback = ""] + * @property {} [callback=undefined] */ Q_INVOKABLE void loadFromCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); @@ -272,7 +262,7 @@ public: * @function Assets.saveToCache * @property {} options * @property {} scope - * @property {} [callback = ""] + * @property {} [callback=undefined] */ Q_INVOKABLE void saveToCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); @@ -283,7 +273,7 @@ public: * @property {} data * @property {} metadata * @property {} scope - * @property {} [callback = ""] + * @property {} [callback=undefined] */ Q_INVOKABLE void saveToCache(const QUrl& url, const QByteArray& data, const QVariantMap& metadata, diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index be2b4ebc8c..36fe29243d 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -31,21 +31,88 @@ protected: AudioScriptingInterface() {} // these methods are protected to stop C++ callers from calling, but invokable from script + + /**jsdoc + * @function Audio.playSound + * @param {} sound + * @param {} [injectorOptions=null] + * @returns {object} + */ Q_INVOKABLE ScriptAudioInjector* playSound(SharedSoundPointer sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions()); + + /**jsdoc + * @function Audio.playSystemSound + * @param {} sound + * @param {} position + * @returns {object} + */ // FIXME: there is no way to play a positionless sound Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound, const QVector3D& position); + /**jsdoc + * @function Audio.setStereoInput + * @param {boolean} stereo + * @returns {boolean} + */ Q_INVOKABLE bool setStereoInput(bool stereo); + + /**jsdoc + * @function Audio.isStereoInput + * @returns {boolean} + */ Q_INVOKABLE bool isStereoInput(); signals: - void mutedByMixer(); /// the client has been muted by the mixer - void environmentMuted(); /// the entire environment has been muted by the mixer - void receivedFirstPacket(); /// the client has received its first packet from the audio mixer - void disconnected(); /// the client has been disconnected from the audio mixer - void noiseGateOpened(); /// the noise gate has opened - void noiseGateClosed(); /// the noise gate has closed - void inputReceived(const QByteArray& inputSamples); /// a frame of mic input audio has been received and processed + + /**jsdoc + * The client has been muted by the mixer. + * @function Audio.mutedByMixer + * @returns {Signal} + */ + void mutedByMixer(); + + /**jsdoc + * The entire environment has been muted by the mixer. + * @function Audio.environmentMuted + * @returns {Signal} + */ + void environmentMuted(); + + /**jsdoc + * The client has received its first packet from the audio mixer. + * @function Audio.receivedFirstPacket + * @returns {Signal} + */ + void receivedFirstPacket(); + + /**jsdoc + * The client has been disconnected from the audio mixer. + * @function Audio.disconnected + * @returns {Signal} + */ + void disconnected(); + + /**jsdoc + * The noise gate has opened. + * @function Audio.noiseGateOpened + * @returns {Signal} + */ + void noiseGateOpened(); + + /**jsdoc + * The noise gate has closed. + * @function Audio.noiseGateClosed + * @returns {Signal} + */ + void noiseGateClosed(); + + /**jsdoc + * A frame of mic input audio has been received and processed. + * @function Audio.inputReceived + * @param {} inputSamples + * @returns {Signal} + */ + void inputReceived(const QByteArray& inputSamples); private: AbstractAudioInterface* _localAudioInterface { nullptr }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index c79ffffec7..f0a13cc62b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2161,6 +2161,32 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& }, forceRedownload); } +/**jsdoc + * Triggered when the script starts for a user. + *

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

    + *
    Available in:Client Entity ScriptsServer Entity Scripts
    + * @function Entities.preload + * @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; + * + * this.preload = 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. + * }); + */ // since all of these operations can be asynch we will always do the actual work in the response handler // for the download void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success , const QString& status) { @@ -2345,6 +2371,13 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co processDeferredEntityLoads(entityScript, entityID); } +/**jsdoc + * Triggered when the script terminates for a user. + *

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

    + *
    Available in:Client Entity ScriptsServer Entity Scripts
    + * @function Entities.unload + * @returns {Signal} + */ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap) { if (QThread::currentThread() != thread()) { #ifdef THREAD_DEBUGGING diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 871705d74b..a788cd9f0e 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -273,9 +273,9 @@ QVariantList ScriptEngines::getRunning() { } else { displayURLString = displayURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)); } - resultNode.insert("url", displayURLString); // The path contains the exact path/URL of the script, which also is used in the stopScript function. - resultNode.insert("path", normalizeScriptURL(runningScript).toString()); + resultNode.insert("path", displayURLString); + resultNode.insert("url", normalizeScriptURL(runningScript).toString()); resultNode.insert("local", runningScriptURL.isLocalFile()); result.append(resultNode); } @@ -538,7 +538,6 @@ int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { ii++; - qDebug() << "initializer" << ii; initializer(scriptEngine); } return ii; diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index b1ceab4149..c7ad4a790d 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -213,7 +213,7 @@ void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectio int byteForSection = (BITS_IN_OCTAL * section / BITS_IN_BYTE); unsigned char* byteAt = octalCode + 1 + byteForSection; char bitInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE; - char shiftBy = BITS_IN_BYTE - bitInByte - BITS_IN_OCTAL; + int8_t shiftBy = BITS_IN_BYTE - bitInByte - BITS_IN_OCTAL; const unsigned char UNSHIFTED_MASK = 0x07; unsigned char shiftedMask; unsigned char shiftedValue; diff --git a/libraries/shared/src/shared/MiniPromises.cpp b/libraries/shared/src/shared/MiniPromises.cpp index bb78852c29..21a3f44d50 100644 --- a/libraries/shared/src/shared/MiniPromises.cpp +++ b/libraries/shared/src/shared/MiniPromises.cpp @@ -22,6 +22,5 @@ namespace { } void MiniPromise::registerMetaTypes(QObject* engine) { auto scriptEngine = qobject_cast(engine); - qDebug() << "----------------------- MiniPromise::registerMetaTypes ------------" << scriptEngine; qScriptRegisterMetaType(scriptEngine, promiseToScriptValue, promiseFromScriptValue); } diff --git a/libraries/shared/src/shared/Storage.cpp b/libraries/shared/src/shared/Storage.cpp index 8fe1454242..b983213e4a 100644 --- a/libraries/shared/src/shared/Storage.cpp +++ b/libraries/shared/src/shared/Storage.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include "StorageLogging.h" Q_LOGGING_CATEGORY(storagelogging, "hifi.core.storage") @@ -102,4 +102,4 @@ FileStorage::~FileStorage() { if (_file.isOpen()) { _file.close(); } -} \ No newline at end of file +} diff --git a/libraries/shared/src/shared/StorageLogging.h b/libraries/shared/src/shared/StorageLogging.h new file mode 100644 index 0000000000..33d89411bd --- /dev/null +++ b/libraries/shared/src/shared/StorageLogging.h @@ -0,0 +1,18 @@ +// +// StorageLogging.h +// +// Created by Seth Alves on 2018-4-20 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_StorageLogging_h +#define hifi_StorageLogging_h + +#include + +Q_DECLARE_LOGGING_CATEGORY(storagelogging) + +#endif // hifi_StorageLogging_h diff --git a/libraries/trackers/src/trackers/FaceTracker.h b/libraries/trackers/src/trackers/FaceTracker.h index 4224bb6633..47fbf72616 100644 --- a/libraries/trackers/src/trackers/FaceTracker.h +++ b/libraries/trackers/src/trackers/FaceTracker.h @@ -64,29 +64,22 @@ signals: * @function FaceTracker.muteToggled * @returns {Signal} */ - void muteToggled(); public slots: - /**jsdoc - * @function FaceTracker.setEnabled - * @param {boolean} enabled - */ - + // No JSDoc here because it's overridden in DdeFaceTracker. virtual void setEnabled(bool enabled) = 0; /**jsdoc * @function FaceTracker.toggleMute */ - void toggleMute(); /**jsdoc * @function FaceTracker.getMuted * @returns {boolean} */ - bool getMuted() { return _isMuted; } protected: diff --git a/libraries/ui/src/ui/Logging.h b/libraries/ui/src/ui/Logging.h index 6d31b0e86a..dd14268dba 100644 --- a/libraries/ui/src/ui/Logging.h +++ b/libraries/ui/src/ui/Logging.h @@ -6,8 +6,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_Controllers_Logging_h -#define hifi_Controllers_Logging_h +#ifndef hifi_UI_Logging_h +#define hifi_UI_Logging_h #include diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 43b573a169..ac4194ed55 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -102,7 +102,7 @@ class AudioHandler : public QObject, QRunnable { public: AudioHandler(OffscreenQmlSurface* surface, const QString& deviceName, QObject* parent = nullptr); - virtual ~AudioHandler() { qDebug() << "Audio Handler Destroyed"; } + virtual ~AudioHandler() { } void run() override; diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 9403a824e3..aea752c565 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -21,40 +21,16 @@ // BEGIN AVATAR SELECTOR LOGIC - var UNSELECTED_TEXTURES = { - "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png") - }; - var SELECTED_TEXTURES = { - "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-selected.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-selected.png") - }; - var HOVER_TEXTURES = { - "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-hover.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-hover.png") - }; - var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6 }; var SELECTED_COLOR = { red: 0xF3, green: 0x91, blue: 0x29 }; var HOVER_COLOR = { red: 0xD0, green: 0xD0, blue: 0xD0 }; - var conserveResources = true; var overlays = {}; // Keeps track of all our extended overlay data objects, keyed by target identifier. - function ExtendedOverlay(key, type, properties, selected, hasModel) { // A wrapper around overlays to store the key it is associated with. + function ExtendedOverlay(key, type, properties) { // A wrapper around overlays to store the key it is associated with. overlays[key] = this; - if (hasModel) { - var modelKey = key + "-m"; - this.model = new ExtendedOverlay(modelKey, "model", { - url: Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx"), - textures: textures(selected), - ignoreRayIntersection: true - }, false, false); - } else { - this.model = undefined; - } this.key = key; - this.selected = selected || false; // not undefined + this.selected = false; this.hovering = false; this.activeOverlay = Overlays.addOverlay(type, properties); // We could use different overlays for (un)selected... } @@ -76,10 +52,6 @@ } return { red: scale(base.red), green: scale(base.green), blue: scale(base.blue) }; } - - function textures(selected, hovering) { - return hovering ? HOVER_TEXTURES : selected ? SELECTED_TEXTURES : UNSELECTED_TEXTURES; - } // so we don't have to traverse the overlays to get the last one var lastHoveringId = 0; ExtendedOverlay.prototype.hover = function (hovering) { @@ -91,9 +63,6 @@ lastHoveringId = 0; } this.editOverlay({ color: color(this.selected, hovering) }); - if (this.model) { - this.model.editOverlay({ textures: textures(this.selected, hovering) }); - } if (hovering) { // un-hover the last hovering overlay if (lastHoveringId && lastHoveringId !== this.key) { @@ -108,15 +77,12 @@ } this.editOverlay({ color: color(selected, this.hovering) }); - if (this.model) { - this.model.editOverlay({ textures: textures(selected) }); - } this.selected = selected; }; // Class methods: - var selectedIds = []; + var selectedId = false; ExtendedOverlay.isSelected = function (id) { - return -1 !== selectedIds.indexOf(id); + return selectedId === id; }; ExtendedOverlay.get = function (key) { // answer the extended overlay data object associated with the given avatar identifier return overlays[key]; @@ -153,51 +119,14 @@ }); }; - function HighlightedEntity(id, entityProperties) { - this.id = id; - this.overlay = Overlays.addOverlay('cube', { - position: entityProperties.position, - rotation: entityProperties.rotation, - dimensions: entityProperties.dimensions, - solid: false, - color: { - red: 0xF3, - green: 0x91, - blue: 0x29 - }, - ignoreRayIntersection: true, - drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. - }); - HighlightedEntity.overlays.push(this); - } - HighlightedEntity.overlays = []; - HighlightedEntity.clearOverlays = function clearHighlightedEntities() { - HighlightedEntity.overlays.forEach(function (highlighted) { - Overlays.deleteOverlay(highlighted.overlay); - }); - HighlightedEntity.overlays = []; - }; - HighlightedEntity.updateOverlays = function updateHighlightedEntities() { - HighlightedEntity.overlays.forEach(function (highlighted) { - var properties = Entities.getEntityProperties(highlighted.id, ['position', 'rotation', 'dimensions']); - Overlays.editOverlay(highlighted.overlay, { - position: properties.position, - rotation: properties.rotation, - dimensions: properties.dimensions - }); - }); - }; - - function addAvatarNode(id) { - var selected = ExtendedOverlay.isSelected(id); return new ExtendedOverlay(id, "sphere", { drawInFront: true, solid: true, alpha: 0.8, - color: color(selected, false), + color: color(false, false), ignoreRayIntersection: false - }, selected, !conserveResources); + }); } var pingPong = true; @@ -236,14 +165,6 @@ position: target, dimensions: 0.032 * distance }); - if (overlay.model) { - overlay.model.ping = pingPong; - overlay.model.editOverlay({ - position: target, - scale: 0.2 * distance, // constant apparent size - rotation: Camera.orientation - }); - } }); pingPong = !pingPong; ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) @@ -251,13 +172,10 @@ overlay.deleteOverlay(); } }); - // We could re-populateNearbyUserList if anything added or removed, but not for now. - HighlightedEntity.updateOverlays(); } function removeOverlays() { - selectedIds = []; + selectedId = false; lastHoveringId = 0; - HighlightedEntity.clearOverlays(); ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); }); @@ -267,7 +185,7 @@ // Clicks. // function usernameFromIDReply(id, username, machineFingerprint, isAdmin) { - if (selectedIds[0] === id) { + if (selectedId === id) { var message = { method: 'updateSelectedRecipientUsername', userName: username === "" ? "unknown username" : username @@ -279,13 +197,13 @@ ExtendedOverlay.applyPickRay(pickRay, function (overlay) { var nextSelectedStatus = !overlay.selected; var avatarId = overlay.key; - selectedIds = nextSelectedStatus ? [avatarId] : []; + selectedId = nextSelectedStatus ? avatarId : false; if (nextSelectedStatus) { Users.requestUsernameFromID(avatarId); } var message = { method: 'selectRecipient', - id: [avatarId], + id: avatarId, isSelected: nextSelectedStatus, displayName: '"' + AvatarList.getAvatar(avatarId).sessionDisplayName + '"', userName: '' @@ -298,24 +216,6 @@ overlay.select(selected); }); - HighlightedEntity.clearOverlays(); - if (selectedIds.length) { - Entities.findEntitiesInFrustum(Camera.frustum).forEach(function (id) { - // Because lastEditedBy is per session, the vast majority of entities won't match, - // so it would probably be worth reducing marshalling costs by asking for just we need. - // However, providing property name(s) is advisory and some additional properties are - // included anyway. As it turns out, asking for 'lastEditedBy' gives 'position', 'rotation', - // and 'dimensions', too, so we might as well make use of them instead of making a second - // getEntityProperties call. - // It would be nice if we could harden this against future changes by specifying all - // and only these four in an array, but see - // https://highfidelity.fogbugz.com/f/cases/2728/Entities-getEntityProperties-id-lastEditedBy-name-lastEditedBy-doesn-t-work - var properties = Entities.getEntityProperties(id, 'lastEditedBy'); - if (ExtendedOverlay.isSelected(properties.lastEditedBy)) { - new HighlightedEntity(id, properties); - } - }); - } return true; }); } @@ -657,12 +557,14 @@ } if (onWalletScreen) { + if (!isWired) { + Users.usernameFromIDReply.connect(usernameFromIDReply); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + triggerMapping.enable(); + triggerPressMapping.enable(); + } isWired = true; - Users.usernameFromIDReply.connect(usernameFromIDReply); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); } else { off(); } diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 53dbee829d..1fce772ec8 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -796,7 +796,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa }; var onMousePress = function(event) { - if (isInEditMode()) { // don't consider any mouse clicks on the entity while in edit + if (isInEditMode() || !event.isLeftButton) { // don't consider any left clicks on the entity while in edit return; } var pickRay = Camera.computePickRay(event.x, event.y); diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 64ce73fad6..a05778e2dd 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -153,40 +153,16 @@ var selectionDisplay = null; // for gridTool.js to ignore } // BEGIN AVATAR SELECTOR LOGIC - var UNSELECTED_TEXTURES = { - "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png") - }; - var SELECTED_TEXTURES = { - "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-selected.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-selected.png") - }; - var HOVER_TEXTURES = { - "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-hover.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-hover.png") - }; - var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6 }; var SELECTED_COLOR = { red: 0xF3, green: 0x91, blue: 0x29 }; var HOVER_COLOR = { red: 0xD0, green: 0xD0, blue: 0xD0 }; - var conserveResources = true; var overlays = {}; // Keeps track of all our extended overlay data objects, keyed by target identifier. - function ExtendedOverlay(key, type, properties, selected, hasModel) { // A wrapper around overlays to store the key it is associated with. + function ExtendedOverlay(key, type, properties) { // A wrapper around overlays to store the key it is associated with. overlays[key] = this; - if (hasModel) { - var modelKey = key + "-m"; - this.model = new ExtendedOverlay(modelKey, "model", { - url: Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx"), - textures: textures(selected), - ignoreRayIntersection: true - }, false, false); - } else { - this.model = undefined; - } this.key = key; - this.selected = selected || false; // not undefined + this.selected = false; this.hovering = false; this.activeOverlay = Overlays.addOverlay(type, properties); // We could use different overlays for (un)selected... } @@ -208,10 +184,6 @@ var selectionDisplay = null; // for gridTool.js to ignore } return { red: scale(base.red), green: scale(base.green), blue: scale(base.blue) }; } - - function textures(selected, hovering) { - return hovering ? HOVER_TEXTURES : selected ? SELECTED_TEXTURES : UNSELECTED_TEXTURES; - } // so we don't have to traverse the overlays to get the last one var lastHoveringId = 0; ExtendedOverlay.prototype.hover = function (hovering) { @@ -223,9 +195,6 @@ var selectionDisplay = null; // for gridTool.js to ignore lastHoveringId = 0; } this.editOverlay({ color: color(this.selected, hovering) }); - if (this.model) { - this.model.editOverlay({ textures: textures(this.selected, hovering) }); - } if (hovering) { // un-hover the last hovering overlay if (lastHoveringId && lastHoveringId !== this.key) { @@ -240,15 +209,12 @@ var selectionDisplay = null; // for gridTool.js to ignore } this.editOverlay({ color: color(selected, this.hovering) }); - if (this.model) { - this.model.editOverlay({ textures: textures(selected) }); - } this.selected = selected; }; // Class methods: - var selectedIds = []; + var selectedId = false; ExtendedOverlay.isSelected = function (id) { - return -1 !== selectedIds.indexOf(id); + return selectedId === id; }; ExtendedOverlay.get = function (key) { // answer the extended overlay data object associated with the given avatar identifier return overlays[key]; @@ -285,51 +251,14 @@ var selectionDisplay = null; // for gridTool.js to ignore }); }; - function HighlightedEntity(id, entityProperties) { - this.id = id; - this.overlay = Overlays.addOverlay('cube', { - position: entityProperties.position, - rotation: entityProperties.rotation, - dimensions: entityProperties.dimensions, - solid: false, - color: { - red: 0xF3, - green: 0x91, - blue: 0x29 - }, - ignoreRayIntersection: true, - drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. - }); - HighlightedEntity.overlays.push(this); - } - HighlightedEntity.overlays = []; - HighlightedEntity.clearOverlays = function clearHighlightedEntities() { - HighlightedEntity.overlays.forEach(function (highlighted) { - Overlays.deleteOverlay(highlighted.overlay); - }); - HighlightedEntity.overlays = []; - }; - HighlightedEntity.updateOverlays = function updateHighlightedEntities() { - HighlightedEntity.overlays.forEach(function (highlighted) { - var properties = Entities.getEntityProperties(highlighted.id, ['position', 'rotation', 'dimensions']); - Overlays.editOverlay(highlighted.overlay, { - position: properties.position, - rotation: properties.rotation, - dimensions: properties.dimensions - }); - }); - }; - - function addAvatarNode(id) { - var selected = ExtendedOverlay.isSelected(id); return new ExtendedOverlay(id, "sphere", { drawInFront: true, solid: true, alpha: 0.8, - color: color(selected, false), + color: color(false, false), ignoreRayIntersection: false - }, selected, !conserveResources); + }); } var pingPong = true; @@ -368,14 +297,6 @@ var selectionDisplay = null; // for gridTool.js to ignore position: target, dimensions: 0.032 * distance }); - if (overlay.model) { - overlay.model.ping = pingPong; - overlay.model.editOverlay({ - position: target, - scale: 0.2 * distance, // constant apparent size - rotation: Camera.orientation - }); - } }); pingPong = !pingPong; ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) @@ -383,13 +304,10 @@ var selectionDisplay = null; // for gridTool.js to ignore overlay.deleteOverlay(); } }); - // We could re-populateNearbyUserList if anything added or removed, but not for now. - HighlightedEntity.updateOverlays(); } function removeOverlays() { - selectedIds = []; + selectedId = false; lastHoveringId = 0; - HighlightedEntity.clearOverlays(); ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); }); @@ -399,7 +317,7 @@ var selectionDisplay = null; // for gridTool.js to ignore // Clicks. // function usernameFromIDReply(id, username, machineFingerprint, isAdmin) { - if (selectedIds[0] === id) { + if (selectedId === id) { var message = { method: 'updateSelectedRecipientUsername', userName: username === "" ? "unknown username" : username @@ -411,13 +329,13 @@ var selectionDisplay = null; // for gridTool.js to ignore ExtendedOverlay.applyPickRay(pickRay, function (overlay) { var nextSelectedStatus = !overlay.selected; var avatarId = overlay.key; - selectedIds = nextSelectedStatus ? [avatarId] : []; + selectedId = nextSelectedStatus ? avatarId : false; if (nextSelectedStatus) { Users.requestUsernameFromID(avatarId); } var message = { method: 'selectRecipient', - id: [avatarId], + id: avatarId, isSelected: nextSelectedStatus, displayName: '"' + AvatarList.getAvatar(avatarId).sessionDisplayName + '"', userName: '' @@ -430,24 +348,6 @@ var selectionDisplay = null; // for gridTool.js to ignore overlay.select(selected); }); - HighlightedEntity.clearOverlays(); - if (selectedIds.length) { - Entities.findEntitiesInFrustum(Camera.frustum).forEach(function (id) { - // Because lastEditedBy is per session, the vast majority of entities won't match, - // so it would probably be worth reducing marshalling costs by asking for just we need. - // However, providing property name(s) is advisory and some additional properties are - // included anyway. As it turns out, asking for 'lastEditedBy' gives 'position', 'rotation', - // and 'dimensions', too, so we might as well make use of them instead of making a second - // getEntityProperties call. - // It would be nice if we could harden this against future changes by specifying all - // and only these four in an array, but see - // https://highfidelity.fogbugz.com/f/cases/2728/Entities-getEntityProperties-id-lastEditedBy-name-lastEditedBy-doesn-t-work - var properties = Entities.getEntityProperties(id, 'lastEditedBy'); - if (ExtendedOverlay.isSelected(properties.lastEditedBy)) { - new HighlightedEntity(id, properties); - } - }); - } return true; }); } @@ -1155,12 +1055,14 @@ var selectionDisplay = null; // for gridTool.js to ignore } if (onCommerceScreen) { + if (!isWired) { + Users.usernameFromIDReply.connect(usernameFromIDReply); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + triggerMapping.enable(); + triggerPressMapping.enable(); + } isWired = true; - Users.usernameFromIDReply.connect(usernameFromIDReply); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); Wallet.refreshWalletStatus(); } else { off(); diff --git a/scripts/system/particle_explorer/particleExplorer.js b/scripts/system/particle_explorer/particleExplorer.js index 3598f30ee0..099c4be9e3 100644 --- a/scripts/system/particle_explorer/particleExplorer.js +++ b/scripts/system/particle_explorer/particleExplorer.js @@ -321,7 +321,8 @@ { id: "alpha", name: "Alpha", - type: "SliderFloat" + type: "SliderFloat", + max: 1.0 }, { type: "Row" @@ -329,7 +330,8 @@ { id: "alphaSpread", name: "Alpha Spread", - type: "SliderFloat" + type: "SliderFloat", + max: 1.0 }, { type: "Row" @@ -337,7 +339,8 @@ { id: "alphaStart", name: "Alpha Start", - type: "SliderFloat" + type: "SliderFloat", + max: 1.0 }, { type: "Row" @@ -345,7 +348,8 @@ { id: "alphaFinish", name: "Alpha Finish", - type: "SliderFloat" + type: "SliderFloat", + max: 1.0 }, { type: "Row" diff --git a/tests/controllers/CMakeLists.txt b/tests/controllers/CMakeLists.txt index b5e866ccce..ce1c150ed4 100644 --- a/tests/controllers/CMakeLists.txt +++ b/tests/controllers/CMakeLists.txt @@ -23,5 +23,9 @@ if (WIN32) add_dependency_external_projects(wasapi) endif() +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + target_link_libraries(${TARGET_NAME} atomic) +endif() + package_libraries_for_deployment() -endif() \ No newline at end of file +endif() diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 9d6ed0e595..93ff325a98 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -27,6 +27,10 @@ if (WIN32) add_dependency_external_projects(wasapi) endif() +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + target_link_libraries(${TARGET_NAME} atomic) +endif() + package_libraries_for_deployment() diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 07644850ee..5092e8b809 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -9,21 +9,25 @@ function endsWith(path, exts) { } exports.handlers = { + + // This event is triggered before parsing has even started. + // We use this event to scan the C++ files for jsdoc comments + // and reformat them into a form digestable by jsdoc. beforeParse: function(e) { - const pathTools = require('path'); + var pathTools = require('path'); var rootFolder = pathTools.dirname(e.filename); console.log("Scanning hifi source for jsdoc comments..."); // directories to scan for jsdoc comments var dirList = [ '../../interface/src', - '../../interface/src/assets', - '../../interface/src/audio', + '../../interface/src/assets', + '../../interface/src/audio', '../../interface/src/avatar', - '../../interface/src/commerce', - '../../interface/src/devices', - '../../interface/src/java', - '../../interface/src/networking', + '../../interface/src/commerce', + '../../interface/src/devices', + '../../interface/src/java', + '../../interface/src/networking', '../../interface/src/ui/', '../../interface/src/scripting', '../../interface/src/ui/overlays', @@ -47,27 +51,96 @@ exports.handlers = { '../../libraries/script-engine/src', '../../libraries/shared/src', '../../libraries/shared/src/shared', + '../../libraries/trackers/src/trackers', '../../libraries/ui/src/ui', '../../plugins/oculus/src', - '../../plugins/openvr/src', + '../../plugins/openvr/src' ]; + + // only files with this extension will be searched for jsdoc comments. var exts = ['.h', '.cpp']; - const fs = require('fs'); + var fs = require('fs'); dirList.forEach(function (dir) { var joinedDir = pathTools.join(rootFolder, dir); - var files = fs.readdirSync(joinedDir) + var files = fs.readdirSync(joinedDir); files.forEach(function (file) { var path = pathTools.join(joinedDir, file); if (fs.lstatSync(path).isFile() && endsWith(path, exts)) { + // load entire file into a string var data = fs.readFileSync(path, "utf8"); + + // this regex searches for blocks starting with /**jsdoc and end with */ var reg = /(\/\*\*jsdoc(.|[\r\n])*?\*\/)/gm; var matches = data.match(reg); if (matches) { - e.source += matches.map(function (s) { return s.replace('/**jsdoc', '/**'); }).join('\n'); + // add to source, but strip off c-comment asterisks + e.source += matches.map(function (s) { + return s.replace('/**jsdoc', '/**'); + }).join('\n'); } } }); }); + }, + + // This event is triggered when a new doclet has been created + // but before it is passed to the template for output + newDoclet: function (e) { + + // we only care about hifi custom tags on namespace and class doclets + if (e.doclet.kind === "namespace" || e.doclet.kind === "class") { + var rows = []; + if (e.doclet.hifiInterface) { + rows.push("Interface Scripts"); + } + if (e.doclet.hifiClientEntity) { + rows.push("Client Entity Scripts"); + } + if (e.doclet.hifiServerEntity) { + rows.push("Server Entity Scripts"); + } + if (e.doclet.hifiAssignmentClient) { + rows.push("Assignment Client Scripts"); + } + + // Append an Available In: table at the end of the namespace description. + if (rows.length > 0) { + var table = "

    Available in:" + rows.join("") + "
    "; + e.doclet.description = (e.doclet.description ? e.doclet.description : "") + table; + } + } } }; + +// Define custom hifi tags here +exports.defineTags = function (dictionary) { + + // @hifi-interface + dictionary.defineTag("hifi-interface", { + onTagged: function (doclet, tag) { + doclet.hifiInterface = true; + } + }); + + // @hifi-assignment-client + dictionary.defineTag("hifi-assignment-client", { + onTagged: function (doclet, tag) { + doclet.hifiAssignmentClient = true; + } + }); + + // @hifi-client-entity + dictionary.defineTag("hifi-client-entity", { + onTagged: function (doclet, tag) { + doclet.hifiClientEntity = true; + } + }); + + // @hifi-server-entity + dictionary.defineTag("hifi-server-entity", { + onTagged: function (doclet, tag) { + doclet.hifiServerEntity = true; + } + }); +};