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 Name | Description | Example |
+ *
+ *
+ *
+ * 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. |
+ *
+ *
+ * releaseGrab |
+ * This 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 Scripts | Server 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 Scripts | Server 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;
+ }
+ });
+};