From dafa830c0db183fd844404269e11085aaad97249 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 25 Oct 2017 14:07:02 -0700 Subject: [PATCH 01/81] First steps --- .../qml/hifi/commerce/checkout/Checkout.qml | 22 +++++++-------- .../common/EmulatedMarketplaceHeader.qml | 12 ++++----- .../InspectionCertificate.qml | 6 ++--- .../qml/hifi/commerce/purchases/Purchases.qml | 18 ++++++------- .../qml/hifi/commerce/wallet/Help.qml | 10 +++---- .../qml/hifi/commerce/wallet/NeedsLogIn.qml | 4 +-- .../hifi/commerce/wallet/PassphraseModal.qml | 10 +++---- .../commerce/wallet/PassphraseSelection.qml | 8 +++--- .../qml/hifi/commerce/wallet/Security.qml | 6 ++--- .../commerce/wallet/SecurityImageChange.qml | 8 +++--- .../qml/hifi/commerce/wallet/SendMoney.qml | 4 +-- .../qml/hifi/commerce/wallet/Wallet.qml | 16 +++++------ .../qml/hifi/commerce/wallet/WalletHome.qml | 12 ++++----- .../qml/hifi/commerce/wallet/WalletSetup.qml | 12 ++++----- interface/src/Application.cpp | 27 ++++++++++++++++++- interface/src/commerce/QmlCommerce.cpp | 4 +-- interface/src/commerce/QmlCommerce.h | 6 ++--- libraries/ui/src/QmlWindowClass.cpp | 2 +- scripts/system/commerce/wallet.js | 8 ++++-- 19 files changed, 110 insertions(+), 85 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 8ea9ce494c..0a4b2e2cff 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -43,8 +43,8 @@ Rectangle { property bool isWearable; // Style color: hifi.colors.white; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onWalletStatusResult: { if (walletStatus === 0) { @@ -71,7 +71,7 @@ Rectangle { if (!isLoggedIn && root.activeView !== "needsLogIn") { root.activeView = "needsLogIn"; } else { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -112,7 +112,7 @@ Rectangle { } onItemIdChanged: { - commerce.inventory(); + Commerce.inventory(); itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; } @@ -121,7 +121,7 @@ Rectangle { } onItemPriceChanged: { - commerce.balance(); + Commerce.balance(); } Timer { @@ -200,7 +200,7 @@ Rectangle { Component.onCompleted: { purchasesReceived = false; balanceReceived = false; - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -221,7 +221,7 @@ Rectangle { Connections { target: GlobalServices onMyUsernameChanged: { - commerce.getLoginStatus(); + Commerce.getLoginStatus(); } } @@ -471,9 +471,9 @@ Rectangle { if (itemIsJson) { buyButton.enabled = false; if (!root.shouldBuyWithControlledFailure) { - commerce.buy(itemId, itemPrice); + Commerce.buy(itemId, itemPrice); } else { - commerce.buy(itemId, itemPrice, true); + Commerce.buy(itemId, itemPrice, true); } } else { if (urlHandler.canHandleUrl(itemHref)) { @@ -938,8 +938,8 @@ Rectangle { } root.balanceReceived = false; root.purchasesReceived = false; - commerce.inventory(); - commerce.balance(); + Commerce.inventory(); + Commerce.balance(); } // diff --git a/interface/resources/qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml b/interface/resources/qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml index cc316a70e9..e95c720e5f 100644 --- a/interface/resources/qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml +++ b/interface/resources/qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml @@ -31,14 +31,14 @@ Item { height: mainContainer.height + additionalDropdownHeight; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onWalletStatusResult: { if (walletStatus === 0) { sendToParent({method: "needsLogIn"}); } else if (walletStatus === 3) { - commerce.getSecurityImage(); + Commerce.getSecurityImage(); } else if (walletStatus > 3) { console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus); } @@ -48,7 +48,7 @@ Item { if (!isLoggedIn) { sendToParent({method: "needsLogIn"}); } else { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -61,13 +61,13 @@ Item { } Component.onCompleted: { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } Connections { target: GlobalServices onMyUsernameChanged: { - commerce.getLoginStatus(); + Commerce.getLoginStatus(); } } diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index aa1372494f..ec34de6adc 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -35,8 +35,8 @@ Rectangle { property bool isMyCert: false; // Style color: hifi.colors.faintGray; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onCertificateInfoResult: { if (result.status !== 'success') { @@ -69,7 +69,7 @@ Rectangle { onCertificateIdChanged: { if (certificateId !== "") { - commerce.certificateInfo(certificateId); + Commerce.certificateInfo(certificateId); } } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index f292f9603e..b88710d19c 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -38,8 +38,8 @@ Rectangle { property bool isDebuggingFirstUseTutorial: false; // Style color: hifi.colors.white; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onWalletStatusResult: { if (walletStatus === 0) { @@ -60,7 +60,7 @@ Rectangle { root.activeView = "firstUseTutorial"; } else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") { root.activeView = "purchasesMain"; - commerce.inventory(); + Commerce.inventory(); } } else { console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus); @@ -71,7 +71,7 @@ Rectangle { if (!isLoggedIn && root.activeView !== "needsLogIn") { root.activeView = "needsLogIn"; } else { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -197,7 +197,7 @@ Rectangle { Component.onCompleted: { securityImageResultReceived = false; purchasesReceived = false; - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -218,7 +218,7 @@ Rectangle { Connections { target: GlobalServices onMyUsernameChanged: { - commerce.getLoginStatus(); + Commerce.getLoginStatus(); } } @@ -233,7 +233,7 @@ Rectangle { onSendSignalToParent: { if (msg.method === "authSuccess") { root.activeView = "initialize"; - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } else { sendToScript(msg); } @@ -254,7 +254,7 @@ Rectangle { case 'tutorial_finished': Settings.setValue("isFirstUseOfPurchases", false); root.activeView = "purchasesMain"; - commerce.inventory(); + Commerce.inventory(); break; } } @@ -589,7 +589,7 @@ Rectangle { if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) { console.log("Refreshing Purchases..."); root.pendingInventoryReply = true; - commerce.inventory(); + Commerce.inventory(); } } } diff --git a/interface/resources/qml/hifi/commerce/wallet/Help.qml b/interface/resources/qml/hifi/commerce/wallet/Help.qml index 0026bf6cdb..f41c6932c0 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Help.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Help.qml @@ -27,8 +27,8 @@ Item { property string keyFilePath; property bool showDebugButtons: true; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onKeyFilePathIfExistsResult: { root.keyFilePath = path; @@ -37,7 +37,7 @@ Item { onVisibleChanged: { if (visible) { - commerce.getKeyFilePathIfExists(); + Commerce.getKeyFilePathIfExists(); } } @@ -67,7 +67,7 @@ Item { width: 150; text: "DBG: Clear Pass"; onClicked: { - commerce.setPassphrase(""); + Commerce.setPassphrase(""); sendSignalToWallet({method: 'passphraseReset'}); } } @@ -82,7 +82,7 @@ Item { width: 150; text: "DBG: RST Wallet"; onClicked: { - commerce.reset(); + Commerce.reset(); sendSignalToWallet({method: 'walletReset'}); } } diff --git a/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml b/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml index 7ce0cf3853..404d7e84cf 100644 --- a/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml +++ b/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml @@ -30,8 +30,8 @@ Item { source: "images/wallet-bg.jpg"; } - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; } // diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index d967a36b68..9f04db7d5c 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -36,8 +36,8 @@ Item { source: "images/wallet-bg.jpg"; } - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onSecurityImageResult: { titleBarSecurityImage.source = ""; @@ -218,7 +218,7 @@ Item { onAccepted: { submitPassphraseInputButton.enabled = false; - commerce.setPassphrase(passphraseField.text); + Commerce.setPassphrase(passphraseField.text); } } @@ -258,7 +258,7 @@ Item { source: "image://security/securityImage"; cache: false; onVisibleChanged: { - commerce.getSecurityImage(); + Commerce.getSecurityImage(); } } Item { @@ -326,7 +326,7 @@ Item { text: "Submit" onClicked: { submitPassphraseInputButton.enabled = false; - commerce.setPassphrase(passphraseField.text); + Commerce.setPassphrase(passphraseField.text); } } diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml index ffeedde8f0..0145f92b96 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml @@ -36,8 +36,8 @@ Item { propagateComposedEvents: false; } - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onSecurityImageResult: { passphrasePageSecurityImage.source = ""; passphrasePageSecurityImage.source = "image://security/securityImage"; @@ -193,7 +193,7 @@ Item { source: "image://security/securityImage"; cache: false; onVisibleChanged: { - commerce.getSecurityImage(); + Commerce.getSecurityImage(); } } Item { @@ -316,7 +316,7 @@ Item { passphraseFieldAgain.error = false; currentPassphraseField.error = false; setErrorText(""); - commerce.changePassphrase(currentPassphraseField.text, passphraseField.text); + Commerce.changePassphrase(currentPassphraseField.text, passphraseField.text); return true; } } diff --git a/interface/resources/qml/hifi/commerce/wallet/Security.qml b/interface/resources/qml/hifi/commerce/wallet/Security.qml index 485b0ec086..d825196655 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Security.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Security.qml @@ -27,8 +27,8 @@ Item { id: root; property string keyFilePath; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onKeyFilePathIfExistsResult: { root.keyFilePath = path; @@ -234,7 +234,7 @@ Item { onVisibleChanged: { if (visible) { - commerce.getKeyFilePathIfExists(); + Commerce.getKeyFilePathIfExists(); } } diff --git a/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml b/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml index 7f767060f6..7cb4a3068f 100644 --- a/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml +++ b/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml @@ -30,8 +30,8 @@ Item { id: securityImageModel; } - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onSecurityImageResult: { securityImageChangePageSecurityImage.source = ""; @@ -70,7 +70,7 @@ Item { source: "image://security/securityImage"; cache: false; onVisibleChanged: { - commerce.getSecurityImage(); + Commerce.getSecurityImage(); } } Item { @@ -198,7 +198,7 @@ Item { securityImageSubmitButton.text = "Submitting..."; securityImageSubmitButton.enabled = false; var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex()) - commerce.chooseSecurityImage(securityImagePath); + Commerce.chooseSecurityImage(securityImagePath); } } } diff --git a/interface/resources/qml/hifi/commerce/wallet/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/SendMoney.qml index 75334b1686..11a6c99b0c 100644 --- a/interface/resources/qml/hifi/commerce/wallet/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/SendMoney.qml @@ -25,8 +25,8 @@ Item { id: root; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; } // "Unavailable" diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml index 759d7a37eb..21bf7bace0 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml @@ -36,8 +36,8 @@ Rectangle { source: "images/wallet-bg.jpg"; } - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onWalletStatusResult: { if (walletStatus === 0) { @@ -54,7 +54,7 @@ Rectangle { } } else if (walletStatus === 3) { root.activeView = "walletHome"; - commerce.getSecurityImage(); + Commerce.getSecurityImage(); } else { console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus); } @@ -64,7 +64,7 @@ Rectangle { if (!isLoggedIn && root.activeView !== "needsLogIn") { root.activeView = "needsLogIn"; } else if (isLoggedIn) { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -174,7 +174,7 @@ Rectangle { if (msg.method === 'walletSetup_finished') { if (msg.referrer === '') { root.activeView = "initialize"; - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } else if (msg.referrer === 'purchases') { sendToScript({method: 'goToPurchases'}); } else { @@ -254,7 +254,7 @@ Rectangle { color: hifi.colors.baseGray; Component.onCompleted: { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } } @@ -275,7 +275,7 @@ Rectangle { Connections { target: GlobalServices onMyUsernameChanged: { - commerce.getLoginStatus(); + Commerce.getLoginStatus(); } } @@ -289,7 +289,7 @@ Rectangle { Connections { onSendSignalToParent: { if (msg.method === "authSuccess") { - commerce.getWalletStatus(); + Commerce.getWalletStatus(); } else { sendToScript(msg); } diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 1fe0dcc58b..929dd1e7e8 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -28,8 +28,8 @@ Item { property bool historyReceived: false; property int pendingCount: 0; - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onBalanceResult : { balanceText.text = result.data.balance; @@ -116,8 +116,8 @@ Item { onVisibleChanged: { if (visible) { historyReceived = false; - commerce.balance(); - commerce.history(); + Commerce.balance(); + Commerce.history(); } else { refreshTimer.stop(); } @@ -147,8 +147,8 @@ Item { onTriggered: { console.log("Refreshing Wallet Home..."); historyReceived = false; - commerce.balance(); - commerce.history(); + Commerce.balance(); + Commerce.history(); } } diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml index 99fe933bd6..6672f4b97e 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml @@ -37,8 +37,8 @@ Item { source: "images/wallet-bg.jpg"; } - Hifi.QmlCommerce { - id: commerce; + Connections { + target: Commerce; onSecurityImageResult: { if (!exists && root.lastPage === "step_2") { @@ -356,7 +356,7 @@ Item { onClicked: { root.lastPage = "step_2"; var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex()) - commerce.chooseSecurityImage(securityImagePath); + Commerce.chooseSecurityImage(securityImagePath); root.activeView = "step_3"; passphraseSelection.clearPassphraseFields(); } @@ -440,7 +440,7 @@ Item { onVisibleChanged: { if (visible) { - commerce.getWalletAuthenticatedStatus(); + Commerce.getWalletAuthenticatedStatus(); if (!root.hasShownSecurityImageTip) { securityImageTip.visible = true; } @@ -529,7 +529,7 @@ Item { onClicked: { if (passphraseSelection.validateAndSubmitPassphrase()) { root.lastPage = "step_3"; - commerce.generateKeyPair(); + Commerce.generateKeyPair(); root.activeView = "step_4"; } } @@ -662,7 +662,7 @@ Item { onVisibleChanged: { if (visible) { - commerce.getKeyFilePathIfExists(); + Commerce.getKeyFilePathIfExists(); } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 87d4db9936..4f6e871d48 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2246,7 +2246,32 @@ void Application::initializeUi() { LoginDialog::registerType(); Tooltip::registerType(); UpdateDialog::registerType(); - QmlCommerce::registerType(); + QmlContextCallback callback = [](QQmlContext* context, QObject*) { + context->setContextProperty("Commerce", new QmlCommerce()); + }; + OffscreenQmlSurface::addWhitelistContextHandler({ + QUrl{ "qrc://qml/hifi/commerce/checkout/Checkout.qml" }, + QUrl{ "qrc://qml/hifi/commerce/common/CommerceLightbox.qml" }, + QUrl{ "qrc://qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, + QUrl{ "qrc://qml/hifi/commerce/common/FirstUseTutorial.qml" }, + QUrl{ "qrc://qml/hifi/commerce/common/SortableListModel.qml" }, + QUrl{ "qrc://qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, + QUrl{ "qrc://qml/hifi/commerce/purchases/PurchasedItem.qml" }, + QUrl{ "qrc://qml/hifi/commerce/purchases/Purchases.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/Help.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/NeedsLogIn.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/PassphraseChange.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/PassphraseModal.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/PassphraseSelection.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/Security.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/SecurityImageChange.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/SecurityImageModel.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/SecurityImageSelection.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/SendMoney.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/Wallet.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/WalletHome.qml" }, + QUrl{ "qrc://qml/hifi/commerce/wallet/WalletSetup.qml" }, + }, callback); qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType("Hifi", 1, 0, "Preference"); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 803264fa9f..ecce682896 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -16,9 +16,7 @@ #include "Wallet.h" #include -HIFI_QML_DEF(QmlCommerce) - -QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) { +QmlCommerce::QmlCommerce() { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index ae63133425..915edb71ef 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -16,16 +16,14 @@ #define hifi_QmlCommerce_h #include -#include #include -class QmlCommerce : public OffscreenQmlDialog { +class QmlCommerce : public QObject { Q_OBJECT - HIFI_QML_DECL public: - QmlCommerce(QQuickItem* parent = nullptr); + QmlCommerce(); signals: void walletStatusResult(uint walletStatus); diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 14d8ec8985..1758150e0a 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -62,7 +62,7 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) { QUrl url { properties[SOURCE_PROPERTY].toString() }; if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" && - url.scheme() != "atp") { + url.scheme() != "atp" && url.scheme() != "qrc") { properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString(); } diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 04b67ec14f..7b260dacfc 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -26,7 +26,7 @@ // Relevant Variables: // -WALLET_QML_SOURCE: The path to the Wallet QML // -onWalletScreen: true/false depending on whether we're looking at the app. - var WALLET_QML_SOURCE = Script.resourcesPath() + "qml/hifi/commerce/wallet/Wallet.qml"; + var WALLET_QML_SOURCE = "qrc:///qml/hifi/commerce/wallet/Wallet.qml"; var MARKETPLACE_PURCHASES_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/purchases/Purchases.qml"; var onWalletScreen = false; function onButtonClicked() { @@ -38,7 +38,11 @@ // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - tablet.loadQMLSource(WALLET_QML_SOURCE); + var window = new OverlayWindow({ + title: "Wallet", + source: WALLET_QML_SOURCE, + width: 480, height: 706 + }); } } From 5898f0bd0caadb5091f4e3247d8a7a89e0605772 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 25 Oct 2017 15:04:47 -0700 Subject: [PATCH 02/81] Gotta do some fancy stuff with anchors for this to work --- interface/resources/qml/hifi/commerce/wallet/Wallet.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml index 21bf7bace0..ce4400b33d 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml @@ -31,6 +31,8 @@ Rectangle { property bool keyboardRaised: false; property bool isPassword: false; + anchors.fill: (typeof parent === undefined) ? undefined : parent; + Image { anchors.fill: parent; source: "images/wallet-bg.jpg"; From a5caae373978f8317e28686b08bbe96fc22b3f7c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 25 Oct 2017 16:49:23 -0700 Subject: [PATCH 03/81] Modify QML context population order --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 29 ++++++++++----------- libraries/ui/src/ui/OffscreenQmlSurface.h | 15 ++++++----- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index ecd07a5874..cf746b26fd 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -98,7 +98,7 @@ void OffscreenQmlSurface::addWhitelistContextHandler(const std::initializer_list } -QmlContextCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QObject*) {}; +QmlContextObjectCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QObject*) {}; struct TextureSet { // The number of surfaces with this size @@ -688,7 +688,7 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) { _qmlContext->setBaseUrl(baseUrl); } -void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback) { if (QThread::currentThread() != thread()) { qCWarning(uiLogging) << "Called load on a non-surface thread"; } @@ -699,13 +699,16 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, con QList callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource); // If we have whitelisted content, we must load a new context createNewContext |= !callbacks.empty(); - callbacks.push_back(onQmlLoadedCallback); QQmlContext* targetContext = _qmlContext; if (_rootItem && createNewContext) { targetContext = new QQmlContext(targetContext); } + for (const auto& callback : callbacks) { + callback(targetContext); + } + // FIXME eliminate loading of relative file paths for QML QUrl finalQmlSource = qmlSource; @@ -716,23 +719,23 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, con auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); if (qmlComponent->isLoading()) { connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { - finishQmlLoad(qmlComponent, targetContext, callbacks); + finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback); }); return; } - finishQmlLoad(qmlComponent, targetContext, callbacks); + finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback); } -void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) { load(qmlSource, true, onQmlLoadedCallback); } -void OffscreenQmlSurface::load(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) { load(qmlSource, false, onQmlLoadedCallback); } -void OffscreenQmlSurface::load(const QString& qmlSourceFile, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::load(const QString& qmlSourceFile, const QmlContextObjectCallback& onQmlLoadedCallback) { return load(QUrl(qmlSourceFile), onQmlLoadedCallback); } @@ -740,7 +743,7 @@ void OffscreenQmlSurface::clearCache() { _qmlContext->engine()->clearComponentCache(); } -void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QList& callbacks) { +void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QmlContextObjectCallback& callback) { disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0); if (qmlComponent->isError()) { for (const auto& error : qmlComponent->errors()) { @@ -775,9 +778,7 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext // Make sure we will call callback for this codepath // Call this before qmlComponent->completeCreate() otherwise ghost window appears if (newItem && _rootItem) { - for (const auto& callback : callbacks) { - callback(qmlContext, newObject); - } + callback(qmlContext, newObject); } QObject* eventBridge = qmlContext->contextProperty("eventBridge").value(); @@ -814,9 +815,7 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext _rootItem->setSize(_quickWindow->renderTargetSize()); // Call this callback after rootitem is set, otherwise VrMenu wont work - for (const auto& callback : callbacks) { - callback(qmlContext, newObject); - } + callback(qmlContext, newObject); } void OffscreenQmlSurface::updateQuick() { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 12ee9e59a1..890a1d263c 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -35,7 +35,8 @@ class QQuickItem; // one copy in flight, and one copy being used by the receiver #define GPU_RESOURCE_BUFFER_SIZE 3 -using QmlContextCallback = std::function; +using QmlContextCallback = std::function; +using QmlContextObjectCallback = std::function; class OffscreenQmlSurface : public QObject { Q_OBJECT @@ -43,7 +44,7 @@ class OffscreenQmlSurface : public QObject { public: static void setSharedContext(QOpenGLContext* context); - static QmlContextCallback DEFAULT_CONTEXT_CALLBACK; + static QmlContextObjectCallback DEFAULT_CONTEXT_CALLBACK; static void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback); static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); }; @@ -56,10 +57,10 @@ public: void resize(const QSize& size, bool forceResize = false); QSize size() const; - Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); - Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); - Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); - Q_INVOKABLE void load(const QString& qmlSourceFile, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void load(const QString& qmlSourceFile, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); void clearCache(); void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; } // Optional values for event handling @@ -124,7 +125,7 @@ protected: private: static QOpenGLContext* getSharedContext(); - void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QList& callbacks); + void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QmlContextObjectCallback& callbacks); QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject); void setupFbo(); bool allowNewFrame(uint8_t fps); From 7027dbb8d4de70b680a09bf0048ad61060805f38 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 26 Oct 2017 10:48:26 -0700 Subject: [PATCH 04/81] Integrate Austin's changes --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dbc1d4cfbd..1de17b1568 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2251,7 +2251,7 @@ void Application::initializeUi() { LoginDialog::registerType(); Tooltip::registerType(); UpdateDialog::registerType(); - QmlContextCallback callback = [](QQmlContext* context, QObject*) { + QmlContextCallback callback = [](QQmlContext* context) { context->setContextProperty("Commerce", new QmlCommerce()); }; OffscreenQmlSurface::addWhitelistContextHandler({ From 40aa3b522c8edf06d9c683c1955bb36f0c0fe51f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 26 Oct 2017 10:59:18 -0700 Subject: [PATCH 05/81] Three slashes, not two --- interface/src/Application.cpp | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1de17b1568..d437b1532f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2255,27 +2255,27 @@ void Application::initializeUi() { context->setContextProperty("Commerce", new QmlCommerce()); }; OffscreenQmlSurface::addWhitelistContextHandler({ - QUrl{ "qrc://qml/hifi/commerce/checkout/Checkout.qml" }, - QUrl{ "qrc://qml/hifi/commerce/common/CommerceLightbox.qml" }, - QUrl{ "qrc://qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, - QUrl{ "qrc://qml/hifi/commerce/common/FirstUseTutorial.qml" }, - QUrl{ "qrc://qml/hifi/commerce/common/SortableListModel.qml" }, - QUrl{ "qrc://qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, - QUrl{ "qrc://qml/hifi/commerce/purchases/PurchasedItem.qml" }, - QUrl{ "qrc://qml/hifi/commerce/purchases/Purchases.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/Help.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/NeedsLogIn.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/PassphraseChange.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/PassphraseModal.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/PassphraseSelection.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/Security.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/SecurityImageChange.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/SecurityImageModel.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/SecurityImageSelection.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/SendMoney.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/Wallet.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/WalletHome.qml" }, - QUrl{ "qrc://qml/hifi/commerce/wallet/WalletSetup.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/checkout/Checkout.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/common/CommerceLightbox.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/common/FirstUseTutorial.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/common/SortableListModel.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/purchases/PurchasedItem.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/purchases/Purchases.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/Help.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/NeedsLogIn.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/PassphraseChange.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/PassphraseModal.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/PassphraseSelection.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/Security.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/SecurityImageChange.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/SecurityImageModel.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/SecurityImageSelection.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/SendMoney.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/Wallet.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/WalletHome.qml" }, + QUrl{ "qrc:///qml/hifi/commerce/wallet/WalletSetup.qml" }, }, callback); qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType("Hifi", 1, 0, "Preference"); From ffc51d5387a350a9d24d4c9430dfafc1ed0d74eb Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 26 Oct 2017 14:20:13 -0700 Subject: [PATCH 06/81] Working on QML whitelist functionality --- interface/resources/qml/OverlayWindowTest.qml | 18 +++ interface/resources/qml/QmlWindow.qml | 30 ++--- interface/src/Application.cpp | 6 + libraries/ui/src/QmlWindowClass.cpp | 2 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 109 ++++++++++++------ libraries/ui/src/ui/OffscreenQmlSurface.h | 8 +- scripts/developer/tests/qmlTest.js | 2 +- 7 files changed, 113 insertions(+), 62 deletions(-) create mode 100644 interface/resources/qml/OverlayWindowTest.qml diff --git a/interface/resources/qml/OverlayWindowTest.qml b/interface/resources/qml/OverlayWindowTest.qml new file mode 100644 index 0000000000..7b82b2f705 --- /dev/null +++ b/interface/resources/qml/OverlayWindowTest.qml @@ -0,0 +1,18 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Rectangle { + width: 100 + height: 100 + color: "white" + Rectangle { + width: 10 + height: 10 + color: "red" + } + + Label { + text: OverlayWindowTestString + anchors.centerIn: parent + } +} diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index 9a84418b3a..23b435074d 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -22,7 +22,6 @@ Windows.Window { // Don't destroy on close... otherwise the JS/C++ will have a dangling pointer destroyOnCloseButton: false property var source; - property var component; property var dynamicContent; // Keyboard control properties in case needed by QML content. @@ -35,28 +34,13 @@ Windows.Window { dynamicContent.destroy(); dynamicContent = null; } - component = Qt.createComponent(source); - console.log("Created component " + component + " from source " + source); - } - - onComponentChanged: { - console.log("Component changed to " + component) - populate(); - } - - function populate() { - console.log("Populate called: dynamicContent " + dynamicContent + " component " + component); - if (!dynamicContent && component) { - if (component.status == Component.Error) { - console.log("Error loading component:", component.errorString()); - } else if (component.status == Component.Ready) { - console.log("Building dynamic content"); - dynamicContent = component.createObject(contentHolder); - } else { - console.log("Component not yet ready, connecting to status change"); - component.statusChanged.connect(populate); - } - } + console.log("QQQ Foo"); + QmlSurface.createContentFromQml(source, contentHolder, function(newObject) { + console.log("QQQ Bar " + dynamicContent); + dynamicContent = newObject; + dynamicContent.visible = true; + }); + console.log("QQQ Baz"); } // Handle message traffic from the script that launched us to the loaded QML diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 87d4db9936..deb4963ff4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2240,6 +2240,12 @@ extern void setupPreferences(); void Application::initializeUi() { // Make sure all QML surfaces share the main thread GL context OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext()); + OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "qrc:///qml/OverlayWindowTest.qml" }, + [](QQmlContext* context) { + qDebug() << "Whitelist OverlayWindow worked"; + context->setContextProperty("OverlayWindowTestString", "TestWorked"); + }); + AddressBarDialog::registerType(); ErrorDialog::registerType(); diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 14d8ec8985..1758150e0a 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -62,7 +62,7 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) { QUrl url { properties[SOURCE_PROPERTY].toString() }; if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" && - url.scheme() != "atp") { + url.scheme() != "atp" && url.scheme() != "qrc") { properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString(); } diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index cf746b26fd..5ef804330b 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -64,11 +64,19 @@ public: for (const auto& url : urls) { _callbacks[url].push_back(callback); } + for (const auto& url : _callbacks.keys()) { + qDebug() << "URL found for " << url << " with " << _callbacks[url].size() << " items"; + } }); } QList getCallbacksForUrl(const QUrl& url) const { + qDebug() << "Looking for callbacks for " << url; + return resultWithReadLock>([&] { + for (const auto& url : _callbacks.keys()) { + qDebug() << "URL found for " << url << " with " << _callbacks[url].size() << " items"; + } QList result; auto itr = _callbacks.find(url); if (_callbacks.end() != itr) { @@ -98,7 +106,7 @@ void OffscreenQmlSurface::addWhitelistContextHandler(const std::initializer_list } -QmlContextObjectCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QObject*) {}; +QmlContextObjectCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QQuickItem*) {}; struct TextureSet { // The number of surfaces with this size @@ -590,6 +598,7 @@ void OffscreenQmlSurface::create() { _qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); _qmlContext->setContextProperty("eventBridge", this); _qmlContext->setContextProperty("webEntity", this); + _qmlContext->setContextProperty("QmlSurface", this); // FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper // Find a way to flag older scripts using this mechanism and wanr that this is deprecated @@ -688,20 +697,14 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) { _qmlContext->setBaseUrl(baseUrl); } -void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback) { - if (QThread::currentThread() != thread()) { - qCWarning(uiLogging) << "Called load on a non-surface thread"; - } - // Synchronous loading may take a while; restart the deadlock timer - QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection); - +QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, bool forceNewContext) { // Get any whitelist functionality QList callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource); // If we have whitelisted content, we must load a new context - createNewContext |= !callbacks.empty(); + forceNewContext |= !callbacks.empty(); QQmlContext* targetContext = _qmlContext; - if (_rootItem && createNewContext) { + if (_rootItem && forceNewContext) { targetContext = new QQmlContext(targetContext); } @@ -709,6 +712,15 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, con callback(targetContext); } + return targetContext; +} + +void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback) { + if (QThread::currentThread() != thread()) { + qCWarning(uiLogging) << "Called load on a non-surface thread"; + } + // Synchronous loading may take a while; restart the deadlock timer + QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection); // FIXME eliminate loading of relative file paths for QML QUrl finalQmlSource = qmlSource; @@ -716,17 +728,36 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, con finalQmlSource = _qmlContext->resolvedUrl(qmlSource); } + auto targetContext = contextForUrl(finalQmlSource); auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); if (qmlComponent->isLoading()) { connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { - finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback); + finishQmlLoad(qmlComponent, targetContext, nullptr, onQmlLoadedCallback); }); return; } - finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback); + finishQmlLoad(qmlComponent, targetContext, nullptr, onQmlLoadedCallback); } +void OffscreenQmlSurface::createContentFromQml(const QUrl& qmlSource, QQuickItem* parent, const QJSValue& callback) { + auto targetContext = contextForUrl(qmlSource); + + auto onQmlLoadedCallback = [=](QQmlContext*, QObject* newItem) { + QJSValue(callback).call(QJSValueList() << _qmlContext->engine()->newQObject(newItem)); + }; + + auto qmlComponent = new QQmlComponent(_qmlContext->engine(), qmlSource, QQmlComponent::PreferSynchronous); + if (qmlComponent->isLoading()) { + connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { + finishQmlLoad(qmlComponent, targetContext, parent, onQmlLoadedCallback); + }); + return; + } + finishQmlLoad(qmlComponent, targetContext, parent, onQmlLoadedCallback); +} + + void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) { load(qmlSource, true, onQmlLoadedCallback); } @@ -743,7 +774,8 @@ void OffscreenQmlSurface::clearCache() { _qmlContext->engine()->clearComponentCache(); } -void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QmlContextObjectCallback& callback) { + +void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& callback) { disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0); if (qmlComponent->isError()) { for (const auto& error : qmlComponent->errors()) { @@ -765,6 +797,22 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext return; } + if (!newObject) { + if (!_rootItem) { + qFatal("Could not load object as root item"); + return; + } + qCWarning(uiLogging) << "Unable to load QML item"; + return; + } + + QObject* eventBridge = qmlContext->contextProperty("eventBridge").value(); + if (qmlContext != _qmlContext && eventBridge && eventBridge != this) { + // FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper + // Find a way to flag older scripts using this mechanism and wanr that this is deprecated + qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext)); + } + qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership); // All quick items should be focusable @@ -775,35 +823,26 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext newItem->setFlag(QQuickItem::ItemIsFocusScope, true); } + // Make sure we will call callback for this codepath // Call this before qmlComponent->completeCreate() otherwise ghost window appears - if (newItem && _rootItem) { - callback(qmlContext, newObject); - } + // If we already have a root, just set a couple of flags and the ancestry + if (_rootItem) { + callback(qmlContext, newItem); - QObject* eventBridge = qmlContext->contextProperty("eventBridge").value(); - if (qmlContext != _qmlContext && eventBridge && eventBridge != this) { - // FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper - // Find a way to flag older scripts using this mechanism and wanr that this is deprecated - qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext)); + if (!parent) { + parent = _rootItem; + } + // Allow child windows to be destroyed from JS + QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership); + newObject->setParent(parent); + newItem->setParentItem(parent); } qmlComponent->completeCreate(); qmlComponent->deleteLater(); - // If we already have a root, just set a couple of flags and the ancestry - if (newItem && _rootItem) { - // Allow child windows to be destroyed from JS - QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership); - newObject->setParent(_rootItem); - if (newItem) { - newItem->setParentItem(_rootItem); - } - return; - } - - if (!newItem) { - qFatal("Could not load object as root item"); + if (_rootItem) { return; } @@ -815,7 +854,7 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext _rootItem->setSize(_quickWindow->renderTargetSize()); // Call this callback after rootitem is set, otherwise VrMenu wont work - callback(qmlContext, newObject); + callback(qmlContext, newItem); } void OffscreenQmlSurface::updateQuick() { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 890a1d263c..185630905d 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -30,13 +30,14 @@ class QQmlContext; class QQmlComponent; class QQuickWindow; class QQuickItem; +class QJSValue; // GPU resources are typically buffered for one copy being used by the renderer, // one copy in flight, and one copy being used by the receiver #define GPU_RESOURCE_BUFFER_SIZE 3 using QmlContextCallback = std::function; -using QmlContextObjectCallback = std::function; +using QmlContextObjectCallback = std::function; class OffscreenQmlSurface : public QObject { Q_OBJECT @@ -57,6 +58,8 @@ public: void resize(const QSize& size, bool forceResize = false); QSize size() const; + Q_INVOKABLE void createContentFromQml(const QUrl& qmlSource, QQuickItem* parent, const QJSValue& callback); + Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); @@ -123,9 +126,10 @@ protected: void setFocusText(bool newFocusText); private: + QQmlContext* contextForUrl(const QUrl& url, bool forceNewContext = false); static QOpenGLContext* getSharedContext(); - void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QmlContextObjectCallback& callbacks); + void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& callbacks); QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject); void setupFbo(); bool allowNewFrame(uint8_t fps); diff --git a/scripts/developer/tests/qmlTest.js b/scripts/developer/tests/qmlTest.js index c891b6a1b7..0eaabac6d1 100644 --- a/scripts/developer/tests/qmlTest.js +++ b/scripts/developer/tests/qmlTest.js @@ -1,7 +1,7 @@ print("Launching web window"); qmlWindow = new OverlayWindow({ title: 'Test Qml', - source: "https://s3.amazonaws.com/DreamingContent/qml/content.qml", + source: "qrc:///qml/OverlayWindowTest.qml", height: 240, width: 320, toolWindow: false, From d162e1cff67c870516fb34672e59e82f99015050 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 25 Oct 2017 16:49:23 -0700 Subject: [PATCH 07/81] Whitelist functionality for tablet apps --- interface/resources/qml/OverlayWindowTest.qml | 18 +++ interface/resources/qml/QmlWindow.qml | 26 +--- .../resources/qml/hifi/tablet/Tablet.qml | 35 +++-- .../resources/qml/hifi/tablet/TabletRoot.qml | 122 ++++++++++------- interface/src/Application.cpp | 24 +++- interface/src/Menu.cpp | 4 +- .../scripting/WalletScriptingInterface.cpp | 4 +- interface/src/ui/DialogsManager.cpp | 4 +- interface/src/ui/LoginDialog.cpp | 2 +- .../ui/overlays/ContextOverlayInterface.cpp | 2 +- .../src/RenderableWebEntityItem.cpp | 7 +- libraries/ui/src/QmlWindowClass.cpp | 2 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 128 +++++++++++------- libraries/ui/src/ui/OffscreenQmlSurface.h | 26 ++-- .../ui/src/ui/OffscreenQmlSurfaceCache.cpp | 1 - .../ui/src/ui/TabletScriptingInterface.cpp | 65 +++------ .../ui/src/ui/TabletScriptingInterface.h | 8 +- scripts/developer/inputRecording.js | 2 +- scripts/developer/tests/qmlTest.js | 2 +- scripts/system/audio.js | 2 +- scripts/system/commerce/wallet.js | 4 +- scripts/system/edit.js | 2 +- scripts/system/generalSettings.js | 2 +- scripts/system/marketplaces/marketplaces.js | 2 +- scripts/system/pal.js | 2 +- scripts/system/tablet-goto.js | 2 +- .../skyboxChanger/skyboxchanger.js | 2 +- .../spectator-camera/spectatorCamera.js | 2 +- 28 files changed, 284 insertions(+), 218 deletions(-) create mode 100644 interface/resources/qml/OverlayWindowTest.qml diff --git a/interface/resources/qml/OverlayWindowTest.qml b/interface/resources/qml/OverlayWindowTest.qml new file mode 100644 index 0000000000..7b82b2f705 --- /dev/null +++ b/interface/resources/qml/OverlayWindowTest.qml @@ -0,0 +1,18 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Rectangle { + width: 100 + height: 100 + color: "white" + Rectangle { + width: 10 + height: 10 + color: "red" + } + + Label { + text: OverlayWindowTestString + anchors.centerIn: parent + } +} diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index 9a84418b3a..7c1ce704c3 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -22,7 +22,6 @@ Windows.Window { // Don't destroy on close... otherwise the JS/C++ will have a dangling pointer destroyOnCloseButton: false property var source; - property var component; property var dynamicContent; // Keyboard control properties in case needed by QML content. @@ -35,28 +34,9 @@ Windows.Window { dynamicContent.destroy(); dynamicContent = null; } - component = Qt.createComponent(source); - console.log("Created component " + component + " from source " + source); - } - - onComponentChanged: { - console.log("Component changed to " + component) - populate(); - } - - function populate() { - console.log("Populate called: dynamicContent " + dynamicContent + " component " + component); - if (!dynamicContent && component) { - if (component.status == Component.Error) { - console.log("Error loading component:", component.errorString()); - } else if (component.status == Component.Ready) { - console.log("Building dynamic content"); - dynamicContent = component.createObject(contentHolder); - } else { - console.log("Component not yet ready, connecting to status change"); - component.statusChanged.connect(populate); - } - } + QmlSurface.load(source, contentHolder, function(newObject) { + dynamicContent = newObject; + }); } // Handle message traffic from the script that launched us to the loaded QML diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml index 66e3dfdbbb..b21bf9c506 100644 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ b/interface/resources/qml/hifi/tablet/Tablet.qml @@ -2,6 +2,7 @@ import QtQuick 2.5 import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.3 +import "." import "../../styles-uit" import "../audio" as HifiAudio @@ -12,6 +13,31 @@ Item { property int columnIndex: 0 property int count: (flowMain.children.length - 1) + Component { + id: buttonComponent + TabletButton { } + } + + Component.onCompleted: { + tablet.populateButtons(); + } + + function createClickedHandler(proxy) { + return function() { proxy.clicked(); } + } + + function populateButtons() { + var tabletProxy = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var buttons = tabletProxy.getButtons(); + for (var i = 0; i < buttons.length; i++) { + var proxy = buttons[i]; + var button = tablet.addButtonProxy(proxy.getProperties()); + button.clicked.connect(createClickedHandler(proxy)); + proxy.setQmlButton(button); + } + sortButtons(); + } + // used to look up a button by its uuid function findButtonIndex(uuid) { if (!uuid) { @@ -47,9 +73,7 @@ Item { // called by C++ code when a button should be added to the tablet function addButtonProxy(properties) { - var component = Qt.createComponent("TabletButton.qml"); - var button = component.createObject(flowMain); - + var button = buttonComponent.createObject(flowMain); // copy all properites to button var keys = Object.keys(properties).forEach(function (key) { button[key] = properties[key]; @@ -62,8 +86,6 @@ Item { button.tabletRoot = parent.parent; } - sortButtons(); - return button; } @@ -83,11 +105,8 @@ Item { anchors { top: parent.top - topMargin: 0 left: parent.left - leftMargin: 0 right: parent.right - rightMargin: 0 } gradient: Gradient { diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index a161741049..028ac2d8b6 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -68,18 +68,17 @@ Item { function loadSource(url) { tabletApps.clear(); - loader.source = ""; // make sure we load the qml fresh each time. - loader.source = url; - tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); + loader.load(url) + tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); } function loadQMLOnTop(url) { tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); - loader.source = ""; - loader.source = tabletApps.get(currentApp).appUrl; - if (loader.item.hasOwnProperty("gotoPreviousApp")) { - loader.item.gotoPreviousApp = true; - } + loader.load(tabletApps.get(currentApp).appUrl, function(){ + if (loader.item.hasOwnProperty("gotoPreviousApp")) { + loader.item.gotoPreviousApp = true; + } + }) } function loadWebOnTop(url, injectJavaScriptUrl) { @@ -92,13 +91,11 @@ Item { } function loadWebBase() { - loader.source = ""; - loader.source = "TabletWebView.qml"; + loader.load("hifi/tablet/TabletWebView.qml"); } function loadTabletWebBase() { - loader.source = ""; - loader.source = "./BlocksWebView.qml"; + loader.load("hifi/tablet/BlocksWebView.qml"); } function returnToPreviousApp() { @@ -110,7 +107,7 @@ Item { loadSource("TabletWebView.qml"); loadWebUrl(webUrl, scriptUrl); } else { - loader.source = tabletApps.get(currentApp).appUrl; + loader.load(tabletApps.get(currentApp).appUrl); } } @@ -173,47 +170,72 @@ Item { } } - Loader { - id: loader - objectName: "loader" - asynchronous: false - - width: parent.width - height: parent.height - - // Hook up callback for clara.io download from the marketplace. - Connections { - id: eventBridgeConnection - target: eventBridge - onWebEventReceived: { - if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") { - ApplicationInterface.addAssetToWorldFromURL(message.slice(18)); - } - } - } - - onLoaded: { - if (loader.item.hasOwnProperty("sendToScript")) { - loader.item.sendToScript.connect(tabletRoot.sendToScript); - } - if (loader.item.hasOwnProperty("setRootMenu")) { - loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu); - } - loader.item.forceActiveFocus(); - - if (openModal) { - openModal.canceled(); - openModal.destroy(); - openModal = null; - } - - if (openBrowser) { - openBrowser.destroy(); - openBrowser = null; + // Hook up callback for clara.io download from the marketplace. + Connections { + id: eventBridgeConnection + target: eventBridge + onWebEventReceived: { + if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") { + ApplicationInterface.addAssetToWorldFromURL(message.slice(18)); } } } + Item { + id: loader + objectName: "loader"; + anchors.fill: parent; + property string source: ""; + property var item: null; + signal loaded; + + onWidthChanged: { + if (loader.item) { + loader.item.width = loader.width; + } + } + + onHeightChanged: { + if (loader.item) { + loader.item.height = loader.height; + } + } + + function load(newSource, callback) { + loader.source = newSource; + loader.item = null; + QmlSurface.load(newSource, loader, function(newItem) { + loader.item = newItem; + loader.item.width = loader.width; + loader.item.height = loader.height; + loader.loaded(); + if (loader.item.hasOwnProperty("sendToScript")) { + loader.item.sendToScript.connect(tabletRoot.sendToScript); + } + if (loader.item.hasOwnProperty("setRootMenu")) { + loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu); + } + loader.item.forceActiveFocus(); + + if (openModal) { + openModal.canceled(); + openModal.destroy(); + openModal = null; + } + + if (openBrowser) { + openBrowser.destroy(); + openBrowser = null; + } + + if (callback) { + callback(); + } + }); + console.log("QQQ done calling QmlSurface.load") + } + } + width: 480 height: 706 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4f051697ad..8689b167c9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2214,6 +2214,16 @@ extern void setupPreferences(); void Application::initializeUi() { // Make sure all QML surfaces share the main thread GL context OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext()); + OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "qrc:///qml/OverlayWindowTest.qml" }, + [](QQmlContext* context) { + qDebug() << "Whitelist OverlayWindow worked"; + context->setContextProperty("OverlayWindowTestString", "TestWorked"); + }); + OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "qrc:///qml/hifi/audio/Audio.qml" }, + [](QQmlContext* context) { + qDebug() << "QQQ" << __FUNCTION__ << "Whitelist Audio worked"; + }); + AddressBarDialog::registerType(); ErrorDialog::registerType(); @@ -2230,10 +2240,9 @@ void Application::initializeUi() { auto surfaceContext = offscreenUi->getSurfaceContext(); offscreenUi->setProxyWindow(_window->windowHandle()); - offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // support the window management and scripting proxies for VR use - offscreenUi->createDesktop(QString("qrc:///qml/hifi/Desktop.qml")); + offscreenUi->createDesktop(QString("hifi/Desktop.qml")); // FIXME either expose so that dialogs can set this themselves or // do better detection in the offscreen UI of what has focus @@ -7194,13 +7203,17 @@ void Application::updateDisplayMode() { } auto offscreenUi = DependencyManager::get(); + auto desktop = offscreenUi->getDesktop(); // Make the switch atomic from the perspective of other threads { std::unique_lock lock(_displayPluginLock); - // Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below. - bool wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool(); - offscreenUi->getDesktop()->setProperty("repositionLocked", true); + bool wasRepositionLocked = false; + if (desktop) { + // Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below. + wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool(); + offscreenUi->getDesktop()->setProperty("repositionLocked", true); + } if (_displayPlugin) { disconnect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent); @@ -7246,7 +7259,6 @@ void Application::updateDisplayMode() { getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); - auto desktop = offscreenUi->getDesktop(); if (desktop) { desktop->setProperty("repositionLocked", wasRepositionLocked); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9df22ab08e..7025022c0a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -101,7 +101,7 @@ Menu::Menu() { auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J); connect(action, &QAction::triggered, [] { static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml"); - static const QUrl tabletUrl("../../hifi/dialogs/TabletRunningScripts.qml"); + static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml"); static const QString name("RunningScripts"); qApp->showDialog(widgetUrl, tabletUrl, name); }); @@ -338,7 +338,7 @@ Menu::Menu() { connect(action, &QAction::triggered, [] { auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); auto hmd = DependencyManager::get(); - tablet->loadQMLSource("ControllerSettings.qml"); + tablet->loadQMLSource("hifi/tablet/ControllerSettings.qml"); if (!hmd->getShouldShowTablet()) { hmd->toggleShouldShowTablet(); diff --git a/interface/src/scripting/WalletScriptingInterface.cpp b/interface/src/scripting/WalletScriptingInterface.cpp index 99fdd5fbde..c866bac2b2 100644 --- a/interface/src/scripting/WalletScriptingInterface.cpp +++ b/interface/src/scripting/WalletScriptingInterface.cpp @@ -1,4 +1,4 @@ -// +// // WalletScriptingInterface.cpp // interface/src/scripting // @@ -23,7 +23,7 @@ void WalletScriptingInterface::refreshWalletStatus() { wallet->getWalletStatus(); } -static const QString CHECKOUT_QML_PATH = qApp->applicationDirPath() + "../../../qml/hifi/commerce/checkout/Checkout.qml"; +static const QString CHECKOUT_QML_PATH = "hifi/commerce/checkout/Checkout.qml"; void WalletScriptingInterface::buy(const QString& name, const QString& id, const int& price, const QString& href) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "buy", Q_ARG(const QString&, name), Q_ARG(const QString&, id), Q_ARG(const int&, price), Q_ARG(const QString&, href)); diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index f216bb4edc..ff2d4868df 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -31,7 +31,7 @@ #include "scripting/HMDScriptingInterface.h" -static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml"; +static const QVariant TABLET_ADDRESS_DIALOG = "hifi/tablet/TabletAddressDialog.qml"; template void DialogsManager::maybeCreateDialog(QPointer& member) { if (!member) { @@ -91,7 +91,7 @@ void DialogsManager::setDomainConnectionFailureVisibility(bool visible) { ConnectionFailureDialog::hide(); } } else { - static const QUrl url("../../dialogs/TabletConnectionFailureDialog.qml"); + static const QUrl url("dialogs/TabletConnectionFailureDialog.qml"); auto hmd = DependencyManager::get(); if (visible) { tablet->initialScreen(url); diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 7ce2a0146d..2e40d3c087 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -46,7 +46,7 @@ void LoginDialog::showWithSelection() if (tablet->getToolbarMode()) { LoginDialog::show(); } else { - static const QUrl url("../../dialogs/TabletLoginDialog.qml"); + static const QUrl url("dialogs/TabletLoginDialog.qml"); tablet->initialScreen(url); if (!hmd->getShouldShowTablet()) { hmd->openTablet(); diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index b5af529f2b..a8d0c3cc54 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -264,7 +264,7 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemI } } -static const QString INSPECTION_CERTIFICATE_QML_PATH = qApp->applicationDirPath() + "../../../qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml"; +static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertificate/InspectionCertificate.qml"; void ContextOverlayInterface::openInspectionCertificate() { // lets open the tablet to the inspection certificate QML if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index a2e574a829..d8e1fa7cf1 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -30,6 +30,8 @@ using namespace render; using namespace render::entities; +static const QString WEB_ENTITY_QML = "controls/WebEntityView.qml"; + const float METERS_TO_INCHES = 39.3701f; static uint32_t _currentWebCount{ 0 }; // Don't allow more than 100 concurrent web views @@ -218,6 +220,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { }; { + // FIXME use the surface cache instead of explicit creation _webSurface = QSharedPointer(new OffscreenQmlSurface(), deleter); _webSurface->create(); } @@ -289,7 +292,6 @@ void WebEntityRenderer::loadSourceURL() { if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || _lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) { _contentType = htmlContent; - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/")); // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) { @@ -298,12 +300,11 @@ void WebEntityRenderer::loadSourceURL() { _webSurface->setMaxFps(DEFAULT_MAX_FPS); } - _webSurface->load("WebEntityView.qml", [this](QQmlContext* context, QObject* item) { + _webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) { item->setProperty("url", _lastSourceUrl); }); } else { _contentType = qmlContent; - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); _webSurface->load(_lastSourceUrl); if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { auto tabletScriptingInterface = DependencyManager::get(); diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 14d8ec8985..1758150e0a 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -62,7 +62,7 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) { QUrl url { properties[SOURCE_PROPERTY].toString() }; if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" && - url.scheme() != "atp") { + url.scheme() != "atp" && url.scheme() != "qrc") { properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString(); } diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index ecd07a5874..8711e52eff 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -47,6 +47,7 @@ #include "types/HFWebEngineProfile.h" #include "types/SoundEffect.h" +#include "TabletScriptingInterface.h" #include "Logging.h" Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml") @@ -98,7 +99,7 @@ void OffscreenQmlSurface::addWhitelistContextHandler(const std::initializer_list } -QmlContextCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QObject*) {}; +QmlContextObjectCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QQuickItem*) {}; struct TextureSet { // The number of surfaces with this size @@ -586,10 +587,11 @@ void OffscreenQmlSurface::create() { auto qmlEngine = acquireEngine(_quickWindow); _qmlContext = new QQmlContext(qmlEngine->rootContext()); - + _qmlContext->setBaseUrl(QUrl{ "qrc:///qml/" }); _qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); _qmlContext->setContextProperty("eventBridge", this); _qmlContext->setContextProperty("webEntity", this); + _qmlContext->setContextProperty("QmlSurface", this); // FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper // Find a way to flag older scripts using this mechanism and wanr that this is deprecated @@ -684,55 +686,69 @@ QQuickItem* OffscreenQmlSurface::getRootItem() { return _rootItem; } -void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) { - _qmlContext->setBaseUrl(baseUrl); +QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, bool forceNewContext) { + // Get any whitelist functionality + QList callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource); + // If we have whitelisted content, we must load a new context + forceNewContext |= !callbacks.empty(); + + QQmlContext* targetContext = _qmlContext; + if (_rootItem && forceNewContext) { + targetContext = new QQmlContext(targetContext); + } + + for (const auto& callback : callbacks) { + callback(targetContext); + } + + return targetContext; } -void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::load(const QUrl& qmlSource, QQuickItem* parent, const QJSValue& callback) { + loadInternal(qmlSource, false, parent, [callback](QQmlContext* context, QQuickItem* newItem) { + QJSValue(callback).call(QJSValueList() << context->engine()->newQObject(newItem)); + }); +} + +void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback) { + loadInternal(qmlSource, createNewContext, nullptr, onQmlLoadedCallback); +} + +void OffscreenQmlSurface::loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback) { + qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << qmlSource; if (QThread::currentThread() != thread()) { qCWarning(uiLogging) << "Called load on a non-surface thread"; } // Synchronous loading may take a while; restart the deadlock timer QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection); - // Get any whitelist functionality - QList callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource); - // If we have whitelisted content, we must load a new context - createNewContext |= !callbacks.empty(); - callbacks.push_back(onQmlLoadedCallback); - - QQmlContext* targetContext = _qmlContext; - if (_rootItem && createNewContext) { - targetContext = new QQmlContext(targetContext); - } - - - // FIXME eliminate loading of relative file paths for QML QUrl finalQmlSource = qmlSource; if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) { finalQmlSource = _qmlContext->resolvedUrl(qmlSource); + qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << "resolved to " << finalQmlSource; } + auto targetContext = contextForUrl(finalQmlSource, createNewContext); auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); if (qmlComponent->isLoading()) { connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { - finishQmlLoad(qmlComponent, targetContext, callbacks); + finishQmlLoad(qmlComponent, targetContext, parent, onQmlLoadedCallback); }); return; } - finishQmlLoad(qmlComponent, targetContext, callbacks); + finishQmlLoad(qmlComponent, targetContext, parent, onQmlLoadedCallback); } -void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) { load(qmlSource, true, onQmlLoadedCallback); } -void OffscreenQmlSurface::load(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) { load(qmlSource, false, onQmlLoadedCallback); } -void OffscreenQmlSurface::load(const QString& qmlSourceFile, const QmlContextCallback& onQmlLoadedCallback) { +void OffscreenQmlSurface::load(const QString& qmlSourceFile, const QmlContextObjectCallback& onQmlLoadedCallback) { return load(QUrl(qmlSourceFile), onQmlLoadedCallback); } @@ -740,7 +756,8 @@ void OffscreenQmlSurface::clearCache() { _qmlContext->engine()->clearComponentCache(); } -void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QList& callbacks) { + +void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& callback) { disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0); if (qmlComponent->isError()) { for (const auto& error : qmlComponent->errors()) { @@ -762,6 +779,22 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext return; } + if (!newObject) { + if (!_rootItem) { + qFatal("Could not load object as root item"); + return; + } + qCWarning(uiLogging) << "Unable to load QML item"; + return; + } + + QObject* eventBridge = qmlContext->contextProperty("eventBridge").value(); + if (qmlContext != _qmlContext && eventBridge && eventBridge != this) { + // FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper + // Find a way to flag older scripts using this mechanism and wanr that this is deprecated + qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext)); + } + qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership); // All quick items should be focusable @@ -772,37 +805,26 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext newItem->setFlag(QQuickItem::ItemIsFocusScope, true); } + // Make sure we will call callback for this codepath // Call this before qmlComponent->completeCreate() otherwise ghost window appears - if (newItem && _rootItem) { - for (const auto& callback : callbacks) { - callback(qmlContext, newObject); - } - } + // If we already have a root, just set a couple of flags and the ancestry + if (_rootItem) { + callback(qmlContext, newItem); - QObject* eventBridge = qmlContext->contextProperty("eventBridge").value(); - if (qmlContext != _qmlContext && eventBridge && eventBridge != this) { - // FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper - // Find a way to flag older scripts using this mechanism and wanr that this is deprecated - qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext)); + if (!parent) { + parent = _rootItem; + } + // Allow child windows to be destroyed from JS + QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership); + newObject->setParent(parent); + newItem->setParentItem(parent); } qmlComponent->completeCreate(); qmlComponent->deleteLater(); - // If we already have a root, just set a couple of flags and the ancestry - if (newItem && _rootItem) { - // Allow child windows to be destroyed from JS - QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership); - newObject->setParent(_rootItem); - if (newItem) { - newItem->setParentItem(_rootItem); - } - return; - } - - if (!newItem) { - qFatal("Could not load object as root item"); + if (_rootItem) { return; } @@ -813,10 +835,16 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext _rootItem->setParentItem(_quickWindow->contentItem()); _rootItem->setSize(_quickWindow->renderTargetSize()); - // Call this callback after rootitem is set, otherwise VrMenu wont work - for (const auto& callback : callbacks) { - callback(qmlContext, newObject); + if (_rootItem->objectName() == "tabletRoot") { + _qmlContext->setContextProperty("tabletRoot", QVariant::fromValue(_rootItem)); + auto tabletScriptingInterface = DependencyManager::get(); + tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", this); + QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); + _qmlContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } + + // Call this callback after rootitem is set, otherwise VrMenu wont work + callback(qmlContext, newItem); } void OffscreenQmlSurface::updateQuick() { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 12ee9e59a1..2d2eb0811b 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -30,12 +30,14 @@ class QQmlContext; class QQmlComponent; class QQuickWindow; class QQuickItem; +class QJSValue; // GPU resources are typically buffered for one copy being used by the renderer, // one copy in flight, and one copy being used by the receiver #define GPU_RESOURCE_BUFFER_SIZE 3 -using QmlContextCallback = std::function; +using QmlContextCallback = std::function; +using QmlContextObjectCallback = std::function; class OffscreenQmlSurface : public QObject { Q_OBJECT @@ -43,7 +45,7 @@ class OffscreenQmlSurface : public QObject { public: static void setSharedContext(QOpenGLContext* context); - static QmlContextCallback DEFAULT_CONTEXT_CALLBACK; + static QmlContextObjectCallback DEFAULT_CONTEXT_CALLBACK; static void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback); static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); }; @@ -56,10 +58,15 @@ public: void resize(const QSize& size, bool forceResize = false); QSize size() const; - Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); - Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); - Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); - Q_INVOKABLE void load(const QString& qmlSourceFile, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + // Usable from QML code as QmlSurface.load(url, parent, function(newItem){ ... }) + Q_INVOKABLE void load(const QUrl& qmlSource, QQuickItem* parent, const QJSValue& callback); + + // For C++ use + Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + Q_INVOKABLE void load(const QString& qmlSourceFile, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK); + void clearCache(); void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; } // Optional values for event handling @@ -73,7 +80,6 @@ public: void resume(); bool isPaused() const; - void setBaseUrl(const QUrl& baseUrl); QQuickItem* getRootItem(); QQuickWindow* getWindow(); QObject* getEventHandler(); @@ -124,13 +130,13 @@ protected: private: static QOpenGLContext* getSharedContext(); - void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QList& callbacks); + QQmlContext* contextForUrl(const QUrl& url, bool forceNewContext = false); + void loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback); + void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback); QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject); - void setupFbo(); bool allowNewFrame(uint8_t fps); void render(); void cleanup(); - QJsonObject getGLContextData(); private slots: void updateQuick(); diff --git a/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp b/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp index 2a0ca4a2e9..9b6b031dd9 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp @@ -45,7 +45,6 @@ void OffscreenQmlSurfaceCache::release(const QString& rootSource, const QSharedP QSharedPointer OffscreenQmlSurfaceCache::buildSurface(const QString& rootSource) { auto surface = QSharedPointer(new OffscreenQmlSurface()); surface->create(); - surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); surface->load(rootSource); surface->resize(QSize(100, 100)); return surface; diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index b9da230715..a261ae45b1 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -210,9 +210,9 @@ QObject* TabletScriptingInterface::getFlags() { // TabletProxy // -static const char* TABLET_SOURCE_URL = "Tablet.qml"; -static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; -static const char* VRMENU_SOURCE_URL = "TabletMenu.qml"; +static const char* TABLET_SOURCE_URL = "hifi/tablet/Tablet.qml"; +static const char* WEB_VIEW_SOURCE_URL = "hifi/tablet/TabletWebView.qml"; +static const char* VRMENU_SOURCE_URL = "hifi/tablet/TabletMenu.qml"; class TabletRootWindow : public QmlWindowClass { virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; } @@ -232,6 +232,15 @@ TabletProxy::~TabletProxy() { disconnect(this, &TabletProxy::tabletShownChanged, this, &TabletProxy::onTabletShown); } +QVariant TabletProxy::getButtons() { + Q_ASSERT(QThread::currentThread() == qApp->thread()); + QVariantList result; + for (const auto& button : _tabletButtonProxies) { + result.push_back(QVariant::fromValue(button.data())); + } + return result; +} + void TabletProxy::setToolbarMode(bool toolbarMode) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setToolbarMode", Q_ARG(bool, toolbarMode)); @@ -247,7 +256,6 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { auto offscreenUi = DependencyManager::get(); if (toolbarMode) { - removeButtonsFromHomeScreen(); addButtonsToToolbar(); // create new desktop window @@ -267,7 +275,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { removeButtonsFromToolbar(); if (_currentPathLoaded == TABLET_SOURCE_URL) { - addButtonsToHomeScreen(); + // Tablet QML now pulls buttons from Tablet proxy } else { loadHomeScreen(true); } @@ -284,18 +292,20 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { } } +#if 0 static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) { Q_ASSERT(QThread::currentThread() == qApp->thread()); if (buttonProxy == NULL){ - qCCritical(uiLogging) << "TabletScriptingInterface addButtonProxyToQmlTablet buttonProxy is NULL"; + qCCritical(uiLogging) << __FUNCTION__ << "buttonProxy is NULL"; return; } QVariant resultVar; + qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << "adding button " << buttonProxy; bool hasResult = QMetaObject::invokeMethod(qmlTablet, "addButtonProxy", Qt::DirectConnection, Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, buttonProxy->getProperties())); if (!hasResult) { - qCWarning(uiLogging) << "TabletScriptingInterface addButtonProxyToQmlTablet has no result"; + qCWarning(uiLogging) << __FUNCTION__ << " has no result"; return; } @@ -307,6 +317,8 @@ static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* QObject::connect(qmlButton, SIGNAL(clicked()), buttonProxy, SLOT(clickedSlot())); buttonProxy->setQmlButton(qobject_cast(qmlButton)); } +#endif + static QString getUsername() { QString username = "Unknown user"; @@ -362,7 +374,7 @@ void TabletProxy::onTabletShown() { static_cast(parent())->playSound(TabletScriptingInterface::TabletOpen); if (_showRunningScripts) { _showRunningScripts = false; - pushOntoStack("../../hifi/dialogs/TabletRunningScripts.qml"); + pushOntoStack("hifi/dialogs/TabletRunningScripts.qml"); } } } @@ -396,9 +408,6 @@ void TabletProxy::setQmlTabletRoot(OffscreenQmlSurface* qmlOffscreenSurface) { }); if (_toolbarMode) { - // if someone creates the tablet in toolbar mode, make sure to display the home screen on the tablet. - auto loader = _qmlTabletRoot->findChild("loader"); - QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen())); QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); } @@ -427,7 +436,6 @@ void TabletProxy::setQmlTabletRoot(OffscreenQmlSurface* qmlOffscreenSurface) { QMetaObject::invokeMethod(_qmlTabletRoot, "setShown", Q_ARG(const QVariant&, QVariant(true))); } } else { - removeButtonsFromHomeScreen(); _state = State::Uninitialized; emit screenChanged(QVariant("Closed"), QVariant("")); _currentPathLoaded = ""; @@ -456,7 +464,6 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) { } if (root) { - removeButtonsFromHomeScreen(); auto offscreenUi = DependencyManager::get(); QObject* menu = offscreenUi->getRootMenu(); QMetaObject::invokeMethod(root, "setMenuProperties", Q_ARG(QVariant, QVariant::fromValue(menu)), Q_ARG(const QVariant&, QVariant(submenu))); @@ -530,7 +537,6 @@ void TabletProxy::loadQMLSource(const QVariant& path, bool resizable) { } if (root) { - removeButtonsFromHomeScreen(); //works only in Tablet QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path)); _state = State::QML; if (path != _currentPathLoaded) { @@ -612,8 +618,6 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) { if ((_state != State::Home && _state != State::Uninitialized) || forceOntoHomeScreen) { if (!_toolbarMode && _qmlTabletRoot) { - auto loader = _qmlTabletRoot->findChild("loader"); - QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen())); QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound"); } else if (_toolbarMode && _desktopWindow) { @@ -674,7 +678,6 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS } if (root) { - removeButtonsFromHomeScreen(); if (loadOtherBase) { QMetaObject::invokeMethod(root, "loadTabletWebBase"); } else { @@ -701,12 +704,8 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { auto tabletButtonProxy = QSharedPointer(new TabletButtonProxy(properties.toMap())); _tabletButtonProxies.push_back(tabletButtonProxy); if (!_toolbarMode && _qmlTabletRoot) { - auto tablet = getQmlTablet(); - if (tablet) { - addButtonProxyToQmlTablet(tablet, tabletButtonProxy.data()); - } else { - qCCritical(uiLogging) << "Could not find tablet in TabletRoot.qml"; - } + // Tablet now pulls buttons from the tablet proxy + // FIXME emit a signal so that the tablet can refresh buttons if they change } else if (_toolbarMode) { auto toolbarProxy = DependencyManager::get()->getSystemToolbarProxy(); if (toolbarProxy) { @@ -791,31 +790,11 @@ void TabletProxy::sendToQml(const QVariant& msg) { } } -void TabletProxy::addButtonsToHomeScreen() { - auto tablet = getQmlTablet(); - if (!tablet || _toolbarMode) { - return; - } - for (auto& buttonProxy : _tabletButtonProxies) { - addButtonProxyToQmlTablet(tablet, buttonProxy.data()); - } - auto loader = _qmlTabletRoot->findChild("loader"); - QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen())); -} OffscreenQmlSurface* TabletProxy::getTabletSurface() { return _qmlOffscreenSurface; } -void TabletProxy::removeButtonsFromHomeScreen() { - auto tablet = getQmlTablet(); - for (auto& buttonProxy : _tabletButtonProxies) { - if (tablet) { - QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getProperties())); - } - buttonProxy->setQmlButton(nullptr); - } -} void TabletProxy::desktopWindowClosed() { gotoHomeScreen(); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index bd195fdd20..e7dc5ede1f 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -196,6 +196,8 @@ public: Q_INVOKABLE bool isPathLoaded(const QVariant& path); + Q_INVOKABLE QVariant getButtons(); + QQuickItem* getTabletRoot() const { return _qmlTabletRoot; } OffscreenQmlSurface* getTabletSurface(); @@ -237,12 +239,10 @@ signals: void tabletShownChanged(); protected slots: - void addButtonsToHomeScreen(); void desktopWindowClosed(); void emitWebEvent(const QVariant& msg); void onTabletShown(); protected: - void removeButtonsFromHomeScreen(); void loadHomeScreen(bool forceOntoHomeScreen); void addButtonsToToolbar(); void removeButtonsFromToolbar(); @@ -277,7 +277,9 @@ public: TabletButtonProxy(const QVariantMap& properties); ~TabletButtonProxy(); - void setQmlButton(QQuickItem* qmlButton); + + Q_INVOKABLE void setQmlButton(QQuickItem* qmlButton); + void setToolbarButtonProxy(QObject* toolbarButtonProxy); QUuid getUuid() const { return _uuid; } diff --git a/scripts/developer/inputRecording.js b/scripts/developer/inputRecording.js index 85bda623b3..6fb8e471cd 100644 --- a/scripts/developer/inputRecording.js +++ b/scripts/developer/inputRecording.js @@ -19,7 +19,7 @@ tablet.gotoHomeScreen(); onRecordingScreen = false; } else { - tablet.loadQMLSource("InputRecorder.qml"); + tablet.loadQMLSource("hifi/tablet/InputRecorder.qml"); onRecordingScreen = true; } } diff --git a/scripts/developer/tests/qmlTest.js b/scripts/developer/tests/qmlTest.js index c891b6a1b7..0eaabac6d1 100644 --- a/scripts/developer/tests/qmlTest.js +++ b/scripts/developer/tests/qmlTest.js @@ -1,7 +1,7 @@ print("Launching web window"); qmlWindow = new OverlayWindow({ title: 'Test Qml', - source: "https://s3.amazonaws.com/DreamingContent/qml/content.qml", + source: "qrc:///qml/OverlayWindowTest.qml", height: 240, width: 320, toolWindow: false, diff --git a/scripts/system/audio.js b/scripts/system/audio.js index 0a3471fa81..a93177ca38 100644 --- a/scripts/system/audio.js +++ b/scripts/system/audio.js @@ -15,7 +15,7 @@ var TABLET_BUTTON_NAME = "AUDIO"; var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; -var AUDIO_QML_SOURCE = "../audio/Audio.qml"; +var AUDIO_QML_SOURCE = "hifi/audio/Audio.qml"; var MUTE_ICONS = { icon: "icons/tablet-icons/mic-mute-i.svg", diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 8e4a3215fd..9b2367b762 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -26,8 +26,8 @@ // Relevant Variables: // -WALLET_QML_SOURCE: The path to the Wallet QML // -onWalletScreen: true/false depending on whether we're looking at the app. - var WALLET_QML_SOURCE = Script.resourcesPath() + "qml/hifi/commerce/wallet/Wallet.qml"; - var MARKETPLACE_PURCHASES_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/purchases/Purchases.qml"; + var WALLET_QML_SOURCE = "hifi/commerce/wallet/Wallet.qml"; + var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/purchases/Purchases.qml"; var onWalletScreen = false; function onButtonClicked() { if (!tablet) { diff --git a/scripts/system/edit.js b/scripts/system/edit.js index e76a02b6f5..07551f31e5 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -656,7 +656,7 @@ var toolBar = (function () { selectionDisplay.triggerMapping.disable(); tablet.landscape = false; } else { - tablet.loadQMLSource("Edit.qml", true); + tablet.loadQMLSource("hifi/tablet/Edit.qml", true); UserActivityLogger.enabledEdit(); entityListTool.setVisible(true); gridTool.setVisible(true); diff --git a/scripts/system/generalSettings.js b/scripts/system/generalSettings.js index 7d97f13757..082528ffc5 100644 --- a/scripts/system/generalSettings.js +++ b/scripts/system/generalSettings.js @@ -18,7 +18,7 @@ var buttonName = "Settings"; var toolBar = null; var tablet = null; - var settings = "TabletGeneralPreferences.qml" + var settings = "hifi/tablet/TabletGeneralPreferences.qml" function onClicked(){ if (tablet) { tablet.loadQMLSource(settings); diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index f0044084f6..b427739292 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -346,7 +346,7 @@ Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled); break; case 'purchases_openGoTo': - tablet.loadQMLSource("TabletAddressDialog.qml"); + tablet.loadQMLSource("hifi/tablet/TabletAddressDialog.qml"); break; case 'purchases_itemCertificateClicked': setCertificateInfo("", message.itemCertificateId); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 44ff7c2acd..05a7dc8975 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -40,7 +40,7 @@ var HOVER_TEXTURES = { var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6}; var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29}; var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now -var PAL_QML_SOURCE = "../Pal.qml"; +var PAL_QML_SOURCE = "hifi/Pal.qml"; var conserveResources = true; Script.include("/~/system/libraries/controllers.js"); diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js index 929c6e0e5c..2a0e827932 100644 --- a/scripts/system/tablet-goto.js +++ b/scripts/system/tablet-goto.js @@ -24,7 +24,7 @@ print('tablet-goto.js:', [].map.call(arguments, JSON.stringify)); } - var gotoQmlSource = "TabletAddressDialog.qml"; + var gotoQmlSource = "hifi/tablet/TabletAddressDialog.qml"; var buttonName = "GOTO"; var onGotoScreen = false; var shouldActivateButton = false; diff --git a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js index e7a135ec9e..7bc65722cd 100644 --- a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js +++ b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js @@ -24,7 +24,7 @@ if (onSkyboxChangerScreen) { tablet.gotoHomeScreen(); } else { - tablet.loadQMLSource("../SkyboxChanger.qml"); + tablet.loadQMLSource("hifi/SkyboxChanger.qml"); } } diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index f0b943ad92..76044d2975 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -390,7 +390,7 @@ // Relevant Variables: // -SPECTATOR_CAMERA_QML_SOURCE: The path to the SpectatorCamera QML // -onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app. - var SPECTATOR_CAMERA_QML_SOURCE = Script.resourcesPath() + "qml/hifi/SpectatorCamera.qml"; + var SPECTATOR_CAMERA_QML_SOURCE = "hifi/SpectatorCamera.qml"; var onSpectatorCameraScreen = false; function onTabletButtonClicked() { if (!tablet) { From 2cd76be6c487de87bbdfa58fdf54e1d653311fba Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 6 Nov 2017 10:31:32 -0800 Subject: [PATCH 08/81] Fix encoding for wallet scripting interface --- interface/src/scripting/WalletScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WalletScriptingInterface.cpp b/interface/src/scripting/WalletScriptingInterface.cpp index c866bac2b2..55d53000b7 100644 --- a/interface/src/scripting/WalletScriptingInterface.cpp +++ b/interface/src/scripting/WalletScriptingInterface.cpp @@ -1,4 +1,4 @@ -// +// // WalletScriptingInterface.cpp // interface/src/scripting // From 803e5d143d2e5bb638ffc31ff93db6368d8fa480 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 7 Nov 2017 11:48:46 -0800 Subject: [PATCH 09/81] Moved Haze pass to be before transparency pass. --- libraries/render-utils/src/RenderDeferredTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 6a3b560167..0f095900be 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -159,6 +159,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job task.addJob("DrawBackgroundDeferred", lightingModel); + const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeModel, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingFramebuffer)); + task.addJob("DrawHazeDeferred", drawHazeInputs); + // Render transparent objects forward in LightingBuffer const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); @@ -169,9 +172,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DebugLightClusters", debugLightClustersInputs); } - const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeModel, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingFramebuffer)); - task.addJob("DrawHaze", drawHazeInputs); - const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // Lighting Buffer ready for tone mapping From b7f31eb5b9cabf53c205178895aed8bb50ba48b0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 7 Nov 2017 12:42:26 -0800 Subject: [PATCH 10/81] Fixing desktop QML loading, tablet clickthrough bugs --- .../resources/qml/hifi/tablet/TabletRoot.qml | 13 ++- .../resources/qml/hifi/tablet/WindowRoot.qml | 82 +++++++++++++------ 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 028ac2d8b6..6eb8e59ed1 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -202,8 +202,16 @@ Item { } function load(newSource, callback) { - loader.source = newSource; - loader.item = null; + if (loader.source == newSource) { + loader.loaded(); + return; + } + + if (loader.item) { + loader.item.destroy(); + loader.item = null; + } + QmlSurface.load(newSource, loader, function(newItem) { loader.item = newItem; loader.item.width = loader.width; @@ -232,7 +240,6 @@ Item { callback(); } }); - console.log("QQQ done calling QmlSurface.load") } } diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index e3170f85ef..baf2fa05c2 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -59,18 +59,15 @@ Windows.ScrollingWindow { } function loadSource(url) { - loader.source = ""; // make sure we load the qml fresh each time. - loader.source = url; + loader.load(url) } function loadWebBase() { - loader.source = ""; - loader.source = "WindowWebView.qml"; + loader.load("hifi/tablet/TabletWebView.qml"); } function loadTabletWebBase() { - loader.source = ""; - loader.source = "./BlocksWebView.qml"; + loader.load("hifi/tablet/BlocksWebView.qml"); } function loadWebUrl(url, injectedJavaScriptUrl) { @@ -111,38 +108,73 @@ Windows.ScrollingWindow { username = newUsername; } - Loader { + // Hook up callback for clara.io download from the marketplace. + Connections { + id: eventBridgeConnection + target: eventBridge + onWebEventReceived: { + if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") { + ApplicationInterface.addAssetToWorldFromURL(message.slice(18)); + } + } + } + + Item { id: loader - objectName: "loader" - asynchronous: false + objectName: "loader"; + property string source: ""; + property var item: null; height: pane.scrollHeight width: pane.contentWidth anchors.left: parent.left anchors.top: parent.top - - // Hook up callback for clara.io download from the marketplace. - Connections { - id: eventBridgeConnection - target: eventBridge - onWebEventReceived: { - if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") { - ApplicationInterface.addAssetToWorldFromURL(message.slice(18)); - } + signal loaded; + + onWidthChanged: { + if (loader.item) { + loader.item.width = loader.width; } } + + onHeightChanged: { + if (loader.item) { + loader.item.height = loader.height; + } + } + + function load(newSource, callback) { + if (loader.source == newSource) { + loader.loaded(); + return; + } - onLoaded: { - if (loader.item.hasOwnProperty("sendToScript")) { - loader.item.sendToScript.connect(tabletRoot.sendToScript); + if (loader.item) { + loader.item.destroy(); + loader.item = null; } - if (loader.item.hasOwnProperty("setRootMenu")) { - loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu); - } - loader.item.forceActiveFocus(); + + QmlSurface.load(newSource, loader, function(newItem) { + loader.item = newItem; + loader.item.width = loader.width; + loader.item.height = loader.height; + loader.loaded(); + if (loader.item.hasOwnProperty("sendToScript")) { + loader.item.sendToScript.connect(tabletRoot.sendToScript); + } + if (loader.item.hasOwnProperty("setRootMenu")) { + loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu); + } + loader.item.forceActiveFocus(); + + if (callback) { + callback(); + } + }); } } + implicitWidth: 480 implicitHeight: 706 } From 87aee7242aa1957d80ba2bfd606e72046c32fdb0 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 7 Nov 2017 15:25:42 -0800 Subject: [PATCH 11/81] Moved linearDepthMap into Haze.slf Refactored computation of keylight attenuation - now function in Haze.slh --- .../render-utils/src/DeferredGlobalLight.slh | 50 ++----------------- libraries/render-utils/src/Haze.slf | 1 + libraries/render-utils/src/Haze.slh | 43 +++++++++++++++- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index f70daf1e77..881de119b0 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -123,6 +123,9 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += ambientSpecular; // Directional + // Get directional light (used by both directional light and haze attenuation) + Light directionalLight = getLight(); + vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation @@ -135,52 +138,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Attenuate the light if haze effect selected if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - // Directional light attenuation is simulated by assuming the light source is at a fixed height above the - // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height - // - // The distance is computed from the height and the directional light orientation - // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees - - // Get directional light - Light light = getLight(); - vec3 lightDirection = getLightDirection(light); - - // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen) - float height_95p = 2000.0; - if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) { - height_95p = -log(0.05) / hazeParams.hazeKeyLightAltitudeFactor; - } - - // Note that the sine will always be positive - float sin_pitch = sqrt(1.0 - lightDirection.y * lightDirection.y); - - float distance; - const float minimumSinPitch = 0.001; - if (sin_pitch < minimumSinPitch) { - distance = height_95p / minimumSinPitch; - } else { - distance = height_95p / sin_pitch; - } - - // Position of fragment in world coordinates - vec4 worldFragPos = invViewMat * vec4(position, 0.0); - - // Integration is from the fragment towards the light source - // Note that the haze base reference affects only the haze density as function of altitude - float hazeDensityDistribution = - hazeParams.hazeKeyLightRangeFactor * - exp(-hazeParams.hazeKeyLightAltitudeFactor * (worldFragPos.y - hazeParams.hazeBaseReference)); - - float hazeIntegral = hazeDensityDistribution * distance; - - // Note that t is constant and equal to -log(0.05) - // float t = hazeParams.hazeAltitudeFactor * height_95p; - // hazeIntegral *= (1.0 - exp (-t)) / t; - hazeIntegral *= 0.3171178; - - float hazeAmount = 1.0 - exp(-hazeIntegral); - - color = mix(color, vec3(0.0, 0.0, 0.0), hazeAmount); + color = computeHazeColor(color, directionalLight, invViewMat, position); } return color; diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index b366e6d639..79cca8b17b 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -23,6 +23,7 @@ <@include Haze.slh@> uniform sampler2D colorMap; +uniform sampler2D linearDepthMap; vec4 unpackPositionFromZeye(vec2 texcoord) { float Zeye = -texture(linearDepthMap, texcoord).x; diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index de7f0ac246..ea72b305c2 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -40,7 +40,48 @@ layout(std140) uniform hazeBuffer { HazeParams hazeParams; }; -uniform sampler2D linearDepthMap; +vec3 computeHazeColor(vec3 color, Light directionalLight, mat4 invViewMat, vec3 worldFragPos) { + // Directional light attenuation is simulated by assuming the light source is at a fixed height above the + // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height + // + // The distance is computed from the height and the directional light orientation + // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees + vec3 lightDirection = getLightDirection(directionalLight); + // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen) + float height_95p = 2000.0; + const float log_p_005 = log(0.05); + if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) { + height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor; + } + + // Note that we need the sine to be positive + float sin_pitch = abs(lightDirection.y); + + float distance; + const float minimumSinPitch = 0.001; + if (sin_pitch < minimumSinPitch) { + distance = height_95p / minimumSinPitch; + } else { + distance = height_95p / sin_pitch; + } + + // Integration is from the fragment towards the light source + // Note that the haze base reference affects only the haze density as function of altitude + float hazeDensityDistribution = + hazeParams.hazeKeyLightRangeFactor * + exp(-hazeParams.hazeKeyLightAltitudeFactor * (worldFragPos.y - hazeParams.hazeBaseReference)); + + float hazeIntegral = hazeDensityDistribution * distance; + + // Note that t is constant and equal to -log(0.05) + // float t = hazeParams.hazeAltitudeFactor * height_95p; + // hazeIntegral *= (1.0 - exp (-t)) / t; + hazeIntegral *= 0.3171178; + + float hazeAmount = 1.0 - exp(-hazeIntegral); + + return mix(color, vec3(0.0, 0.0, 0.0), hazeAmount); +} <@endif@> From ee6a8510c6c8cda61b506fac9619f52ace116690 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 7 Nov 2017 17:22:57 -0800 Subject: [PATCH 12/81] Refactored haze computation. --- .../render-utils/src/DeferredGlobalLight.slh | 2 +- libraries/render-utils/src/Haze.slf | 99 +------------------ libraries/render-utils/src/Haze.slh | 99 ++++++++++++++++++- 3 files changed, 102 insertions(+), 98 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 881de119b0..67a45e6ddf 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -138,7 +138,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Attenuate the light if haze effect selected if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - color = computeHazeColor(color, directionalLight, invViewMat, position); + color = computeHazeColorKeyLightAttenuation(color, directionalLight, invViewMat, position); } return color; diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 79cca8b17b..18deb9c891 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -46,104 +46,11 @@ void main(void) { discard; } - // Distance to fragment - vec4 eyeFragPos = unpackPositionFromZeye(varTexCoord0); - float distance = length(eyeFragPos.xyz); - vec4 fragColor = texture(colorMap, varTexCoord0); - vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0); - - // Directional light component is a function of the angle from the eye, between the fragment and the sun - DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); + vec4 eyeFragPos = unpackPositionFromZeye(varTexCoord0); vec4 worldFragPos = getViewInverse() * eyeFragPos; - vec3 eyeFragDir = normalize(worldFragPos.xyz); + vec3 worldEyePos = getViewInverse()[3].xyz; - Light light = getLight(); - vec3 lightDirection = getLightDirection(light); - - float glareComponent = max(0.0, dot(eyeFragDir, -lightDirection)); - float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend)); - - vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0); - - // Use the haze colour for the glare colour, if blend is not enabled - vec4 blendedHazeColor; - if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) { - blendedHazeColor = mix(hazeColor, glareColor, power); - } else { - blendedHazeColor = hazeColor; - } - - vec4 potentialFragColor; - - if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) { - // Compute separately for each colour - // Haze is based on both range and altitude - // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt - - // The eyepoint position is in the last column of the matrix - vec3 worldEyePos = getViewInverse()[3].xyz; - - // Note that the haze base reference affects only the haze density as function of altitude - vec3 hazeDensityDistribution = - hazeParams.colorModulationFactor * - exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); - - vec3 hazeIntegral = hazeDensityDistribution * distance; - - const float slopeThreshold = 0.01; - float deltaHeight = worldFragPos.y - worldEyePos.y; - if (abs(deltaHeight) > slopeThreshold) { - float t = hazeParams.hazeHeightFactor * deltaHeight; - hazeIntegral *= (1.0 - exp (-t)) / t; - } - - vec3 hazeAmount = 1.0 - exp(-hazeIntegral); - - // Compute color after haze effect - potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0)); - } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) { - // Haze is based only on range - float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor); - - // Compute color after haze effect - potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount); - } else { - // Haze is based on both range and altitude - // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt - - // The eyepoint position is in the last column of the matrix - vec3 worldEyePos = getViewInverse()[3].xyz; - - // Note that the haze base reference affects only the haze density as function of altitude - float hazeDensityDistribution = - hazeParams.hazeRangeFactor * - exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); - - float hazeIntegral = hazeDensityDistribution * distance; - - const float slopeThreshold = 0.01; - float deltaHeight = worldFragPos.y - worldEyePos.y; - if (abs(deltaHeight) > slopeThreshold) { - float t = hazeParams.hazeHeightFactor * deltaHeight; - // Protect from wild values - if (abs(t) > 0.0000001) { - hazeIntegral *= (1.0 - exp (-t)) / t; - } - } - - float hazeAmount = 1.0 - exp(-hazeIntegral); - - // Compute color after haze effect - potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount); - } - - // Mix with background at far range - const float BLEND_DISTANCE = 27000.0; - if (distance > BLEND_DISTANCE) { - outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend); - } else { - outFragColor = potentialFragColor; - } + outFragColor = computeHazeColor(fragColor, eyeFragPos, worldFragPos, worldEyePos); } diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index ea72b305c2..0633802c84 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -40,7 +40,7 @@ layout(std140) uniform hazeBuffer { HazeParams hazeParams; }; -vec3 computeHazeColor(vec3 color, Light directionalLight, mat4 invViewMat, vec3 worldFragPos) { +vec3 computeHazeColorKeyLightAttenuation(vec3 color, Light directionalLight, mat4 invViewMat, vec3 worldFragPos) { // Directional light attenuation is simulated by assuming the light source is at a fixed height above the // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height // @@ -83,5 +83,102 @@ vec3 computeHazeColor(vec3 color, Light directionalLight, mat4 invViewMat, vec3 return mix(color, vec3(0.0, 0.0, 0.0), hazeAmount); } + +vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec3 worldEyePos) { + // Distance to fragment + float distance = length(eyeFragPos.xyz); + + // Convert haze colour from uniform into a vec4 + vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0); + + // Directional light component is a function of the angle from the eye, between the fragment and the sun + vec3 eyeFragDir = normalize(worldFragPos.xyz); + + Light light = getLight(); + vec3 lightDirection = getLightDirection(light); + + float glareComponent = max(0.0, dot(eyeFragDir, -lightDirection)); + float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend)); + + vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0); + + // Use the haze colour for the glare colour, if blend is not enabled + vec4 blendedHazeColor; + if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) { + blendedHazeColor = mix(hazeColor, glareColor, power); + } else { + blendedHazeColor = hazeColor; + } + + vec4 potentialFragColor; + + if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) { + // Compute separately for each colour + // Haze is based on both range and altitude + // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt + + // Note that the haze base reference affects only the haze density as function of altitude + vec3 hazeDensityDistribution = + hazeParams.colorModulationFactor * + exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + + vec3 hazeIntegral = hazeDensityDistribution * distance; + + const float slopeThreshold = 0.01; + float deltaHeight = worldFragPos.y - worldEyePos.y; + if (abs(deltaHeight) > slopeThreshold) { + float t = hazeParams.hazeHeightFactor * deltaHeight; + hazeIntegral *= (1.0 - exp (-t)) / t; + } + + vec3 hazeAmount = 1.0 - exp(-hazeIntegral); + + // Compute color after haze effect + potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0)); + } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) { + // Haze is based only on range + float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor); + + // Compute color after haze effect + potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount); + } else { + // Haze is based on both range and altitude + // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt + + // Note that the haze base reference affects only the haze density as function of altitude + float hazeDensityDistribution = + hazeParams.hazeRangeFactor * + exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + + float hazeIntegral = hazeDensityDistribution * distance; + + const float slopeThreshold = 0.01; + float deltaHeight = worldFragPos.y - worldEyePos.y; + if (abs(deltaHeight) > slopeThreshold) { + float t = hazeParams.hazeHeightFactor * deltaHeight; + // Protect from wild values + if (abs(t) > 0.0000001) { + hazeIntegral *= (1.0 - exp (-t)) / t; + } + } + + float hazeAmount = 1.0 - exp(-hazeIntegral); + + // Compute color after haze effect + potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount); + } + + // Mix with background at far range + const float BLEND_DISTANCE = 27000.0; + vec4 outFragColor; + if (distance > BLEND_DISTANCE) { + outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend); + } else { + outFragColor = potentialFragColor; + } + + return outFragColor; +} + <@endif@> From 83ff20b599445a740a44f5847572e2e836b8764a Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 08:00:31 -0800 Subject: [PATCH 13/81] Renamed getHazeParametersBuffer to getParametersBuffer --- libraries/model/src/model/Haze.h | 2 +- libraries/render-utils/src/DeferredLightingEffect.cpp | 2 +- libraries/render-utils/src/DrawHaze.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index a0cc7c3bc7..e8b680705f 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -95,7 +95,7 @@ namespace model { void setZoneTransform(const glm::mat4& zoneTransform); using UniformBufferView = gpu::BufferView; - UniformBufferView getHazeParametersBuffer() const { return _hazeParametersBuffer; } + UniformBufferView getParametersBuffer() const { return _hazeParametersBuffer; } protected: class Parameters { diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 2187cb70b1..aae908c835 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -560,7 +560,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Haze if (haze) { - batch.setUniformBuffer(HAZE_MODEL_BUFFER_SLOT, haze->getHazeParametersBuffer()); + batch.setUniformBuffer(HAZE_MODEL_BUFFER_SLOT, haze->getParametersBuffer()); } batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 7cf07d8f33..6b544eeb30 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -169,7 +169,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu auto hazeStage = args->_scene->getStage(); if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { model::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); - batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); + batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getParametersBuffer()); } batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer()); From 3d2c8186e7c4a1067e752c0adc36d2886d1107f1 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 08:01:19 -0800 Subject: [PATCH 14/81] Added Haze model as input to transparency shader. --- libraries/render-utils/src/RenderDeferredTask.cpp | 4 +++- libraries/render-utils/src/RenderDeferredTask.h | 4 ++-- libraries/render/src/render/ShapePipeline.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 0f095900be..79a8bc0827 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -163,7 +163,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawHazeDeferred", drawHazeInputs); // Render transparent objects forward in LightingBuffer - const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); + const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel, hazeModel).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); // LIght Cluster Grid Debuging job @@ -291,6 +291,7 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); + const auto& hazeModel = inputs.get2(); RenderArgs* args = renderContext->args; @@ -311,6 +312,7 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& // Setup lighting model for all items; batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); + batch.setUniformBuffer(render::ShapePipeline::Slot::HAZE_MODEL, hazeModel->getParametersBuffer()); // From the lighting model define a global shapKey ORED with individiual keys ShapeKey::Builder keyBuilder; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 452420589b..9a1e37ea92 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -15,7 +15,7 @@ #include #include #include "LightingModel.h" - +#include "model/Haze.h" class BeginGPURangeTimer { public: @@ -66,7 +66,7 @@ protected: class DrawDeferred { public: - using Inputs = render::VaryingSet2 ; + using Inputs = render::VaryingSet3 ; using Config = DrawConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index f0749504eb..0184c4275f 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -238,6 +238,7 @@ public: LIGHT, LIGHT_AMBIENT_BUFFER, FADE_PARAMETERS, + HAZE_MODEL }; enum MAP { From a8a118582dc344cd4ddcd505147eb81b9574ec8f Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 09:37:58 -0800 Subject: [PATCH 15/81] WIP - passing uniform into model translucency shader. --- libraries/model/src/model/Haze.h | 4 ++-- libraries/render-utils/src/DeferredLightingEffect.cpp | 2 +- libraries/render-utils/src/DrawHaze.cpp | 2 +- libraries/render-utils/src/RenderDeferredTask.cpp | 8 +++++++- libraries/render/src/render/ShapePipeline.cpp | 2 ++ libraries/render/src/render/ShapePipeline.h | 1 + 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index e8b680705f..5c916c3b91 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -95,7 +95,7 @@ namespace model { void setZoneTransform(const glm::mat4& zoneTransform); using UniformBufferView = gpu::BufferView; - UniformBufferView getParametersBuffer() const { return _hazeParametersBuffer; } + UniformBufferView getHazeParametersBuffer() const { return _hazeParametersBuffer; } protected: class Parameters { @@ -128,7 +128,7 @@ namespace model { Parameters() {} }; - UniformBufferView _hazeParametersBuffer; + UniformBufferView _hazeParametersBuffer{ nullptr }; }; using HazePointer = std::shared_ptr; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index aae908c835..2187cb70b1 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -560,7 +560,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Haze if (haze) { - batch.setUniformBuffer(HAZE_MODEL_BUFFER_SLOT, haze->getParametersBuffer()); + batch.setUniformBuffer(HAZE_MODEL_BUFFER_SLOT, haze->getHazeParametersBuffer()); } batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 6b544eeb30..7cf07d8f33 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -169,7 +169,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu auto hazeStage = args->_scene->getStage(); if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { model::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); - batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getParametersBuffer()); + batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); } batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer()); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 79a8bc0827..a9ad01902d 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -312,7 +312,13 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& // Setup lighting model for all items; batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); - batch.setUniformBuffer(render::ShapePipeline::Slot::HAZE_MODEL, hazeModel->getParametersBuffer()); + + // Setup haze iff curretn zone has haze + auto hazeStage = args->_scene->getStage(); + if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { + model::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); + batch.setUniformBuffer(render::ShapePipeline::Slot::HAZE_MODEL, hazePointer->getHazeParametersBuffer()); + } // From the lighting model define a global shapKey ORED with individiual keys ShapeKey::Builder keyBuilder; diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 762b7712d7..4254280fa1 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -87,6 +87,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS)); + slotBindings.insert(gpu::Shader::Binding(std::string("hazeParametersBuffer"), Slot::BUFFER::HAZE_MODEL)); gpu::Shader::makeProgram(*program, slotBindings); @@ -107,6 +108,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer"); + locations->hazeParameterBufferUnit = program->getUniformBuffers().findLocation("hazeParametersBuffer"); ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 0184c4275f..101c060306 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -271,6 +271,7 @@ public: int lightAmbientMapUnit; int fadeMaskTextureUnit; int fadeParameterBufferUnit; + int hazeParameterBufferUnit; }; using LocationsPointer = std::shared_ptr; From 1a58aee385ad8c3bc68ac4b8d7da519b8d703eec Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 8 Nov 2017 12:00:29 -0800 Subject: [PATCH 16/81] Fix scripting URL injection, I hope --- .../resources/qml/hifi/tablet/TabletRoot.qml | 24 ++++++++++--------- .../ui/src/ui/TabletScriptingInterface.cpp | 13 +++++----- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 6eb8e59ed1..bc795ce7ed 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -81,21 +81,23 @@ Item { }) } - function loadWebOnTop(url, injectJavaScriptUrl) { - tabletApps.append({"appUrl": loader.source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url}); - loader.item.url = tabletApps.get(currentApp).appWebUrl; - loader.item.scriptUrl = tabletApps.get(currentApp).scriptUrl; - if (loader.item.hasOwnProperty("gotoPreviousApp")) { - loader.item.gotoPreviousApp = true; - } + function loadWebContent(source, url, injectJavaScriptUrl) { + tabletApps.append({"appUrl": source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url}); + loader.load(source, function() { + loader.item.url = tabletApps.get(currentApp).appWebUrl; + loader.item.scriptUrl = tabletApps.get(currentApp).scriptUrl; + if (loader.item.hasOwnProperty("gotoPreviousApp")) { + loader.item.gotoPreviousApp = true; + } + }); } - function loadWebBase() { - loader.load("hifi/tablet/TabletWebView.qml"); + function loadWebBase(url, injectJavaScriptUrl) { + loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl); } - function loadTabletWebBase() { - loader.load("hifi/tablet/BlocksWebView.qml"); + function loadTabletWebBase(url, injectJavaScriptUrl) { + loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl); } function returnToPreviousApp() { diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index a261ae45b1..7440d0b5d0 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -679,19 +679,20 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS if (root) { if (loadOtherBase) { - QMetaObject::invokeMethod(root, "loadTabletWebBase"); + QMetaObject::invokeMethod(root, "loadTabletWebBase", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); } else { - QMetaObject::invokeMethod(root, "loadWebBase"); + QMetaObject::invokeMethod(root, "loadWebBase", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); } QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); if (_toolbarMode && _desktopWindow) { QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false))); } - QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); + _state = State::Web; + emit screenChanged(QVariant("Web"), QVariant(url)); + _currentPathLoaded = QVariant(url); + } else { + qWarning() << "Unable to load web content due to missing root"; } - _state = State::Web; - emit screenChanged(QVariant("Web"), QVariant(url)); - _currentPathLoaded = QVariant(url); } TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { From 4433e79c9c9b70dc6f2a561366b759a23d4e2e43 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 14:08:37 -0800 Subject: [PATCH 17/81] Seems to work. --- .../render-utils/src/DeferredGlobalLight.slh | 44 ++++++++++++++++--- libraries/render-utils/src/Haze.slf | 2 +- libraries/render-utils/src/Haze.slh | 24 +++++++++- .../render-utils/src/model_translucent.slf | 2 +- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 67a45e6ddf..311012716a 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -91,6 +91,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <@endfunc@> +<@include Haze.slh@> <@func declareEvalSkyboxGlobalColor(supportScattering)@> @@ -101,8 +102,6 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <$declareDeferredCurvature()$> <@endif@> -<@include Haze.slh@> - vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness <@if supportScattering@> @@ -138,7 +137,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Attenuate the light if haze effect selected if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - color = computeHazeColorKeyLightAttenuation(color, directionalLight, invViewMat, position); + color = computeHazeColorKeyLightAttenuation(color, directionalLight, position); } return color; @@ -171,9 +170,6 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur } <@endfunc@> - - - <@func declareEvalGlobalLightingAlphaBlended()@> <$declareLightingAmbient(1, 1, 1)$> @@ -191,7 +187,6 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl color += ambientDiffuse; color += ambientSpecular / opacity; - // Directional vec3 directionalDiffuse; vec3 directionalSpecular; @@ -202,6 +197,41 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl return color; } +vec3 evalGlobalLightingAlphaBlendedWithHaze( + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) +{ + <$prepareGlobalLight()$> + + color += emissive * isEmissiveEnabled(); + + // Ambient + vec3 ambientDiffuse; + vec3 ambientSpecular; + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance); + color += ambientDiffuse; + color += ambientSpecular / opacity; + + // Directional + vec3 directionalDiffuse; + vec3 directionalSpecular; + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + color += directionalDiffuse; + color += directionalSpecular / opacity; + + // Haze + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 colorV4 = computeHazeColor( + vec4(color, 0.0), // fragment original color + vec4(position, 0.0), // fragment position in eye coordinates + vec4(fragEyeVector, 0.0), // fragment position in world coordinates + invViewMat[3]); // eye position in world coordinates + + color = colorV4.rgb; + } + + return color; +} <@endfunc@> diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 18deb9c891..d758756975 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -49,7 +49,7 @@ void main(void) { vec4 fragColor = texture(colorMap, varTexCoord0); vec4 eyeFragPos = unpackPositionFromZeye(varTexCoord0); vec4 worldFragPos = getViewInverse() * eyeFragPos; - vec3 worldEyePos = getViewInverse()[3].xyz; + vec4 worldEyePos = getViewInverse()[3]; outFragColor = computeHazeColor(fragColor, eyeFragPos, worldFragPos, worldEyePos); } diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index 0633802c84..97284f1c2a 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -40,7 +40,17 @@ layout(std140) uniform hazeBuffer { HazeParams hazeParams; }; -vec3 computeHazeColorKeyLightAttenuation(vec3 color, Light directionalLight, mat4 invViewMat, vec3 worldFragPos) { + +// Input: +// color - fragment original color +// directionalLight - parameters of the keylight +// worldFragPos - fragment position in world coordinates +// Output: +// fragment colour after haze effect +// +// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission +// +vec3 computeHazeColorKeyLightAttenuation(vec3 color, Light directionalLight, vec3 worldFragPos) { // Directional light attenuation is simulated by assuming the light source is at a fixed height above the // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height // @@ -84,7 +94,17 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, Light directionalLight, mat return mix(color, vec3(0.0, 0.0, 0.0), hazeAmount); } -vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec3 worldEyePos) { +// Input: +// fragColor - fragment original color +// eyeFragPos - fragment position in eye coordinates +// worldFragPos - fragment position in world coordinates +// worldEyePos - eye position in world coordinates +// Output: +// fragment colour after haze effect +// +// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission +// +vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec4 worldEyePos) { // Distance to fragment float distance = length(eyeFragPos.xyz); diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 6cf99a68ef..38f162fdc3 100644 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -66,7 +66,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); - _fragColor = vec4(evalGlobalLightingAlphaBlended( + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, From 25df649b44fac06719208228c24657c5444d2d6d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 8 Nov 2017 14:55:34 -0800 Subject: [PATCH 18/81] Fix desktop mode script URL injection --- .../resources/qml/hifi/tablet/TabletRoot.qml | 8 +++---- .../resources/qml/hifi/tablet/WindowRoot.qml | 22 ++++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index bc795ce7ed..da544c2114 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -68,8 +68,8 @@ Item { function loadSource(url) { tabletApps.clear(); - loader.load(url) - tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); + tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); + loader.load(url) } function loadQMLOnTop(url) { @@ -84,8 +84,8 @@ Item { function loadWebContent(source, url, injectJavaScriptUrl) { tabletApps.append({"appUrl": source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url}); loader.load(source, function() { - loader.item.url = tabletApps.get(currentApp).appWebUrl; - loader.item.scriptUrl = tabletApps.get(currentApp).scriptUrl; + loader.item.scriptURL = injectJavaScriptUrl; + loader.item.url = url; if (loader.item.hasOwnProperty("gotoPreviousApp")) { loader.item.gotoPreviousApp = true; } diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index baf2fa05c2..0b631326f4 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -62,20 +62,22 @@ Windows.ScrollingWindow { loader.load(url) } - function loadWebBase() { - loader.load("hifi/tablet/TabletWebView.qml"); + function loadWebContent(source, url, injectJavaScriptUrl) { + loader.load(source, function() { + loader.item.url = url + loader.item.scriptURL = injectJavaScriptUrl; + if (loader.item.hasOwnProperty("closeButtonVisible")) { + loader.item.closeButtonVisible = false; + } + }); } - function loadTabletWebBase() { - loader.load("hifi/tablet/BlocksWebView.qml"); + function loadWebBase(url, injectJavaScriptUrl) { + loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl); } - function loadWebUrl(url, injectedJavaScriptUrl) { - loader.item.url = url; - loader.item.scriptURL = injectedJavaScriptUrl; - if (loader.item.hasOwnProperty("closeButtonVisible")) { - loader.item.closeButtonVisible = false; - } + function loadTabletWebBase(url, injectJavaScriptUrl) { + loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl); } // used to send a message from qml to interface script. From 3c5fd73ca80d3b8dcdb5c4ff8de4493c88668802 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 8 Nov 2017 14:56:21 -0800 Subject: [PATCH 19/81] Removed unused argument. --- libraries/render-utils/src/RenderDeferredTask.cpp | 3 +-- libraries/render-utils/src/RenderDeferredTask.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a9ad01902d..c301e71296 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -163,7 +163,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawHazeDeferred", drawHazeInputs); // Render transparent objects forward in LightingBuffer - const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel, hazeModel).asVarying(); + const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); // LIght Cluster Grid Debuging job @@ -291,7 +291,6 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); - const auto& hazeModel = inputs.get2(); RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 9a1e37ea92..1573a6cbb0 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -15,7 +15,6 @@ #include #include #include "LightingModel.h" -#include "model/Haze.h" class BeginGPURangeTimer { public: @@ -66,7 +65,7 @@ protected: class DrawDeferred { public: - using Inputs = render::VaryingSet3 ; + using Inputs = render::VaryingSet2 ; using Config = DrawConfig; using JobModel = render::Job::ModelI; From 7bf1b176d72215077545d7fbac9743b24e26aa76 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 10 Nov 2017 12:34:52 -0800 Subject: [PATCH 20/81] Renaming Tablet API to Tablets, supporting dev-mode QML loading from filesystem --- interface/CMakeLists.txt | 8 +- .../qml/LoginDialog/LinkAccountBody.qml | 2 +- .../resources/qml/LoginDialog/SignUpBody.qml | 2 +- .../qml/LoginDialog/UsernameCollisionBody.qml | 2 +- .../resources/qml/controls-uit/Button.qml | 4 +- .../resources/qml/controls-uit/CheckBox.qml | 4 +- .../qml/controls-uit/CheckBoxQQC2.qml | 4 +- .../qml/controls-uit/GlyphButton.qml | 4 +- interface/resources/qml/controls-uit/Key.qml | 4 +- .../qml/controls-uit/RadioButton.qml | 4 +- .../qml/controls/FlickableWebViewCore.qml | 2 +- .../dialogs/TabletConnectionFailureDialog.qml | 2 +- .../qml/dialogs/TabletLoginDialog.qml | 4 +- .../dialogs/preferences/ButtonPreference.qml | 4 +- .../preferences/CheckBoxPreference.qml | 4 +- interface/resources/qml/hifi/Card.qml | 6 +- interface/resources/qml/hifi/audio/MicBar.qml | 4 +- .../qml/hifi/tablet/NewEntityButton.qml | 4 +- .../resources/qml/hifi/tablet/Tablet.qml | 280 ------------------ .../qml/hifi/tablet/TabletAddressDialog.qml | 4 +- .../hifi/tablet/TabletAttachmentsDialog.qml | 2 +- .../qml/hifi/tablet/TabletButton.qml | 5 +- .../resources/qml/hifi/tablet/TabletHome.qml | 159 ++++++++++ .../qml/hifi/tablet/TabletMenuView.qml | 4 +- .../tabletWindows/TabletPreferencesDialog.qml | 4 +- interface/src/Application.cpp | 10 +- interface/src/ui/overlays/Web3DOverlay.cpp | 4 - .../src/model-networking/TextureCache.cpp | 2 - libraries/octree/src/Octree.cpp | 4 - libraries/shared/src/PathUtils.cpp | 25 +- libraries/shared/src/PathUtils.h | 4 + libraries/ui/src/ui/OffscreenQmlSurface.cpp | 17 +- .../ui/src/ui/TabletScriptingInterface.cpp | 12 +- scripts/developer/EZrecord.js | 4 +- scripts/developer/inputRecording.js | 2 +- .../developer/tests/dynamics/dynamicsTests.js | 4 +- scripts/developer/tests/puck-attach.js | 2 +- scripts/developer/tests/sliderTestMain.js | 2 +- .../developer/tests/tabletEventBridgeTest.js | 4 +- scripts/developer/tests/tabletTest.js | 2 +- scripts/developer/utilities/audio/stats.js | 2 +- scripts/developer/utilities/render/luci.js | 2 +- .../render/photobooth/photoboothApp.js | 4 +- scripts/system/audio.js | 2 +- scripts/system/audioMuteOverlay.js | 2 +- scripts/system/audioScope.js | 4 +- scripts/system/bubble.js | 2 +- scripts/system/chat.js | 2 +- scripts/system/commerce/wallet.js | 2 +- scripts/system/controllers/godView.js | 4 +- scripts/system/edit.js | 14 +- scripts/system/fingerPaint.js | 4 +- scripts/system/generalSettings.js | 4 +- scripts/system/goto.js | 4 +- scripts/system/help.js | 4 +- scripts/system/hmd.js | 4 +- scripts/system/libraries/WebTablet.js | 6 +- scripts/system/libraries/entityList.js | 4 +- scripts/system/libraries/gridTool.js | 2 +- scripts/system/libraries/utils.js | 2 +- scripts/system/marketplaces/marketplace.js | 2 +- scripts/system/marketplaces/marketplaces.js | 4 +- scripts/system/menu.js | 2 +- scripts/system/mod.js | 2 +- scripts/system/notifications.js | 4 +- scripts/system/pal.js | 4 +- .../particle_explorer/particleExplorerTool.js | 2 +- scripts/system/snapshot.js | 4 +- scripts/system/tablet-goto.js | 4 +- scripts/system/tablet-ui/tabletUI.js | 6 +- scripts/system/tablet-users.js | 2 +- scripts/tutorials/createFloatingLanternBox.js | 2 +- scripts/tutorials/createTetherballStick.js | 2 +- .../entity_scripts/floatingLantern.js | 2 +- .../entity_scripts/floatingLanternBox.js | 2 +- .../entity_scripts/tetherballStick.js | 2 +- tests/shared/src/PathUtilsTests.cpp | 28 ++ tests/shared/src/PathUtilsTests.h | 20 ++ .../marketplace/blocks/blocksApp.js | 2 +- .../camera-move/app-camera-move.js | 4 +- .../marketplace/clap/clapApp.js | 2 +- .../app-doppleganger-attachments.js | 2 +- .../dist/app-doppleganger-marketplace.js | 2 +- .../doppleganger-mirror/app-doppleganger.js | 2 +- .../marketplace/emoji-tablet/emojiTablet.js | 2 +- .../marketplace/laser/laserPointerApp.js | 2 +- .../marketplace/record/record.js | 4 +- .../marketplace/shapes/shapes.js | 2 +- .../skyboxChanger/skyboxchanger.js | 2 +- .../spectator-camera/spectatorCamera.js | 4 +- .../tablet-raiseHand/tablet-raiseHand.js | 2 +- 91 files changed, 388 insertions(+), 436 deletions(-) delete mode 100644 interface/resources/qml/hifi/tablet/Tablet.qml create mode 100644 interface/resources/qml/hifi/tablet/TabletHome.qml create mode 100644 tests/shared/src/PathUtilsTests.cpp create mode 100644 tests/shared/src/PathUtilsTests.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 4c1b8d8d92..b3400c8dd0 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -12,8 +12,10 @@ function(JOIN VALUES GLUE OUTPUT) endfunction() -set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc) -generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg) +if (NOT DEV_BUILD) + set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc) + generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg) +endif() # set a default root dir for each of our optional externals if it was not passed set(OPTIONAL_EXTERNALS "LeapMotion") @@ -80,7 +82,9 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") # add them to the interface source files set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}") +if (NOT DEV_BUILD) list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC}) +endif() if (UNIX) install( diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 300bcd46f0..552291c186 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -248,7 +248,7 @@ Item { //dont rise local keyboard keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablet interface + //but rise Tablet's one instead for Tablets interface if (root.isTablet) { root.keyboardEnabled = HMD.active; root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index 9d55998b40..e521e16a60 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -221,7 +221,7 @@ Item { root.iconText = "<" //dont rise local keyboard keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablet interface + //but rise Tablet's one instead for Tablets interface if (root.isTablet) { root.keyboardEnabled = HMD.active; root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index 5c212578b8..185cbd9d47 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -131,7 +131,7 @@ Item { root.iconText = "<" //dont rise local keyboard keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablet interface + //but rise Tablet's one instead for Tablets interface if (root.isTablet) { root.keyboardEnabled = HMD.active; root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml index c068fdcfaf..a305bea8dc 100644 --- a/interface/resources/qml/controls-uit/Button.qml +++ b/interface/resources/qml/controls-uit/Button.qml @@ -29,12 +29,12 @@ Original.Button { onHoveredChanged: { if (hovered) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } style: ButtonStyle { diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index 22b25671c3..37bc936aa1 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -31,12 +31,12 @@ Original.CheckBox { activeFocusOnPress: true onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } // TODO: doesnt works for QQC1. check with QQC2 // onHovered: { -// tabletInterface.playSound(TabletEnums.ButtonHover); +// Tablets.playSound(TabletEnums.ButtonHover); // } style: CheckBoxStyle { diff --git a/interface/resources/qml/controls-uit/CheckBoxQQC2.qml b/interface/resources/qml/controls-uit/CheckBoxQQC2.qml index 32d69cf339..404d83ebd2 100644 --- a/interface/resources/qml/controls-uit/CheckBoxQQC2.qml +++ b/interface/resources/qml/controls-uit/CheckBoxQQC2.qml @@ -36,12 +36,12 @@ CheckBox { hoverEnabled: true onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } onHoveredChanged: { if (hovered) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } diff --git a/interface/resources/qml/controls-uit/GlyphButton.qml b/interface/resources/qml/controls-uit/GlyphButton.qml index bc7bc636fe..d225c8e1d1 100644 --- a/interface/resources/qml/controls-uit/GlyphButton.qml +++ b/interface/resources/qml/controls-uit/GlyphButton.qml @@ -27,12 +27,12 @@ Original.Button { onHoveredChanged: { if (hovered) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } style: ButtonStyle { diff --git a/interface/resources/qml/controls-uit/Key.qml b/interface/resources/qml/controls-uit/Key.qml index e54250c872..3ec579a4eb 100644 --- a/interface/resources/qml/controls-uit/Key.qml +++ b/interface/resources/qml/controls-uit/Key.qml @@ -35,13 +35,13 @@ Item { onContainsMouseChanged: { if (containsMouse) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } onClicked: { mouse.accepted = true; - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); webEntity.synthesizeKeyPress(glyph); webEntity.synthesizeKeyPress(glyph, mirrorText); diff --git a/interface/resources/qml/controls-uit/RadioButton.qml b/interface/resources/qml/controls-uit/RadioButton.qml index 65d36d2dcb..da4e944f35 100644 --- a/interface/resources/qml/controls-uit/RadioButton.qml +++ b/interface/resources/qml/controls-uit/RadioButton.qml @@ -30,12 +30,12 @@ Original.RadioButton { readonly property int checkRadius: 2 onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } // TODO: doesnt works for QQC1. check with QQC2 // onHovered: { -// tabletInterface.playSound(TabletEnums.ButtonHover); +// Tablets.playSound(TabletEnums.ButtonHover); // } style: RadioButtonStyle { diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml index cbc4d19334..9e1751ee51 100644 --- a/interface/resources/qml/controls/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/FlickableWebViewCore.qml @@ -41,7 +41,7 @@ Item { } if (WebEngineView.LoadFailedStatus === loadRequest.status) { - console.log(" Tablet WebEngineView failed to load url: " + loadRequest.url.toString()); + console.log("Tablet WebEngineView failed to load url: " + loadRequest.url.toString()); } if (WebEngineView.LoadSucceededStatus === loadRequest.status) { diff --git a/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml b/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml index 6d2ff36550..750ed0edd4 100644 --- a/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml +++ b/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml @@ -24,7 +24,7 @@ Item { }); object.selected.connect(function(button) { if (button === OriginalDialogs.StandardButton.Ok) { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); tablet.gotoHomeScreen() } }); diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 269788a808..5f1e9cd3bf 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -89,10 +89,10 @@ TabletModalWindow { //bodyLoader.active = false } if (gotoPreviousApp) { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); tablet.returnToPreviousApp(); } else { - Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); + Tablets.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); } } diff --git a/interface/resources/qml/dialogs/preferences/ButtonPreference.qml b/interface/resources/qml/dialogs/preferences/ButtonPreference.qml index 3a5c850031..bae581a47f 100644 --- a/interface/resources/qml/dialogs/preferences/ButtonPreference.qml +++ b/interface/resources/qml/dialogs/preferences/ButtonPreference.qml @@ -25,13 +25,13 @@ Preference { id: button onHoveredChanged: { if (hovered) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } onClicked: { preference.trigger(); - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } width: 180 anchors.bottom: parent.bottom diff --git a/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml b/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml index 8904896ab7..81884d9a72 100644 --- a/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml +++ b/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml @@ -41,12 +41,12 @@ Preference { id: checkBox onHoveredChanged: { if (hovered) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } anchors { diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index fc7b8c6200..8d69afab46 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -246,12 +246,12 @@ Item { anchors.fill: parent; acceptedButtons: Qt.LeftButton; onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); goFunction("hifi://" + hifiUrl); } hoverEnabled: true; onEntered: { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); hoverThunk(); } onExited: unhoverThunk(); @@ -269,7 +269,7 @@ Item { } } function go() { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId)); } MouseArea { diff --git a/interface/resources/qml/hifi/audio/MicBar.qml b/interface/resources/qml/hifi/audio/MicBar.qml index b6699d6ceb..9ef8bf3698 100644 --- a/interface/resources/qml/hifi/audio/MicBar.qml +++ b/interface/resources/qml/hifi/audio/MicBar.qml @@ -61,12 +61,12 @@ Rectangle { scrollGestureEnabled: false; onClicked: { Audio.muted = !Audio.muted; - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } drag.target: dragTarget; onContainsMouseChanged: { if (containsMouse) { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); } } } diff --git a/interface/resources/qml/hifi/tablet/NewEntityButton.qml b/interface/resources/qml/hifi/tablet/NewEntityButton.qml index 7f838717df..49fdb4368f 100644 --- a/interface/resources/qml/hifi/tablet/NewEntityButton.qml +++ b/interface/resources/qml/hifi/tablet/NewEntityButton.qml @@ -123,11 +123,11 @@ Item { hoverEnabled: true enabled: true onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); newEntityButton.clicked(); } onEntered: { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); newEntityButton.state = "hover state"; } onExited: { diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml deleted file mode 100644 index b21bf9c506..0000000000 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ /dev/null @@ -1,280 +0,0 @@ -import QtQuick 2.5 -import QtGraphicalEffects 1.0 -import QtQuick.Layouts 1.3 - -import "." -import "../../styles-uit" -import "../audio" as HifiAudio - -Item { - id: tablet - objectName: "tablet" - property int rowIndex: 0 - property int columnIndex: 0 - property int count: (flowMain.children.length - 1) - - Component { - id: buttonComponent - TabletButton { } - } - - Component.onCompleted: { - tablet.populateButtons(); - } - - function createClickedHandler(proxy) { - return function() { proxy.clicked(); } - } - - function populateButtons() { - var tabletProxy = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var buttons = tabletProxy.getButtons(); - for (var i = 0; i < buttons.length; i++) { - var proxy = buttons[i]; - var button = tablet.addButtonProxy(proxy.getProperties()); - button.clicked.connect(createClickedHandler(proxy)); - proxy.setQmlButton(button); - } - sortButtons(); - } - - // used to look up a button by its uuid - function findButtonIndex(uuid) { - if (!uuid) { - return -1; - } - - for (var i in flowMain.children) { - var child = flowMain.children[i]; - if (child.uuid === uuid) { - return i; - } - } - return -1; - } - - function sortButtons() { - var children = []; - for (var i = 0; i < flowMain.children.length; i++) { - children[i] = flowMain.children[i]; - } - - children.sort(function (a, b) { - if (a.sortOrder === b.sortOrder) { - // subsort by stableOrder, because JS sort is not stable in qml. - return a.stableOrder - b.stableOrder; - } else { - return a.sortOrder - b.sortOrder; - } - }); - - flowMain.children = children; - } - - // called by C++ code when a button should be added to the tablet - function addButtonProxy(properties) { - var button = buttonComponent.createObject(flowMain); - // copy all properites to button - var keys = Object.keys(properties).forEach(function (key) { - button[key] = properties[key]; - }); - - // pass a reference to the tabletRoot object to the button. - if (tabletRoot) { - button.tabletRoot = tabletRoot; - } else { - button.tabletRoot = parent.parent; - } - - return button; - } - - // called by C++ code when a button should be removed from the tablet - function removeButtonProxy(properties) { - var index = findButtonIndex(properties.uuid); - if (index < 0) { - console.log("Warning: Tablet.qml could not find button with uuid = " + properties.uuid); - } else { - flowMain.children[index].destroy(); - } - } - - Rectangle { - id: bgTopBar - height: 90 - - anchors { - top: parent.top - left: parent.left - right: parent.right - } - - gradient: Gradient { - GradientStop { - position: 0 - color: "#2b2b2b" - } - - GradientStop { - position: 1 - color: "#1e1e1e" - } - } - - HifiAudio.MicBar { - anchors { - left: parent.left - leftMargin: 30 - verticalCenter: parent.verticalCenter - } - } - - Item { - width: 150 - height: 50 - anchors.right: parent.right - anchors.rightMargin: 30 - anchors.verticalCenter: parent.verticalCenter - - ColumnLayout { - anchors.fill: parent - - RalewaySemiBold { - text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in") - horizontalAlignment: Text.AlignRight - anchors.right: parent.right - font.pixelSize: 20 - color: "#afafaf" - } - - RalewaySemiBold { - visible: Account.loggedIn - height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0 - text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : "" - horizontalAlignment: Text.AlignRight - anchors.right: parent.right - font.pixelSize: 20 - color: "#afafaf" - } - } - - MouseArea { - anchors.fill: parent - onClicked: { - if (!Account.loggedIn) { - DialogsManager.showLoginDialog() - } else { - Account.logOut() - } - } - } - } - } - - Rectangle { - id: bgMain - gradient: Gradient { - GradientStop { - position: 0 - color: "#2b2b2b" - } - - GradientStop { - position: 1 - color: "#0f212e" - } - } - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.top: bgTopBar.bottom - anchors.topMargin: 0 - - Flickable { - id: flickable - width: parent.width - height: parent.height - contentWidth: parent.width - contentHeight: flowMain.childrenRect.height + flowMain.anchors.topMargin + flowMain.anchors.bottomMargin + flowMain.spacing - clip: true - Flow { - id: flowMain - spacing: 16 - anchors.right: parent.right - anchors.rightMargin: 30 - anchors.left: parent.left - anchors.leftMargin: 30 - anchors.bottom: parent.bottom - anchors.bottomMargin: 30 - anchors.top: parent.top - anchors.topMargin: 30 - } - } - } - - function setCurrentItemState(state) { - var index = rowIndex + columnIndex; - - if (index >= 0 && index <= count ) { - flowMain.children[index].state = state; - } - } - - function nextItem() { - setCurrentItemState("base state"); - var nextColumnIndex = (columnIndex + 3 + 1) % 3; - var nextIndex = rowIndex + nextColumnIndex; - if(nextIndex <= count) { - columnIndex = nextColumnIndex; - }; - setCurrentItemState("hover state"); - } - - function previousItem() { - setCurrentItemState("base state"); - var prevIndex = (columnIndex + 3 - 1) % 3; - if((rowIndex + prevIndex) <= count){ - columnIndex = prevIndex; - } - setCurrentItemState("hover state"); - } - - function upItem() { - setCurrentItemState("base state"); - rowIndex = rowIndex - 3; - if (rowIndex < 0 ) { - rowIndex = (count - (count % 3)); - var index = rowIndex + columnIndex; - if(index > count) { - rowIndex = rowIndex - 3; - } - } - setCurrentItemState("hover state"); - } - - function downItem() { - setCurrentItemState("base state"); - rowIndex = rowIndex + 3; - var index = rowIndex + columnIndex; - if (index > count ) { - rowIndex = 0; - } - setCurrentItemState("hover state"); - } - - function selectItem() { - flowMain.children[rowIndex + columnIndex].clicked(); - if (tabletRoot) { - tabletRoot.playButtonClickSound(); - } - } - - Keys.onRightPressed: nextItem(); - Keys.onLeftPressed: previousItem(); - Keys.onDownPressed: downItem(); - Keys.onUpPressed: upItem(); - Keys.onReturnPressed: selectItem(); -} diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 4d9a83817a..3242de89b1 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -72,7 +72,7 @@ StackView { addressLine.focus = !HMD.active; root.parentChanged.connect(center); center(); - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); } Component.onDestruction: { root.parentChanged.disconnect(center); @@ -149,7 +149,7 @@ StackView { onClicked: { addressBarDialog.loadHome(); tabletRoot.shown = false; - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); tablet.gotoHomeScreen(); } anchors { diff --git a/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml b/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml index 19548365aa..14d7d09dba 100644 --- a/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml @@ -37,7 +37,7 @@ Item { } function closeDialog() { - Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); + Tablets.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); } anchors.topMargin: hifi.dimensions.tabletMenuHeader // Space for header. diff --git a/interface/resources/qml/hifi/tablet/TabletButton.qml b/interface/resources/qml/hifi/tablet/TabletButton.qml index 169c7acec1..3a66738b82 100644 --- a/interface/resources/qml/hifi/tablet/TabletButton.qml +++ b/interface/resources/qml/hifi/tablet/TabletButton.qml @@ -121,7 +121,6 @@ Item { enabled: true preventStealing: true onClicked: { - console.log("Tablet Button Clicked!"); if (tabletButton.inDebugMode) { if (tabletButton.isActive) { tabletButton.isActive = false; @@ -131,12 +130,12 @@ Item { } tabletButton.clicked(); if (tabletRoot) { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); } } onEntered: { tabletButton.isEntered = true; - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); if (tabletButton.isActive) { tabletButton.state = "hover active state"; diff --git a/interface/resources/qml/hifi/tablet/TabletHome.qml b/interface/resources/qml/hifi/tablet/TabletHome.qml new file mode 100644 index 0000000000..0b30496c44 --- /dev/null +++ b/interface/resources/qml/hifi/tablet/TabletHome.qml @@ -0,0 +1,159 @@ +import QtQuick 2.5 +import QtGraphicalEffects 1.0 +import QtQuick.Layouts 1.3 + +import "." +import "../../styles-uit" +import "../audio" as HifiAudio + +Item { + id: tablet + objectName: "tablet" + property var tabletProxy: Tablets.getTablet("com.highfidelity.interface.tablet.system"); + + Rectangle { + id: bgTopBar + height: 90 + + anchors { + top: parent.top + left: parent.left + right: parent.right + } + + gradient: Gradient { + GradientStop { + position: 0 + color: "#2b2b2b" + } + + GradientStop { + position: 1 + color: "#1e1e1e" + } + } + + HifiAudio.MicBar { + anchors { + left: parent.left + leftMargin: 30 + verticalCenter: parent.verticalCenter + } + } + + Item { + width: 150 + height: 50 + anchors.right: parent.right + anchors.rightMargin: 30 + anchors.verticalCenter: parent.verticalCenter + + ColumnLayout { + anchors.fill: parent + + RalewaySemiBold { + text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in") + horizontalAlignment: Text.AlignRight + anchors.right: parent.right + font.pixelSize: 20 + color: "#afafaf" + } + + RalewaySemiBold { + visible: Account.loggedIn + height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0 + text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : "" + horizontalAlignment: Text.AlignRight + anchors.right: parent.right + font.pixelSize: 20 + color: "#afafaf" + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (!Account.loggedIn) { + DialogsManager.showLoginDialog() + } else { + Account.logOut() + } + } + } + } + } + + Rectangle { + id: bgMain + clip: true + gradient: Gradient { + GradientStop { + position: 0 + color: "#2b2b2b" + } + + GradientStop { + position: 1 + color: "#0f212e" + } + } + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.left: parent.left + anchors.top: bgTopBar.bottom + + GridView { + id: flickable + anchors.top: parent.top + anchors.topMargin: 15 + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + width: cellWidth * 3 + cellHeight: 145 + cellWidth: 145 + model: tabletProxy.buttons + delegate: Item { + width: flickable.cellWidth + height: flickable.cellHeight + property var proxy: modelData + + TabletButton { + id: tabletButton + anchors.centerIn: parent + onClicked: modelData.clicked() + state: wrapper.GridView.isCurrentItem ? "hover state" : "base state" + } + + Connections { + target: modelData; + onPropertiesChanged: { + updateProperties(); + } + } + + Component.onCompleted: updateProperties() + + function updateProperties() { + var keys = Object.keys(modelData.properties).forEach(function (key) { + if (tabletButton[key] !== modelData.properties[key]) { + tabletButton[key] = modelData.properties[key]; + } + }); + } + } + } + } + + Keys.onRightPressed: flickable.moveCurrentIndexRight(); + Keys.onLeftPressed: flickable.moveCurrentIndexLeft(); + Keys.onDownPressed: flickable.moveCurrentIndexDown(); + Keys.onUpPressed: flickable.moveCurrentIndexUp(); + Keys.onReturnPressed: { + if (flickable.currentItem) { + flickable.currentItem.proxy.clicked(); + if (tabletRoot) { + tabletRoot.playButtonClickSound(); + } + } + } +} diff --git a/interface/resources/qml/hifi/tablet/TabletMenuView.qml b/interface/resources/qml/hifi/tablet/TabletMenuView.qml index 4a4a6b7f87..e069ce8cb1 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuView.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuView.qml @@ -77,12 +77,12 @@ FocusScope { anchors.fill: parent hoverEnabled: true onEntered: { - tabletInterface.playSound(TabletEnums.ButtonHover); + Tablets.playSound(TabletEnums.ButtonHover); listView.currentIndex = index } onClicked: { - tabletInterface.playSound(TabletEnums.ButtonClick); + Tablets.playSound(TabletEnums.ButtonClick); root.selected(item); } } diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index fcb3e9ff92..0665b9971e 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -56,7 +56,7 @@ Item { } function closeDialog() { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (gotoPreviousApp) { tablet.returnToPreviousApp(); @@ -206,7 +206,7 @@ Item { } Component.onCompleted: { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); keyboardEnabled = HMD.active; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 929184fc14..30d93482f8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2214,12 +2214,12 @@ extern void setupPreferences(); void Application::initializeUi() { // Make sure all QML surfaces share the main thread GL context OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext()); - OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "qrc:///qml/OverlayWindowTest.qml" }, + OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "OverlayWindowTest.qml" }, [](QQmlContext* context) { qDebug() << "Whitelist OverlayWindow worked"; context->setContextProperty("OverlayWindowTestString", "TestWorked"); }); - OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "qrc:///qml/hifi/audio/Audio.qml" }, + OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "hifi/audio/Audio.qml" }, [](QQmlContext* context) { qDebug() << "QQQ" << __FUNCTION__ << "Whitelist Audio worked"; }); @@ -2310,9 +2310,6 @@ void Application::initializeUi() { surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get().data()); surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); - surfaceContext->setContextProperty("Tablet", DependencyManager::get().data()); - // Tablet inteference with Tablet.qml. Need to avoid this in QML space - surfaceContext->setContextProperty("tabletInterface", DependencyManager::get().data()); surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); surfaceContext->setContextProperty("FaceTracker", DependencyManager::get().data()); @@ -5807,7 +5804,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); - // Tablet inteference with Tablet.qml. Need to avoid this in QML space + scriptEngine->registerGlobalObject("Tablets", DependencyManager::get().data()); + // FIXME remove these deprecated names for the tablet scripting interface scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Tablet", DependencyManager::get().data()); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index d418a79fbf..07a953c219 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -209,7 +209,6 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper()); _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); _webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get().data()); @@ -228,9 +227,6 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../"); - // Tablet inteference with Tablet.qml. Need to avoid this in QML space - _webSurface->getSurfaceContext()->setContextProperty("tabletInterface", DependencyManager::get().data()); - tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data()); // mark the TabletProxy object as cpp ownership. QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 4184351c2d..092afe1a90 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -217,8 +217,6 @@ gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, co if (!result) { _texturesByHashes[hash] = texture; result = texture; - } else { - qCWarning(modelnetworking) << "QQQ Swapping out texture with previous live texture in hash " << hash.c_str(); } } return result; diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 7563122290..3190f25d7e 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -9,10 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#endif - #include #include #include diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp index 46613f1283..00a11ef06c 100644 --- a/libraries/shared/src/PathUtils.cpp +++ b/libraries/shared/src/PathUtils.cpp @@ -24,9 +24,30 @@ const QString& PathUtils::resourcesPath() { #ifdef Q_OS_MAC - static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; + static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; #else - static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; + static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; +#endif + return staticResourcePath; +} + +#ifdef DEV_BUILD +const QString& PathUtils::projectRootPath() { + static QString sourceFolder; + static std::once_flag once; + std::call_once(once, [&] { + QDir thisDir = QFileInfo(__FILE__).absoluteDir(); + sourceFolder = QDir::cleanPath(thisDir.absoluteFilePath("../../../")); + }); + return sourceFolder; +} +#endif + +const QString& PathUtils::qmlBasePath() { +#ifdef DEV_BUILD + static const QString staticResourcePath = QUrl::fromLocalFile(projectRootPath() + "/interface/resources/qml/").toString(); +#else + static const QString staticResourcePath = "qrc:///qml/"; #endif return staticResourcePath; diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index 8c4bcf2394..9b5b6ef67f 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -30,6 +30,10 @@ class PathUtils : public QObject, public Dependency { Q_PROPERTY(QUrl defaultScripts READ defaultScriptsLocation CONSTANT) public: static const QString& resourcesPath(); + static const QString& qmlBasePath(); +#ifdef DEV_BUILD + static const QString& projectRootPath(); +#endif static QString getAppDataPath(); static QString getAppLocalDataPath(); diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 8711e52eff..aab89ccd4d 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -48,6 +48,7 @@ #include "types/SoundEffect.h" #include "TabletScriptingInterface.h" +#include "ToolbarScriptingInterface.h" #include "Logging.h" Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml") @@ -62,7 +63,10 @@ public: void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback) { withWriteLock([&] { - for (const auto& url : urls) { + for (auto url : urls) { + if (url.isRelative()) { + url = QUrl(PathUtils::qmlBasePath() + url.toString()); + } _callbacks[url].push_back(callback); } }); @@ -382,6 +386,13 @@ void initializeQmlEngine(QQmlEngine* engine, QQuickWindow* window) { rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext)); rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext)); rootContext->setContextProperty("Paths", DependencyManager::get().data()); + static std::once_flag once; + std::call_once(once, [&] { + qRegisterMetaType(); + qRegisterMetaType(); + }); + rootContext->setContextProperty("Tablets", DependencyManager::get().data()); + rootContext->setContextProperty("Toolbars", DependencyManager::get().data()); } QQmlEngine* acquireEngine(QQuickWindow* window) { @@ -587,7 +598,7 @@ void OffscreenQmlSurface::create() { auto qmlEngine = acquireEngine(_quickWindow); _qmlContext = new QQmlContext(qmlEngine->rootContext()); - _qmlContext->setBaseUrl(QUrl{ "qrc:///qml/" }); + _qmlContext->setBaseUrl(QUrl{ PathUtils::qmlBasePath() }); _qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); _qmlContext->setContextProperty("eventBridge", this); _qmlContext->setContextProperty("webEntity", this); @@ -715,7 +726,6 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, con } void OffscreenQmlSurface::loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback) { - qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << qmlSource; if (QThread::currentThread() != thread()) { qCWarning(uiLogging) << "Called load on a non-surface thread"; } @@ -725,7 +735,6 @@ void OffscreenQmlSurface::loadInternal(const QUrl& qmlSource, bool createNewCont QUrl finalQmlSource = qmlSource; if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) { finalQmlSource = _qmlContext->resolvedUrl(qmlSource); - qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << "resolved to " << finalQmlSource; } auto targetContext = contextForUrl(finalQmlSource, createNewContext); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 7440d0b5d0..93d493539e 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -210,7 +210,7 @@ QObject* TabletScriptingInterface::getFlags() { // TabletProxy // -static const char* TABLET_SOURCE_URL = "hifi/tablet/Tablet.qml"; +static const char* TABLET_HOME_SOURCE_URL = "hifi/tablet/TabletHome.qml"; static const char* WEB_VIEW_SOURCE_URL = "hifi/tablet/TabletWebView.qml"; static const char* VRMENU_SOURCE_URL = "hifi/tablet/TabletMenu.qml"; @@ -274,7 +274,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { } else { removeButtonsFromToolbar(); - if (_currentPathLoaded == TABLET_SOURCE_URL) { + if (_currentPathLoaded == TABLET_HOME_SOURCE_URL) { // Tablet QML now pulls buttons from Tablet proxy } else { loadHomeScreen(true); @@ -408,7 +408,7 @@ void TabletProxy::setQmlTabletRoot(OffscreenQmlSurface* qmlOffscreenSurface) { }); if (_toolbarMode) { - QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); + QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_HOME_SOURCE_URL))); } // force to the tablet to go to the homescreen @@ -618,7 +618,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) { if ((_state != State::Home && _state != State::Uninitialized) || forceOntoHomeScreen) { if (!_toolbarMode && _qmlTabletRoot) { - QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); + QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_HOME_SOURCE_URL))); QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound"); } else if (_toolbarMode && _desktopWindow) { // close desktop window @@ -627,8 +627,8 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) { } } _state = State::Home; - emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL)); - _currentPathLoaded = TABLET_SOURCE_URL; + emit screenChanged(QVariant("Home"), QVariant(TABLET_HOME_SOURCE_URL)); + _currentPathLoaded = TABLET_HOME_SOURCE_URL; } } diff --git a/scripts/developer/EZrecord.js b/scripts/developer/EZrecord.js index 7fdebada79..3cfc6e9928 100644 --- a/scripts/developer/EZrecord.js +++ b/scripts/developer/EZrecord.js @@ -227,14 +227,14 @@ } function setUp() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } Recorder.setUp(); - // Tablet/toolbar button. + // tablet/toolbar button. button = tablet.addButton({ icon: APP_ICON_INACTIVE, activeIcon: APP_ICON_ACTIVE, diff --git a/scripts/developer/inputRecording.js b/scripts/developer/inputRecording.js index 6fb8e471cd..574cbbeb3d 100644 --- a/scripts/developer/inputRecording.js +++ b/scripts/developer/inputRecording.js @@ -10,7 +10,7 @@ var recording = false; var onRecordingScreen = false; var passedSaveDirectory = false; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: "IRecord" }); diff --git a/scripts/developer/tests/dynamics/dynamicsTests.js b/scripts/developer/tests/dynamics/dynamicsTests.js index c0b001eab3..be22e2c5fb 100644 --- a/scripts/developer/tests/dynamics/dynamicsTests.js +++ b/scripts/developer/tests/dynamics/dynamicsTests.js @@ -11,14 +11,14 @@ "use strict"; -/* global Entities, Script, Tablet, MyAvatar, Vec3 */ +/* global Entities, Script, Tablets, MyAvatar, Vec3 */ (function() { // BEGIN LOCAL_SCOPE var DYNAMICS_TESTS_URL = Script.resolvePath("dynamics-tests.html"); var DEFAULT_LIFETIME = 120; // seconds - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: Script.resolvePath("dynamicsTests.svg"), diff --git a/scripts/developer/tests/puck-attach.js b/scripts/developer/tests/puck-attach.js index 04d5db5710..6971ec02cd 100644 --- a/scripts/developer/tests/puck-attach.js +++ b/scripts/developer/tests/puck-attach.js @@ -19,7 +19,7 @@ Script.include("/~/system/libraries/Xform.js"); var TABLET_BUTTON_NAME = "PUCKTACH"; var TABLET_APP_URL = "https://hifi-content.s3.amazonaws.com/seefo/production/puck-attach/puck-attach.html"; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var tabletButton = tablet.addButton({ text: TABLET_BUTTON_NAME, icon: "https://s3.amazonaws.com/hifi-public/tony/icons/puck-i.svg", diff --git a/scripts/developer/tests/sliderTestMain.js b/scripts/developer/tests/sliderTestMain.js index 22bf4fa911..e7542ef177 100644 --- a/scripts/developer/tests/sliderTestMain.js +++ b/scripts/developer/tests/sliderTestMain.js @@ -1,6 +1,6 @@ (function () { var HTML_URL = Script.resolvePath("sliderTest.html"); - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: "SLIDER" }); diff --git a/scripts/developer/tests/tabletEventBridgeTest.js b/scripts/developer/tests/tabletEventBridgeTest.js index 83031741fc..3f988303f2 100644 --- a/scripts/developer/tests/tabletEventBridgeTest.js +++ b/scripts/developer/tests/tabletEventBridgeTest.js @@ -11,10 +11,10 @@ // Adds a button to the tablet that will switch to a web page. // This web page contains buttons that will use the event bridge to trigger sounds. -/* globals Tablet */ +/* globals Tablets */ -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var tabletButton = tablet.addButton({ text: "SOUNDS", icon: "http://s3.amazonaws.com/hifi-public/tony/icons/trombone-i.png", diff --git a/scripts/developer/tests/tabletTest.js b/scripts/developer/tests/tabletTest.js index 438d0a4b99..9c1ce0e3bd 100644 --- a/scripts/developer/tests/tabletTest.js +++ b/scripts/developer/tests/tabletTest.js @@ -10,7 +10,7 @@ // Adds a BAM! button to the tablet ui. -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: "BAM!!!" }); diff --git a/scripts/developer/utilities/audio/stats.js b/scripts/developer/utilities/audio/stats.js index 382e14df5f..a828d79340 100644 --- a/scripts/developer/utilities/audio/stats.js +++ b/scripts/developer/utilities/audio/stats.js @@ -10,7 +10,7 @@ // if (HMD.active && !Settings.getValue("HUDUIEnabled")) { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var qml = Script.resolvePath("TabletStats.qml"); tablet.loadQMLSource(qml); Script.stop(); diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index 1e2ac1261f..b2203ce72f 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -27,7 +27,7 @@ } } - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: TABLET_BUTTON_NAME, icon: ICON_URL, diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 154028f091..375a98e543 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -8,7 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablet, Toolbars, Script, HMD, Controller, Menu */ +/* globals Tablets, Toolbars, Script, HMD, Controller, Menu */ (function () { var SNAPSHOT_DELAY = 500; // 500ms var PHOTOBOOTH_WINDOW_HTML_URL = Script.resolvePath("./html/photobooth.html"); @@ -16,7 +16,7 @@ var MODEL_BOUNDING_BOX_DIMENSIONS = {x: 1.0174,y: 1.1925,z: 1.0165}; var PhotoBooth = {}; var photoboothCreated = false; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/snap-i.svg", text: "PHOTOBOOTH" diff --git a/scripts/system/audio.js b/scripts/system/audio.js index a93177ca38..ea0626a30c 100644 --- a/scripts/system/audio.js +++ b/scripts/system/audio.js @@ -54,7 +54,7 @@ function onScreenChanged(type, url) { button.editProperties({isActive: onAudioScreen}); } -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: Audio.muted ? MUTE_ICONS.icon : UNMUTE_ICONS.icon, activeIcon: Audio.muted ? MUTE_ICONS.activeIcon : UNMUTE_ICONS.activeIcon, diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 731d62017d..0db4edb85d 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // audioMuteOverlay.js diff --git a/scripts/system/audioScope.js b/scripts/system/audioScope.js index 81d8e8fbd4..268c883983 100644 --- a/scripts/system/audioScope.js +++ b/scripts/system/audioScope.js @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, Tablet, AudioScope, Audio */ +/* global Script, Tablets, AudioScope, Audio */ (function () { // BEGIN LOCAL_SCOPE @@ -17,7 +17,7 @@ var scopePaused = AudioScope.getPause(); var autoPause = false; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var showScopeButton = tablet.addButton({ icon: "icons/tablet-icons/scope.svg", text: "Audio Scope", diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index 4ea684ff06..2b6924d84f 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -183,7 +183,7 @@ // Setup the bubble button var buttonName = "BUBBLE"; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ icon: "icons/tablet-icons/bubble-i.svg", activeIcon: "icons/tablet-icons/bubble-a.svg", diff --git a/scripts/system/chat.js b/scripts/system/chat.js index fa997e20cc..220c87195a 100644 --- a/scripts/system/chat.js +++ b/scripts/system/chat.js @@ -19,7 +19,7 @@ var tabletButtonIcon = "icons/tablet-icons/menu-i.svg"; // Icon for chat button. var tabletButtonActiveIcon = "icons/tablet-icons/menu-a.svg"; // Active icon for chat button. var tabletButton = null; // The button we create in the tablet. - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); // The awesome tablet. + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); // The awesome tablet. var chatLog = []; // Array of chat messages in the form of [avatarID, displayName, message, data]. var avatarIdentifiers = {}; // Map of avatar ids to dict of identifierParams. var speechBubbleShowing = false; // Is the speech bubble visible? diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 9b2367b762..7f05dcf3d8 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -148,7 +148,7 @@ var walletEnabled = Settings.getValue("commerce", false); function startup() { if (walletEnabled) { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ text: buttonName, icon: "icons/tablet-icons/wallet-i.svg", diff --git a/scripts/system/controllers/godView.js b/scripts/system/controllers/godView.js index 4b406399fd..eb38308cb9 100644 --- a/scripts/system/controllers/godView.js +++ b/scripts/system/controllers/godView.js @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals HMD, Script, Menu, Tablet, Camera */ +/* globals HMD, Script, Menu, Tablets, Camera */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function() { // BEGIN LOCAL_SCOPE @@ -81,7 +81,7 @@ function endGodView() { } var button; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); function onClicked() { if (godView) { diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 2bbd422c65..abd69e2697 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -11,7 +11,7 @@ // /* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, Overlays, OverlayWebWindow, UserActivityLogger, - Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool */ + Settings, Entities, Tablets, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool */ (function() { // BEGIN LOCAL_SCOPE @@ -390,7 +390,7 @@ var toolBar = (function () { } function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); tablet.popFromStack(); switch (message.method) { case "newModelDialogAdd": @@ -417,7 +417,7 @@ var toolBar = (function () { var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); activeButton = tablet.addButton({ captionColorOverride: hasRezPermissions ? "" : "#888888", icon: createButtonIconRsrc, @@ -463,7 +463,7 @@ var toolBar = (function () { var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; // tablet version of new-model dialog - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); tablet.pushOntoStack("NewModelDialog.qml"); }); @@ -644,7 +644,7 @@ var toolBar = (function () { isActive = active; activeButton.editProperties({isActive: isActive}); - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (!isActive) { entityListTool.setVisible(false); @@ -1850,7 +1850,7 @@ var PropertiesTool = function (opts) { var that = {}; var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); webView.setVisible = function(value) {}; var visible = false; @@ -2293,7 +2293,7 @@ function selectParticleEntity(entityID) { particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); // Switch to particle explorer - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); tablet.sendToQml({method: 'selectTab', params: {id: 'particle'}}); } diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 88245503e8..ad4973890b 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -414,12 +414,12 @@ } function setUp() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } - // Tablet button. + // Tablets button. button = tablet.addButton({ icon: "icons/tablet-icons/finger-paint-i.svg", activeIcon: "icons/tablet-icons/finger-paint-a.svg", diff --git a/scripts/system/generalSettings.js b/scripts/system/generalSettings.js index 082528ffc5..8a9001107a 100644 --- a/scripts/system/generalSettings.js +++ b/scripts/system/generalSettings.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ +/* globals Tablets, Toolbars, Script, HMD, DialogsManager */ (function() { // BEGIN LOCAL_SCOPE @@ -34,7 +34,7 @@ alpha: 0.9 }); } else { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ icon: "icons/tablet-icons/goto-i.svg", text: buttonName, diff --git a/scripts/system/goto.js b/scripts/system/goto.js index d364bf579e..31394c8750 100644 --- a/scripts/system/goto.js +++ b/scripts/system/goto.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ +/* globals Tablets, Toolbars, Script, HMD, DialogsManager */ (function() { // BEGIN LOCAL_SCOPE @@ -37,7 +37,7 @@ if (Settings.getValue("HUDUIEnabled")) { alpha: 0.9 }); } else { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ icon: "icons/tablet-icons/goto-i.svg", activeIcon: "icons/tablet-icons/goto-a.svg", diff --git a/scripts/system/help.js b/scripts/system/help.js index 9ab7fa3fb3..5687c8961f 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -10,14 +10,14 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablet, Script, HMD, Controller, Menu */ +/* globals Tablets, Script, HMD, Controller, Menu */ (function() { // BEGIN LOCAL_SCOPE var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; var buttonName = "HELP"; var onHelpScreen = false; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/help-i.svg", activeIcon: "icons/tablet-icons/help-a.svg", diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index b9fd7f725c..a86bbd9a62 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals HMD, Script, Menu, Tablet, Camera */ +/* globals HMD, Script, Menu, Tablets, Camera */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function() { // BEGIN LOCAL_SCOPE @@ -38,7 +38,7 @@ function updateControllerDisplay() { } var button; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); // Independent and Entity mode make people sick; disable them in hmd. var desktopOnlyViews = ['Independent Mode', 'Entity Mode']; diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index c46cfaa073..cd7c575205 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -7,7 +7,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global getControllerWorldLocation, Tablet, WebTablet:true, HMD, Settings, Script, +/* global getControllerWorldLocation, Tablets, WebTablet:true, HMD, Settings, Script, Vec3, Quat, MyAvatar, Entities, Overlays, Camera, Messages, Xform, clamp, Controller, Mat4, resizeTablet */ Script.include(Script.resolvePath("../libraries/utils.js")); @@ -168,7 +168,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { this.receive = function (channel, senderID, senderUUID, localOnly) { if (_this.homeButtonID == senderID) { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var onHomeScreen = tablet.onHomeScreen(); var isMessageOpen; if (onHomeScreen) { @@ -513,7 +513,7 @@ WebTablet.prototype.mousePressEvent = function (event) { entityPickResults.overlayID === this.tabletEntityID)) { var overlayPickResults = Overlays.findRayIntersection(pickRay, true, [this.webOverlayID, this.homeButtonID], []); if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var onHomeScreen = tablet.onHomeScreen(); var isMessageOpen = tablet.isMessageDialogOpen(); if (onHomeScreen) { diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index 9d9689000e..a1f5d31a1a 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -8,14 +8,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, +/* global EntityListTool, Tablets, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */ EntityListTool = function(opts) { var that = {}; var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); webView.setVisible = function(value) {}; var filterInView = false; diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 2c417a9dde..41cbc59502 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -237,7 +237,7 @@ GridTool = function(opts) { var listeners = []; var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); webView.setVisible = function(value) {}; horizontalGrid.addListener(function(data) { diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index 76c248d880..8ea176bbd4 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -354,7 +354,7 @@ flatten = function(array) { getTabletWidthFromSettings = function () { var DEFAULT_TABLET_WIDTH = 0.4375; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var toolbarMode = tablet.toolbarMode; var DEFAULT_TABLET_SCALE = 100; var tabletScalePercentage = DEFAULT_TABLET_SCALE; diff --git a/scripts/system/marketplaces/marketplace.js b/scripts/system/marketplaces/marketplace.js index d90695c767..6d6550ecbc 100644 --- a/scripts/system/marketplaces/marketplace.js +++ b/scripts/system/marketplaces/marketplace.js @@ -82,7 +82,7 @@ function toggleMarketplace() { } } -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var browseExamplesButton = tablet.addButton({ icon: "icons/tablet-icons/market-i.svg", diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index b427739292..a831d761d2 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Tablet, Script, HMD, UserActivityLogger, Entities */ +/* global Tablets, Script, HMD, UserActivityLogger, Entities */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function () { // BEGIN LOCAL_SCOPE @@ -81,7 +81,7 @@ } } - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var marketplaceButton = tablet.addButton({ icon: "icons/tablet-icons/market-i.svg", activeIcon: "icons/tablet-icons/market-a.svg", diff --git a/scripts/system/menu.js b/scripts/system/menu.js index c7a44d3e48..004ece17c3 100644 --- a/scripts/system/menu.js +++ b/scripts/system/menu.js @@ -13,7 +13,7 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet- // var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; (function() { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/menu-i.svg", activeIcon: "icons/tablet-icons/menu-a.svg", diff --git a/scripts/system/mod.js b/scripts/system/mod.js index a3b4974f8d..defdb662b3 100644 --- a/scripts/system/mod.js +++ b/scripts/system/mod.js @@ -18,7 +18,7 @@ Script.include("/~/system/libraries/controllers.js"); // grab the toolbar -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var ASSETS_PATH = Script.resolvePath("assets"); var TOOLS_PATH = Script.resolvePath("assets/images/tools/"); diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index b6ddd9d33e..612c0e50e2 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Script, Settings, Window, Controller, Overlays, SoundArray, LODManager, MyAvatar, Tablet, Camera, HMD, Menu, Quat, Vec3*/ +/*global Script, Settings, Window, Controller, Overlays, SoundArray, LODManager, MyAvatar, Tablets, Camera, HMD, Menu, Quat, Vec3*/ // // notifications.js // Version 0.801 @@ -696,7 +696,7 @@ Window.announcement.connect(onNotify); Window.notifyEditError = onEditError; Window.notify = onNotify; - Tablet.tabletNotification.connect(tabletNotification); + Tablets.tabletNotification.connect(tabletNotification); Wallet.walletNotSetup.connect(walletNotSetup); Messages.subscribe(NOTIFICATIONS_MESSAGE_CHANNEL); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 05a7dc8975..26bec518b4 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Tablet, Settings, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, HMD, Controller, Account, UserActivityLogger, Messages, Window, XMLHttpRequest, print, location, getControllerWorldLocation*/ +/*global Tablets, Settings, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, HMD, Controller, Account, UserActivityLogger, Messages, Window, XMLHttpRequest, print, location, getControllerWorldLocation*/ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // pal.js @@ -677,7 +677,7 @@ var buttonName = "PEOPLE"; var tablet = null; function startup() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ text: buttonName, icon: "icons/tablet-icons/people-i.svg", diff --git a/scripts/system/particle_explorer/particleExplorerTool.js b/scripts/system/particle_explorer/particleExplorerTool.js index d85fc169b1..c2231df406 100644 --- a/scripts/system/particle_explorer/particleExplorerTool.js +++ b/scripts/system/particle_explorer/particleExplorerTool.js @@ -17,7 +17,7 @@ var PARTICLE_EXPLORER_HTML_URL = Script.resolvePath('particleExplorer.html'); ParticleExplorerTool = function() { var that = {}; that.createWebView = function() { - that.webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + that.webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); that.webView.setVisible = function(value) {}; that.webView.webEventReceived.connect(that.webEventReceived); } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 9afdb4ec53..3f29238c24 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -7,7 +7,7 @@ // Distributed under the Apache License, Version 2.0 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablet, Script, HMD, Settings, DialogsManager, Menu, Reticle, OverlayWebWindow, Desktop, Account, MyAvatar, Snapshot */ +/* globals Tablets, Script, HMD, Settings, DialogsManager, Menu, Reticle, OverlayWebWindow, Desktop, Account, MyAvatar, Snapshot */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function () { // BEGIN LOCAL_SCOPE @@ -22,7 +22,7 @@ var clearOverlayWhenMoving; var buttonName = "SNAP"; var buttonConnected = false; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/snap-i.svg", activeIcon: "icons/tablet-icons/snap-a.svg", diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js index 2a0e827932..41b7b84d4c 100644 --- a/scripts/system/tablet-goto.js +++ b/scripts/system/tablet-goto.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Window, Script, Tablet, HMD, Controller, Account, XMLHttpRequest, location, print*/ +/*global Window, Script, Tablets, HMD, Controller, Account, XMLHttpRequest, location, print*/ // // goto.js @@ -30,7 +30,7 @@ var shouldActivateButton = false; function ignore() { } - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var NORMAL_ICON = "icons/tablet-icons/goto-i.svg"; var NORMAL_ACTIVE = "icons/tablet-icons/goto-a.svg"; var WAITING_ICON = "icons/tablet-icons/goto-msg.svg"; diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 17821c737e..0044ca0496 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays, +/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablets, Overlays, MyAvatar, Menu, AvatarInputs, Vec3 */ (function() { // BEGIN LOCAL_SCOPE @@ -33,7 +33,7 @@ function checkTablet() { if (gTablet === null) { - gTablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + gTablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); } } @@ -315,7 +315,7 @@ Script.scriptEnding.connect(function () { // if we reload scripts in tablet mode make sure we close the currently open window, by calling gotoHomeScreen - var tabletProxy = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tabletProxy = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (tabletProxy && tabletProxy.toolbarMode) { tabletProxy.gotoHomeScreen(); } diff --git a/scripts/system/tablet-users.js b/scripts/system/tablet-users.js index 6f37cd55eb..7efd49ae55 100644 --- a/scripts/system/tablet-users.js +++ b/scripts/system/tablet-users.js @@ -33,7 +33,7 @@ GlobalServices.findableBy = myVisibility; } - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/users-i.svg", activeIcon: "icons/tablet-icons/users-a.svg", diff --git a/scripts/tutorials/createFloatingLanternBox.js b/scripts/tutorials/createFloatingLanternBox.js index c84214e295..c83535fa37 100644 --- a/scripts/tutorials/createFloatingLanternBox.js +++ b/scripts/tutorials/createFloatingLanternBox.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // createFloatinLanternBox.js diff --git a/scripts/tutorials/createTetherballStick.js b/scripts/tutorials/createTetherballStick.js index 35f5fb0344..3ad0939c2e 100644 --- a/scripts/tutorials/createTetherballStick.js +++ b/scripts/tutorials/createTetherballStick.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // createTetherballStick.js diff --git a/scripts/tutorials/entity_scripts/floatingLantern.js b/scripts/tutorials/entity_scripts/floatingLantern.js index aa25dc0003..c2a79c9c5b 100644 --- a/scripts/tutorials/entity_scripts/floatingLantern.js +++ b/scripts/tutorials/entity_scripts/floatingLantern.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // floatinLantern.js diff --git a/scripts/tutorials/entity_scripts/floatingLanternBox.js b/scripts/tutorials/entity_scripts/floatingLanternBox.js index b5fb0c27d9..b8e0fbda3e 100644 --- a/scripts/tutorials/entity_scripts/floatingLanternBox.js +++ b/scripts/tutorials/entity_scripts/floatingLanternBox.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // floatingLanternBox.js diff --git a/scripts/tutorials/entity_scripts/tetherballStick.js b/scripts/tutorials/entity_scripts/tetherballStick.js index 867074abd4..50bac88caf 100644 --- a/scripts/tutorials/entity_scripts/tetherballStick.js +++ b/scripts/tutorials/entity_scripts/tetherballStick.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // tetherballStick.js diff --git a/tests/shared/src/PathUtilsTests.cpp b/tests/shared/src/PathUtilsTests.cpp new file mode 100644 index 0000000000..fc31d475d0 --- /dev/null +++ b/tests/shared/src/PathUtilsTests.cpp @@ -0,0 +1,28 @@ +// +// Created by Bradley Austin Davis on 2017/11/08 +// Copyright 2013-2017 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 +// + + +#include "PathUtilsTests.h" + +#include + +#include + + +QTEST_MAIN(PathUtilsTests) + +void PathUtilsTests::testPathUtils() { + QString result = PathUtils::qmlBasePath(); +#if DEV_BUILD + QVERIFY(result.startsWith("file:///")); +#else + QVERIFY(result.startsWith("qrc:///")); +#endif + QVERIFY(result.endsWith("/")); +} + diff --git a/tests/shared/src/PathUtilsTests.h b/tests/shared/src/PathUtilsTests.h new file mode 100644 index 0000000000..8ae410d6cb --- /dev/null +++ b/tests/shared/src/PathUtilsTests.h @@ -0,0 +1,20 @@ +// +// Created by Bradley Austin Davis on 2017/11/08 +// Copyright 2013-2017 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_PathUtilsTests_h +#define hifi_PathUtilsTests_h + +#include + +class PathUtilsTests : public QObject { + Q_OBJECT +private slots: + void testPathUtils(); +}; + +#endif // hifi_PathUtilsTests_h diff --git a/unpublishedScripts/marketplace/blocks/blocksApp.js b/unpublishedScripts/marketplace/blocks/blocksApp.js index c9e8682b23..8088f438de 100644 --- a/unpublishedScripts/marketplace/blocks/blocksApp.js +++ b/unpublishedScripts/marketplace/blocks/blocksApp.js @@ -26,7 +26,7 @@ APP_URL = APP_OUTDATED_URL; } - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: APP_ICON, activeIcon: APP_ICON_ACTIVE, diff --git a/unpublishedScripts/marketplace/camera-move/app-camera-move.js b/unpublishedScripts/marketplace/camera-move/app-camera-move.js index f58dd3d3bd..177565a332 100644 --- a/unpublishedScripts/marketplace/camera-move/app-camera-move.js +++ b/unpublishedScripts/marketplace/camera-move/app-camera-move.js @@ -162,7 +162,7 @@ var globalState = { function main() { log('initializing...', VERSION); - var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), + var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton(BUTTON_CONFIG); Script.scriptEnding.connect(function() { @@ -601,7 +601,7 @@ function _patchCameraModeSetting() { } function getSystemMetadata() { - var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'); + var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'); return { mode: { hmd: HMD.active, diff --git a/unpublishedScripts/marketplace/clap/clapApp.js b/unpublishedScripts/marketplace/clap/clapApp.js index b2d8ce55db..a975d9d8b5 100644 --- a/unpublishedScripts/marketplace/clap/clapApp.js +++ b/unpublishedScripts/marketplace/clap/clapApp.js @@ -16,7 +16,7 @@ // Load up engine var APP_NAME = "CLAP"; var ClapEngine = Script.require(Script.resolvePath("scripts/ClapEngine.js?v9")); -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); // Define Menu var blackIcon = Script.resolvePath("icons/tablet-icons/clap-a.svg?foxv2"); diff --git a/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js b/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js index c09ad602f8..278f4efbaa 100644 --- a/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js +++ b/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js @@ -45,7 +45,7 @@ var buttonConfig = utils.assign({ activeIcon: require('./doppleganger-a.svg.json'), }); -var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), +var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton(buttonConfig); Script.scriptEnding.connect(function() { diff --git a/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js b/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js index bc5368ba5b..1cb7610ff3 100644 --- a/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js +++ b/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js @@ -905,7 +905,7 @@ var buttonConfig = utils.assign({ activeIcon: __webpack_require__(7), }); -var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), +var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton(buttonConfig); Script.scriptEnding.connect(function() { diff --git a/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js b/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js index f4c7bf99c0..d02dd3e9ba 100644 --- a/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js +++ b/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js @@ -12,7 +12,7 @@ var DopplegangerClass = Script.require('./doppleganger.js'); -var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), +var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton({ icon: Script.resolvePath('./doppleganger-i.svg'), activeIcon: Script.resolvePath('./doppleganger-a.svg'), diff --git a/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js b/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js index b4d01e77cf..687c9445cd 100644 --- a/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js +++ b/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js @@ -19,7 +19,7 @@ var lib = Script.require("https://hifi-content.s3.amazonaws.com/elisalj/emoji_sc var APP_NAME = "EMOJIS"; var APP_URL = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/emojiTabletUI.html?" + Date.now(); var APP_ICON = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/icons/emoji-i.svg"; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: APP_ICON, diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index 515a2c3a76..32cc75dd42 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -17,7 +17,7 @@ var TRIGGER_PRESSURE = 0.95; - var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'); + var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'); var button = tablet.addButton({ icon: APP_ICON, diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 68c7ea3f5a..6392f10892 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -631,7 +631,7 @@ } function setUp() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } @@ -694,7 +694,7 @@ } // FIXME: If setUp() is run immediately at Interface start-up, Interface hangs and crashes because of the line of code: - // tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + // tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); //setUp(); //Script.scriptEnding.connect(tearDown); Script.setTimeout(function () { diff --git a/unpublishedScripts/marketplace/shapes/shapes.js b/unpublishedScripts/marketplace/shapes/shapes.js index cd5f119588..de177f435e 100644 --- a/unpublishedScripts/marketplace/shapes/shapes.js +++ b/unpublishedScripts/marketplace/shapes/shapes.js @@ -1930,7 +1930,7 @@ function setUp() { var hasRezPermissions; - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { App.log("ERROR: Tablet not found! App not started."); return; diff --git a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js index 7bc65722cd..114bccb034 100644 --- a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js +++ b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js @@ -28,7 +28,7 @@ } } - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: ICONS.icon, activeIcon: ICONS.activeIcon, diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index 76044d2975..cc600632e5 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Tablet, Script, */ +/*global Tablets, Script, */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // spectatorCamera.js @@ -188,7 +188,7 @@ // -tablet: The tablet instance to be modified. var tablet = null; function startup() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); addOrRemoveButton(false, HMD.active); tablet.screenChanged.connect(onTabletScreenChanged); Window.domainChanged.connect(onDomainChanged); diff --git a/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js index f7702053a4..2f895d5f94 100644 --- a/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js +++ b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js @@ -20,7 +20,7 @@ var isRaiseHandButtonActive = false; var animHandlerId; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: BUTTON_NAME, icon: "icons/tablet-icons/raise-hand-i.svg", From 8f85c7650b88a7e5e91a90f66f4b09d35fa25b02 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 13 Nov 2017 14:16:04 -0800 Subject: [PATCH 21/81] Make sure loaded components get the right parent context --- interface/resources/qml/hifi/tablet/WindowRoot.qml | 7 +------ libraries/ui/src/ui/OffscreenQmlSurface.cpp | 9 ++++++--- libraries/ui/src/ui/OffscreenQmlSurface.h | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index 0b631326f4..9c027308b8 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -64,8 +64,8 @@ Windows.ScrollingWindow { function loadWebContent(source, url, injectJavaScriptUrl) { loader.load(source, function() { - loader.item.url = url loader.item.scriptURL = injectJavaScriptUrl; + loader.item.url = url; if (loader.item.hasOwnProperty("closeButtonVisible")) { loader.item.closeButtonVisible = false; } @@ -146,11 +146,6 @@ Windows.ScrollingWindow { } function load(newSource, callback) { - if (loader.source == newSource) { - loader.loaded(); - return; - } - if (loader.item) { loader.item.destroy(); loader.item = null; diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index aab89ccd4d..a0c6790b93 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -697,13 +697,16 @@ QQuickItem* OffscreenQmlSurface::getRootItem() { return _rootItem; } -QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, bool forceNewContext) { +QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, QQuickItem* parent, bool forceNewContext) { // Get any whitelist functionality QList callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource); // If we have whitelisted content, we must load a new context forceNewContext |= !callbacks.empty(); - QQmlContext* targetContext = _qmlContext; + QQmlContext* targetContext = parent ? QQmlEngine::contextForObject(parent) : _qmlContext; + if (!targetContext) { + targetContext = _qmlContext; + } if (_rootItem && forceNewContext) { targetContext = new QQmlContext(targetContext); } @@ -737,7 +740,7 @@ void OffscreenQmlSurface::loadInternal(const QUrl& qmlSource, bool createNewCont finalQmlSource = _qmlContext->resolvedUrl(qmlSource); } - auto targetContext = contextForUrl(finalQmlSource, createNewContext); + auto targetContext = contextForUrl(finalQmlSource, parent, createNewContext); auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); if (qmlComponent->isLoading()) { connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 2d2eb0811b..62754efe14 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -130,7 +130,7 @@ protected: private: static QOpenGLContext* getSharedContext(); - QQmlContext* contextForUrl(const QUrl& url, bool forceNewContext = false); + QQmlContext* contextForUrl(const QUrl& url, QQuickItem* parent, bool forceNewContext = false); void loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback); void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback); QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject); From d71fd151c5b802c66479ad4fae6c960fc7b7891c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 13 Nov 2017 16:45:27 -0800 Subject: [PATCH 22/81] Fixing button model exposure --- interface/resources/qml/hifi/Desktop.qml | 4 +- .../resources/qml/hifi/toolbars/Toolbar.qml | 127 +++-------- .../qml/hifi/toolbars/ToolbarButton.qml | 3 +- interface/src/Application.cpp | 4 + libraries/ui/src/OffscreenUi.cpp | 3 + .../ui/src/ui/TabletScriptingInterface.cpp | 204 ++++++------------ .../ui/src/ui/TabletScriptingInterface.h | 66 ++++-- tests/shared/src/PathUtilsTests.cpp | 1 - 8 files changed, 149 insertions(+), 263 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index ea9ec2f6c9..960d3e0649 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -45,11 +45,13 @@ OriginalDesktop.Desktop { Toolbar { id: sysToolbar; objectName: "com.highfidelity.interface.toolbar.system"; + property var tablet: Tablets.getTablet("com.highfidelity.interface.tablet.system"); anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. x: sysToolbar.x y: 50 - shown: true + buttonModel: tablet.buttons; + shown: tablet.toolbarMode; } Settings { diff --git a/interface/resources/qml/hifi/toolbars/Toolbar.qml b/interface/resources/qml/hifi/toolbars/Toolbar.qml index 01aa29f665..ff7e835690 100644 --- a/interface/resources/qml/hifi/toolbars/Toolbar.qml +++ b/interface/resources/qml/hifi/toolbars/Toolbar.qml @@ -11,6 +11,8 @@ Window { horizontalSpacers: horizontal verticalSpacers: !horizontal } + property var tabletProxy; + property var buttonModel: ListModel {} hideBackground: true resizable: false destroyOnCloseButton: false @@ -23,24 +25,32 @@ Window { activator: Item {} property bool horizontal: true property real buttonSize: 50; - property var buttons: [] - property var container: horizontal ? row : column Settings { category: "toolbar/" + window.objectName property alias x: window.x property alias y: window.y } + + Component { + id: buttonComponent + ToolbarButton { + id: toolbarButton + property var proxy: modelData; + onClicked: proxy.clicked() + Component.onCompleted: updateProperties() - onHorizontalChanged: { - var newParent = horizontal ? row : column; - for (var i in buttons) { - var child = buttons[i]; - child.parent = newParent; - if (horizontal) { - child.y = 0 - } else { - child.x = 0 + Connections { + target: proxy; + onPropertiesChanged: updateProperties(); + } + + function updateProperties() { + Object.keys(proxy.properties).forEach(function (key) { + if (toolbarButton[key] !== proxy.properties[key]) { + toolbarButton[key] = proxy.properties[key]; + } + }); } } } @@ -52,97 +62,22 @@ Window { Row { id: row + visible: window.horizontal spacing: 6 + Repeater { + model: buttonModel + delegate: buttonComponent + } } - + Column { id: column + visible: !window.horizontal spacing: 6 - } - - Component { id: toolbarButtonBuilder; ToolbarButton { } } - } - - - function findButtonIndex(name) { - if (!name) { - return -1; - } - - for (var i in buttons) { - var child = buttons[i]; - if (child.objectName === name) { - return i; + Repeater { + model: buttonModel + delegate: buttonComponent } } - return -1; - } - - function findButton(name) { - var index = findButtonIndex(name); - if (index < 0) { - return; - } - return buttons[index]; - } - - function sortButtons() { - var children = []; - for (var i = 0; i < container.children.length; i++) { - children[i] = container.children[i]; - } - - children.sort(function (a, b) { - if (a.sortOrder === b.sortOrder) { - // subsort by stableOrder, because JS sort is not stable in qml. - return a.stableOrder - b.stableOrder; - } else { - return a.sortOrder - b.sortOrder; - } - }); - - container.children = children; - } - - function addButton(properties) { - properties = properties || {} - - // If a name is specified, then check if there's an existing button with that name - // and return it if so. This will allow multiple clients to listen to a single button, - // and allow scripts to be idempotent so they don't duplicate buttons if they're reloaded - var result = findButton(properties.objectName); - if (result) { - for (var property in properties) { - result[property] = properties[property]; - } - return result; - } - properties.toolbar = this; - properties.opacity = 0; - result = toolbarButtonBuilder.createObject(container, properties); - buttons.push(result); - - result.opacity = 1; - - sortButtons(); - - fadeIn(null); - - return result; - } - - function removeButton(name) { - var index = findButtonIndex(name); - if (index < -1) { - console.warn("Tried to remove non-existent button " + name); - return; - } - - buttons[index].destroy(); - buttons.splice(index, 1); - - if (buttons.length === 0) { - fadeOut(null); - } } } diff --git a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml index 63149ad23b..3c64d4bf2e 100644 --- a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml +++ b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml @@ -25,7 +25,8 @@ StateImage { property string activeHoverIcon: button.activeIcon property int sortOrder: 100 - property int stableSortOrder: 0 + property int stableOrder: 0 + property var uuid; signal clicked() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d388128709..2d7ae29379 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2234,6 +2234,10 @@ void Application::initializeUi() { qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType("Hifi", 1, 0, "Preference"); + { + auto tabletScriptingInterface = DependencyManager::get(); + tabletScriptingInterface->getTablet(SYSTEM_TABLET); + } auto offscreenUi = DependencyManager::get(); offscreenUi->create(); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 252c08a1f0..d8a2c2c3cb 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -106,6 +106,9 @@ void OffscreenUi::create() { myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags()); myContext->setContextProperty("fileDialogHelper", new FileDialogHelper()); auto tabletScriptingInterface = DependencyManager::get(); + qRegisterMetaType(); + qRegisterMetaType(); + myContext->setContextProperty("Tablets", tabletScriptingInterface.data()); TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 93d493539e..f006547e2b 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -32,6 +32,14 @@ const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; const QString TabletScriptingInterface::QML = "hifi/tablet/TabletRoot.qml"; +static QString getUsername() { + QString username = "Unknown user"; + auto accountManager = DependencyManager::get(); + if (accountManager->isLoggedIn()) { + username = accountManager->getAccountInfo().getUsername(); + } + return username; +} static Setting::Handle tabletSoundsButtonClick("TabletSounds", QStringList { "/sounds/Button06.wav", "/sounds/Button04.wav", @@ -39,6 +47,51 @@ static Setting::Handle tabletSoundsButtonClick("TabletSounds", QStr "/sounds/Tab01.wav", "/sounds/Tab02.wav" }); +TabletButtonListModel::TabletButtonListModel() { + +} + +TabletButtonListModel::~TabletButtonListModel() { + +} + +enum ButtonDeviceRole { + ButtonProxyRole = Qt::UserRole, +}; + +QHash TabletButtonListModel::_roles{ + { ButtonProxyRole, "buttonProxy" }, +}; + +Qt::ItemFlags TabletButtonListModel::_flags{ Qt::ItemIsSelectable | Qt::ItemIsEnabled }; + +QVariant TabletButtonListModel::data(const QModelIndex& index, int role) const { + if (!index.isValid() || index.row() >= rowCount() || role != ButtonProxyRole) { + return QVariant(); + } + + return QVariant::fromValue(_buttons.at(index.row()).data()); +} + +TabletButtonProxy* TabletButtonListModel::addButton(const QVariant& properties) { + auto tabletButtonProxy = QSharedPointer(new TabletButtonProxy(properties.toMap())); + beginResetModel(); + _buttons.push_back(tabletButtonProxy); + endResetModel(); + return tabletButtonProxy.data(); +} + +void TabletButtonListModel::removeButton(TabletButtonProxy* button) { + auto itr = std::find(_buttons.begin(), _buttons.end(), button); + if (itr == _buttons.end()) { + qCWarning(uiLogging) << "TabletProxy::removeButton() could not find button " << button; + return; + } + beginResetModel(); + _buttons.erase(itr); + endResetModel(); +} + TabletScriptingInterface::TabletScriptingInterface() { qmlRegisterType("TabletScriptingInterface", 1, 0, "TabletEnums"); } @@ -232,15 +285,6 @@ TabletProxy::~TabletProxy() { disconnect(this, &TabletProxy::tabletShownChanged, this, &TabletProxy::onTabletShown); } -QVariant TabletProxy::getButtons() { - Q_ASSERT(QThread::currentThread() == qApp->thread()); - QVariantList result; - for (const auto& button : _tabletButtonProxies) { - result.push_back(QVariant::fromValue(button.data())); - } - return result; -} - void TabletProxy::setToolbarMode(bool toolbarMode) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setToolbarMode", Q_ARG(bool, toolbarMode)); @@ -256,8 +300,6 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { auto offscreenUi = DependencyManager::get(); if (toolbarMode) { - addButtonsToToolbar(); - // create new desktop window auto tabletRootWindow = new TabletRootWindow(); tabletRootWindow->initQml(QVariantMap()); @@ -272,11 +314,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { // forward qml surface events to interface js connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); } else { - removeButtonsFromToolbar(); - - if (_currentPathLoaded == TABLET_HOME_SOURCE_URL) { - // Tablet QML now pulls buttons from Tablet proxy - } else { + if (_currentPathLoaded != TABLET_HOME_SOURCE_URL) { loadHomeScreen(true); } //check if running scripts window opened and save it for reopen in Tablet @@ -290,44 +328,8 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { _desktopWindow = nullptr; } } -} -#if 0 -static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) { - Q_ASSERT(QThread::currentThread() == qApp->thread()); - if (buttonProxy == NULL){ - qCCritical(uiLogging) << __FUNCTION__ << "buttonProxy is NULL"; - return; - } - - QVariant resultVar; - qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << "adding button " << buttonProxy; - bool hasResult = QMetaObject::invokeMethod(qmlTablet, "addButtonProxy", Qt::DirectConnection, - Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, buttonProxy->getProperties())); - if (!hasResult) { - qCWarning(uiLogging) << __FUNCTION__ << " has no result"; - return; - } - - QObject* qmlButton = qvariant_cast(resultVar); - if (!qmlButton) { - qCWarning(uiLogging) << "TabletScriptingInterface addButtonProxyToQmlTablet result not a QObject"; - return; - } - QObject::connect(qmlButton, SIGNAL(clicked()), buttonProxy, SLOT(clickedSlot())); - buttonProxy->setQmlButton(qobject_cast(qmlButton)); -} -#endif - - -static QString getUsername() { - QString username = "Unknown user"; - auto accountManager = DependencyManager::get(); - if (accountManager->isLoggedIn()) { - return accountManager->getAccountInfo().getUsername(); - } else { - return "Unknown user"; - } + emit toolbarModeChanged(); } void TabletProxy::initialScreen(const QVariant& url) { @@ -702,20 +704,7 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { return result; } - auto tabletButtonProxy = QSharedPointer(new TabletButtonProxy(properties.toMap())); - _tabletButtonProxies.push_back(tabletButtonProxy); - if (!_toolbarMode && _qmlTabletRoot) { - // Tablet now pulls buttons from the tablet proxy - // FIXME emit a signal so that the tablet can refresh buttons if they change - } else if (_toolbarMode) { - auto toolbarProxy = DependencyManager::get()->getSystemToolbarProxy(); - if (toolbarProxy) { - // copy properties from tablet button proxy to toolbar button proxy. - auto toolbarButtonProxy = toolbarProxy->addButton(tabletButtonProxy->getProperties()); - tabletButtonProxy->setToolbarButtonProxy(toolbarButtonProxy); - } - } - return tabletButtonProxy.data(); + return _buttons.addButton(properties); } bool TabletProxy::onHomeScreen() { @@ -734,35 +723,7 @@ void TabletProxy::removeButton(TabletButtonProxy* tabletButtonProxy) { return; } - auto tablet = getQmlTablet(); - if (!tablet) { - qCCritical(uiLogging) << "Could not find tablet in TabletRoot.qml"; - } - - QSharedPointer buttonProxy; - { - auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); - if (iter == _tabletButtonProxies.end()) { - qCWarning(uiLogging) << "TabletProxy::removeButton() could not find button " << tabletButtonProxy; - return; - } - buttonProxy = *iter; - _tabletButtonProxies.erase(iter); - } - - if (!_toolbarMode && _qmlTabletRoot) { - buttonProxy->setQmlButton(nullptr); - if (tablet) { - QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getProperties())); - } - } else if (_toolbarMode) { - auto toolbarProxy = DependencyManager::get()->getSystemToolbarProxy(); - // remove button from toolbarProxy - if (toolbarProxy) { - toolbarProxy->removeButton(buttonProxy->getUuid().toString()); - buttonProxy->setToolbarButtonProxy(nullptr); - } - } + _buttons.removeButton(tabletButtonProxy); } void TabletProxy::emitScriptEvent(const QVariant& msg) { @@ -801,27 +762,6 @@ void TabletProxy::desktopWindowClosed() { gotoHomeScreen(); } -void TabletProxy::addButtonsToToolbar() { - Q_ASSERT(QThread::currentThread() == thread()); - ToolbarProxy* toolbarProxy = DependencyManager::get()->getSystemToolbarProxy(); - for (auto& buttonProxy : _tabletButtonProxies) { - // copy properties from tablet button proxy to toolbar button proxy. - buttonProxy->setToolbarButtonProxy(toolbarProxy->addButton(buttonProxy->getProperties())); - } - - // make the toolbar visible - toolbarProxy->writeProperty("visible", QVariant(true)); -} - -void TabletProxy::removeButtonsFromToolbar() { - Q_ASSERT(QThread::currentThread() == thread()); - ToolbarProxy* toolbarProxy = DependencyManager::get()->getSystemToolbarProxy(); - for (auto& buttonProxy : _tabletButtonProxies) { - // remove button from toolbarProxy - toolbarProxy->removeButton(buttonProxy->getUuid().toString()); - buttonProxy->setToolbarButtonProxy(nullptr); - } -} QQuickItem* TabletProxy::getQmlTablet() const { if (!_qmlTabletRoot) { @@ -891,25 +831,6 @@ TabletButtonProxy::~TabletButtonProxy() { } } -void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) { - Q_ASSERT(QThread::currentThread() == qApp->thread()); - if (_qmlButton) { - QObject::disconnect(_qmlButton, &QQuickItem::destroyed, this, nullptr); - } - _qmlButton = qmlButton; - if (_qmlButton) { - QObject::connect(_qmlButton, &QQuickItem::destroyed, this, [this] { _qmlButton = nullptr; }); - } -} - -void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { - Q_ASSERT(QThread::currentThread() == thread()); - _toolbarButtonProxy = toolbarButtonProxy; - if (_toolbarButtonProxy) { - QObject::connect(_toolbarButtonProxy, SIGNAL(clicked()), this, SLOT(clickedSlot())); - } -} - QVariantMap TabletButtonProxy::getProperties() { if (QThread::currentThread() != thread()) { QVariantMap result; @@ -926,20 +847,19 @@ void TabletButtonProxy::editProperties(const QVariantMap& properties) { return; } + bool changed = false; QVariantMap::const_iterator iter = properties.constBegin(); while (iter != properties.constEnd()) { const auto& key = iter.key(); const auto& value = iter.value(); if (!_properties.contains(key) || _properties[key] != value) { - _properties[iter.key()] = iter.value(); - if (_qmlButton) { - QMetaObject::invokeMethod(_qmlButton, "changeProperty", Qt::AutoConnection, Q_ARG(QVariant, QVariant(iter.key())), Q_ARG(QVariant, iter.value())); - } + _properties[key] = value; + changed = true; } ++iter; } - if (_toolbarButtonProxy) { - QMetaObject::invokeMethod(_toolbarButtonProxy, "editProperties", Qt::AutoConnection, Q_ARG(QVariantMap, properties)); + if (changed) { + emit propertiesChanged(); } } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index e7dc5ede1f..718d5123db 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -12,13 +12,16 @@ #include #include -#include -#include +#include +#include +#include +#include + #include -#include -#include -#include -#include +#include +#include + +#include #include #include @@ -90,6 +93,31 @@ protected: bool _toolbarMode { false }; }; +class TabletButtonListModel : public QAbstractListModel { + Q_OBJECT + +public: + TabletButtonListModel(); + ~TabletButtonListModel(); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return (int)_buttons.size(); } + QHash roleNames() const override { return _roles; } + Qt::ItemFlags flags(const QModelIndex& index) const override { return _flags; } + QVariant data(const QModelIndex& index, int role) const override; + + +protected: + friend class TabletProxy; + TabletButtonProxy* addButton(const QVariant& properties); + void removeButton(TabletButtonProxy* button); + using List = std::list>; + static QHash _roles; + static Qt::ItemFlags _flags; + std::vector> _buttons; +}; + +Q_DECLARE_METATYPE(TabletButtonListModel*); + /**jsdoc * @class TabletProxy * @property name {string} READ_ONLY: name of this tablet @@ -99,9 +127,10 @@ protected: class TabletProxy : public QObject { Q_OBJECT Q_PROPERTY(QString name READ getName) - Q_PROPERTY(bool toolbarMode READ getToolbarMode WRITE setToolbarMode) + Q_PROPERTY(bool toolbarMode READ getToolbarMode WRITE setToolbarMode NOTIFY toolbarModeChanged) Q_PROPERTY(bool landscape READ getLandscape WRITE setLandscape) Q_PROPERTY(bool tabletShown MEMBER _tabletShown NOTIFY tabletShownChanged) + Q_PROPERTY(TabletButtonListModel* buttons READ getButtons CONSTANT) public: TabletProxy(QObject* parent, const QString& name); ~TabletProxy(); @@ -196,8 +225,6 @@ public: Q_INVOKABLE bool isPathLoaded(const QVariant& path); - Q_INVOKABLE QVariant getButtons(); - QQuickItem* getTabletRoot() const { return _qmlTabletRoot; } OffscreenQmlSurface* getTabletSurface(); @@ -206,6 +233,7 @@ public: QQuickItem* getQmlMenu() const; + TabletButtonListModel* getButtons() { return &_buttons; } signals: /**jsdoc * Signaled when this tablet receives an event from the html/js embedded in the tablet @@ -238,20 +266,20 @@ signals: */ void tabletShownChanged(); + void toolbarModeChanged(); + protected slots: void desktopWindowClosed(); void emitWebEvent(const QVariant& msg); void onTabletShown(); + protected: void loadHomeScreen(bool forceOntoHomeScreen); - void addButtonsToToolbar(); - void removeButtonsFromToolbar(); bool _initialScreen { false }; QVariant _initialPath { "" }; QVariant _currentPathLoaded { "" }; QString _name; - std::vector> _tabletButtonProxies; QQuickItem* _qmlTabletRoot { nullptr }; OffscreenQmlSurface* _qmlOffscreenSurface { nullptr }; QmlWindowClass* _desktopWindow { nullptr }; @@ -262,6 +290,8 @@ protected: State _state { State::Uninitialized }; bool _landscape { false }; bool _showRunningScripts { false }; + + TabletButtonListModel _buttons; }; Q_DECLARE_METATYPE(TabletProxy*); @@ -273,15 +303,11 @@ Q_DECLARE_METATYPE(TabletProxy*); class TabletButtonProxy : public QObject { Q_OBJECT Q_PROPERTY(QUuid uuid READ getUuid) + Q_PROPERTY(QVariantMap properties READ getProperties NOTIFY propertiesChanged) public: TabletButtonProxy(const QVariantMap& properties); ~TabletButtonProxy(); - - Q_INVOKABLE void setQmlButton(QQuickItem* qmlButton); - - void setToolbarButtonProxy(QObject* toolbarButtonProxy); - QUuid getUuid() const { return _uuid; } /**jsdoc @@ -298,9 +324,6 @@ public: */ Q_INVOKABLE void editProperties(const QVariantMap& properties); -public slots: - void clickedSlot() { emit clicked(); } - signals: /**jsdoc * Signaled when this button has been clicked on by the user. @@ -308,12 +331,11 @@ signals: * @returns {Signal} */ void clicked(); + void propertiesChanged(); protected: QUuid _uuid; int _stableOrder; - QQuickItem* _qmlButton { nullptr }; - QObject* _toolbarButtonProxy { nullptr }; QVariantMap _properties; }; diff --git a/tests/shared/src/PathUtilsTests.cpp b/tests/shared/src/PathUtilsTests.cpp index fc31d475d0..1c445908f7 100644 --- a/tests/shared/src/PathUtilsTests.cpp +++ b/tests/shared/src/PathUtilsTests.cpp @@ -13,7 +13,6 @@ #include - QTEST_MAIN(PathUtilsTests) void PathUtilsTests::testPathUtils() { From 8f855c6c9568dc921783914818a859fcea3baeff Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 15 Nov 2017 09:21:10 -0800 Subject: [PATCH 23/81] Update QUrls --- interface/src/Application.cpp | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 60182ce5b6..76f8cc1505 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2234,27 +2234,27 @@ void Application::initializeUi() { context->setContextProperty("Commerce", new QmlCommerce()); }; OffscreenQmlSurface::addWhitelistContextHandler({ - QUrl{ "qrc:///qml/hifi/commerce/checkout/Checkout.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/common/CommerceLightbox.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/common/FirstUseTutorial.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/common/SortableListModel.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/purchases/PurchasedItem.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/purchases/Purchases.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/Help.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/NeedsLogIn.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/PassphraseChange.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/PassphraseModal.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/PassphraseSelection.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/Security.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/SecurityImageChange.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/SecurityImageModel.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/SecurityImageSelection.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/SendMoney.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/Wallet.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/WalletHome.qml" }, - QUrl{ "qrc:///qml/hifi/commerce/wallet/WalletSetup.qml" }, + QUrl{ "hifi/commerce/checkout/Checkout.qml" }, + QUrl{ "hifi/commerce/common/CommerceLightbox.qml" }, + QUrl{ "hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, + QUrl{ "hifi/commerce/common/FirstUseTutorial.qml" }, + QUrl{ "hifi/commerce/common/SortableListModel.qml" }, + QUrl{ "hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, + QUrl{ "hifi/commerce/purchases/PurchasedItem.qml" }, + QUrl{ "hifi/commerce/purchases/Purchases.qml" }, + QUrl{ "hifi/commerce/wallet/Help.qml" }, + QUrl{ "hifi/commerce/wallet/NeedsLogIn.qml" }, + QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" }, + QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" }, + QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" }, + QUrl{ "hifi/commerce/wallet/Security.qml" }, + QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" }, + QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" }, + QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" }, + QUrl{ "hifi/commerce/wallet/SendMoney.qml" }, + QUrl{ "hifi/commerce/wallet/Wallet.qml" }, + QUrl{ "hifi/commerce/wallet/WalletHome.qml" }, + QUrl{ "hifi/commerce/wallet/WalletSetup.qml" }, }, callback); qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType("Hifi", 1, 0, "Preference"); From 64592d66d7aa6e08f05d21f2f40d824a6bd9a50c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Nov 2017 11:46:56 -0800 Subject: [PATCH 24/81] Fix relative path for tablet login dialog --- scripts/system/libraries/accountUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/libraries/accountUtils.js b/scripts/system/libraries/accountUtils.js index 6df0aa3a87..69092b30fc 100644 --- a/scripts/system/libraries/accountUtils.js +++ b/scripts/system/libraries/accountUtils.js @@ -10,7 +10,7 @@ openLoginWindow = function openLoginWindow() { || (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) { Menu.triggerOption("Login / Sign Up"); } else { - tablet.loadQMLOnTop("../../dialogs/TabletLoginDialog.qml"); + tablet.loadQMLOnTop("dialogs/TabletLoginDialog.qml"); HMD.openTablet(); } }; From 1167be410250d38979dd78a6b3d9983f472a0fa9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Nov 2017 11:50:11 -0800 Subject: [PATCH 25/81] Reverting tablet API rename, cleaning up duplicated code --- interface/resources/qml/controls-uit/Button.qml | 4 ++-- interface/resources/qml/controls-uit/CheckBox.qml | 4 ++-- .../resources/qml/controls-uit/CheckBoxQQC2.qml | 4 ++-- interface/resources/qml/controls-uit/GlyphButton.qml | 4 ++-- interface/resources/qml/controls-uit/Key.qml | 4 ++-- interface/resources/qml/controls-uit/RadioButton.qml | 4 ++-- .../qml/dialogs/TabletConnectionFailureDialog.qml | 2 +- .../resources/qml/dialogs/TabletLoginDialog.qml | 4 ++-- .../qml/dialogs/preferences/ButtonPreference.qml | 4 ++-- .../qml/dialogs/preferences/CheckBoxPreference.qml | 4 ++-- interface/resources/qml/hifi/Card.qml | 6 +++--- interface/resources/qml/hifi/Desktop.qml | 2 +- interface/resources/qml/hifi/audio/MicBar.qml | 4 ++-- .../resources/qml/hifi/tablet/NewEntityButton.qml | 4 ++-- .../qml/hifi/tablet/TabletAddressDialog.qml | 4 ++-- .../qml/hifi/tablet/TabletAttachmentsDialog.qml | 2 +- interface/resources/qml/hifi/tablet/TabletButton.qml | 4 ++-- interface/resources/qml/hifi/tablet/TabletHome.qml | 2 +- .../resources/qml/hifi/tablet/TabletMenuView.qml | 4 ++-- .../tablet/tabletWindows/TabletPreferencesDialog.qml | 4 ++-- interface/src/Application.cpp | 3 +-- libraries/ui/src/OffscreenUi.cpp | 6 ------ libraries/ui/src/ui/OffscreenQmlSurface.cpp | 4 +++- scripts/developer/EZrecord.js | 2 +- scripts/developer/inputRecording.js | 2 +- scripts/developer/tests/dynamics/dynamicsTests.js | 2 +- scripts/developer/tests/puck-attach.js | 2 +- scripts/developer/tests/sliderTestMain.js | 2 +- scripts/developer/tests/tabletEventBridgeTest.js | 2 +- scripts/developer/tests/tabletTest.js | 2 +- scripts/developer/utilities/audio/stats.js | 2 +- scripts/developer/utilities/render/luci.js | 2 +- .../utilities/render/photobooth/photoboothApp.js | 2 +- scripts/system/audio.js | 2 +- scripts/system/audioScope.js | 2 +- scripts/system/bubble.js | 2 +- scripts/system/chat.js | 2 +- scripts/system/commerce/wallet.js | 2 +- scripts/system/controllers/godView.js | 2 +- scripts/system/edit.js | 12 ++++++------ scripts/system/fingerPaint.js | 2 +- scripts/system/generalSettings.js | 2 +- scripts/system/goto.js | 2 +- scripts/system/help.js | 2 +- scripts/system/hmd.js | 2 +- scripts/system/libraries/WebTablet.js | 4 ++-- scripts/system/libraries/entityList.js | 2 +- scripts/system/libraries/gridTool.js | 2 +- scripts/system/libraries/utils.js | 2 +- scripts/system/marketplaces/marketplace.js | 2 +- scripts/system/marketplaces/marketplaces.js | 2 +- scripts/system/menu.js | 2 +- scripts/system/mod.js | 2 +- scripts/system/notifications.js | 2 +- scripts/system/pal.js | 2 +- .../system/particle_explorer/particleExplorerTool.js | 2 +- scripts/system/snapshot.js | 2 +- scripts/system/tablet-goto.js | 2 +- scripts/system/tablet-ui/tabletUI.js | 4 ++-- scripts/system/tablet-users.js | 2 +- unpublishedScripts/marketplace/blocks/blocksApp.js | 2 +- .../marketplace/camera-move/app-camera-move.js | 4 ++-- unpublishedScripts/marketplace/clap/clapApp.js | 2 +- .../app-doppleganger-attachments.js | 2 +- .../dist/app-doppleganger-marketplace.js | 2 +- .../doppleganger-mirror/app-doppleganger.js | 2 +- .../marketplace/emoji-tablet/emojiTablet.js | 2 +- .../marketplace/laser/laserPointerApp.js | 2 +- unpublishedScripts/marketplace/record/record.js | 4 ++-- unpublishedScripts/marketplace/shapes/shapes.js | 2 +- .../marketplace/skyboxChanger/skyboxchanger.js | 2 +- .../marketplace/spectator-camera/spectatorCamera.js | 2 +- .../marketplace/tablet-raiseHand/tablet-raiseHand.js | 2 +- 73 files changed, 100 insertions(+), 105 deletions(-) diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml index a305bea8dc..02c6181952 100644 --- a/interface/resources/qml/controls-uit/Button.qml +++ b/interface/resources/qml/controls-uit/Button.qml @@ -29,12 +29,12 @@ Original.Button { onHoveredChanged: { if (hovered) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } style: ButtonStyle { diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index 37bc936aa1..e60f646327 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -31,12 +31,12 @@ Original.CheckBox { activeFocusOnPress: true onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } // TODO: doesnt works for QQC1. check with QQC2 // onHovered: { -// Tablets.playSound(TabletEnums.ButtonHover); +// Tablet.playSound(TabletEnums.ButtonHover); // } style: CheckBoxStyle { diff --git a/interface/resources/qml/controls-uit/CheckBoxQQC2.qml b/interface/resources/qml/controls-uit/CheckBoxQQC2.qml index 404d83ebd2..12b8c80003 100644 --- a/interface/resources/qml/controls-uit/CheckBoxQQC2.qml +++ b/interface/resources/qml/controls-uit/CheckBoxQQC2.qml @@ -36,12 +36,12 @@ CheckBox { hoverEnabled: true onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } onHoveredChanged: { if (hovered) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } diff --git a/interface/resources/qml/controls-uit/GlyphButton.qml b/interface/resources/qml/controls-uit/GlyphButton.qml index d225c8e1d1..9c23171ee1 100644 --- a/interface/resources/qml/controls-uit/GlyphButton.qml +++ b/interface/resources/qml/controls-uit/GlyphButton.qml @@ -27,12 +27,12 @@ Original.Button { onHoveredChanged: { if (hovered) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } style: ButtonStyle { diff --git a/interface/resources/qml/controls-uit/Key.qml b/interface/resources/qml/controls-uit/Key.qml index 3ec579a4eb..54834549ae 100644 --- a/interface/resources/qml/controls-uit/Key.qml +++ b/interface/resources/qml/controls-uit/Key.qml @@ -35,13 +35,13 @@ Item { onContainsMouseChanged: { if (containsMouse) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } onClicked: { mouse.accepted = true; - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); webEntity.synthesizeKeyPress(glyph); webEntity.synthesizeKeyPress(glyph, mirrorText); diff --git a/interface/resources/qml/controls-uit/RadioButton.qml b/interface/resources/qml/controls-uit/RadioButton.qml index da4e944f35..a818be072b 100644 --- a/interface/resources/qml/controls-uit/RadioButton.qml +++ b/interface/resources/qml/controls-uit/RadioButton.qml @@ -30,12 +30,12 @@ Original.RadioButton { readonly property int checkRadius: 2 onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } // TODO: doesnt works for QQC1. check with QQC2 // onHovered: { -// Tablets.playSound(TabletEnums.ButtonHover); +// Tablet.playSound(TabletEnums.ButtonHover); // } style: RadioButtonStyle { diff --git a/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml b/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml index 750ed0edd4..6d2ff36550 100644 --- a/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml +++ b/interface/resources/qml/dialogs/TabletConnectionFailureDialog.qml @@ -24,7 +24,7 @@ Item { }); object.selected.connect(function(button) { if (button === OriginalDialogs.StandardButton.Ok) { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.gotoHomeScreen() } }); diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 5f1e9cd3bf..269788a808 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -89,10 +89,10 @@ TabletModalWindow { //bodyLoader.active = false } if (gotoPreviousApp) { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.returnToPreviousApp(); } else { - Tablets.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); + Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); } } diff --git a/interface/resources/qml/dialogs/preferences/ButtonPreference.qml b/interface/resources/qml/dialogs/preferences/ButtonPreference.qml index bae581a47f..454a9124ae 100644 --- a/interface/resources/qml/dialogs/preferences/ButtonPreference.qml +++ b/interface/resources/qml/dialogs/preferences/ButtonPreference.qml @@ -25,13 +25,13 @@ Preference { id: button onHoveredChanged: { if (hovered) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } onClicked: { preference.trigger(); - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } width: 180 anchors.bottom: parent.bottom diff --git a/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml b/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml index 81884d9a72..73819839a1 100644 --- a/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml +++ b/interface/resources/qml/dialogs/preferences/CheckBoxPreference.qml @@ -41,12 +41,12 @@ Preference { id: checkBox onHoveredChanged: { if (hovered) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } anchors { diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 8d69afab46..83bf1e2c54 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -246,12 +246,12 @@ Item { anchors.fill: parent; acceptedButtons: Qt.LeftButton; onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); goFunction("hifi://" + hifiUrl); } hoverEnabled: true; onEntered: { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); hoverThunk(); } onExited: unhoverThunk(); @@ -269,7 +269,7 @@ Item { } } function go() { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId)); } MouseArea { diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 960d3e0649..ddf5a69a33 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -45,7 +45,7 @@ OriginalDesktop.Desktop { Toolbar { id: sysToolbar; objectName: "com.highfidelity.interface.toolbar.system"; - property var tablet: Tablets.getTablet("com.highfidelity.interface.tablet.system"); + property var tablet: Tablet.getTablet("com.highfidelity.interface.tablet.system"); anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. x: sysToolbar.x diff --git a/interface/resources/qml/hifi/audio/MicBar.qml b/interface/resources/qml/hifi/audio/MicBar.qml index 9ef8bf3698..c66904034b 100644 --- a/interface/resources/qml/hifi/audio/MicBar.qml +++ b/interface/resources/qml/hifi/audio/MicBar.qml @@ -61,12 +61,12 @@ Rectangle { scrollGestureEnabled: false; onClicked: { Audio.muted = !Audio.muted; - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } drag.target: dragTarget; onContainsMouseChanged: { if (containsMouse) { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); } } } diff --git a/interface/resources/qml/hifi/tablet/NewEntityButton.qml b/interface/resources/qml/hifi/tablet/NewEntityButton.qml index 49fdb4368f..1952ef7ee8 100644 --- a/interface/resources/qml/hifi/tablet/NewEntityButton.qml +++ b/interface/resources/qml/hifi/tablet/NewEntityButton.qml @@ -123,11 +123,11 @@ Item { hoverEnabled: true enabled: true onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); newEntityButton.clicked(); } onEntered: { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); newEntityButton.state = "hover state"; } onExited: { diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 3242de89b1..4d9a83817a 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -72,7 +72,7 @@ StackView { addressLine.focus = !HMD.active; root.parentChanged.connect(center); center(); - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); } Component.onDestruction: { root.parentChanged.disconnect(center); @@ -149,7 +149,7 @@ StackView { onClicked: { addressBarDialog.loadHome(); tabletRoot.shown = false; - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.gotoHomeScreen(); } anchors { diff --git a/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml b/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml index 14d7d09dba..19548365aa 100644 --- a/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAttachmentsDialog.qml @@ -37,7 +37,7 @@ Item { } function closeDialog() { - Tablets.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); + Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen(); } anchors.topMargin: hifi.dimensions.tabletMenuHeader // Space for header. diff --git a/interface/resources/qml/hifi/tablet/TabletButton.qml b/interface/resources/qml/hifi/tablet/TabletButton.qml index 3a66738b82..56cc3ed0f7 100644 --- a/interface/resources/qml/hifi/tablet/TabletButton.qml +++ b/interface/resources/qml/hifi/tablet/TabletButton.qml @@ -130,12 +130,12 @@ Item { } tabletButton.clicked(); if (tabletRoot) { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); } } onEntered: { tabletButton.isEntered = true; - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); if (tabletButton.isActive) { tabletButton.state = "hover active state"; diff --git a/interface/resources/qml/hifi/tablet/TabletHome.qml b/interface/resources/qml/hifi/tablet/TabletHome.qml index 0b30496c44..3f9451436c 100644 --- a/interface/resources/qml/hifi/tablet/TabletHome.qml +++ b/interface/resources/qml/hifi/tablet/TabletHome.qml @@ -9,7 +9,7 @@ import "../audio" as HifiAudio Item { id: tablet objectName: "tablet" - property var tabletProxy: Tablets.getTablet("com.highfidelity.interface.tablet.system"); + property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system"); Rectangle { id: bgTopBar diff --git a/interface/resources/qml/hifi/tablet/TabletMenuView.qml b/interface/resources/qml/hifi/tablet/TabletMenuView.qml index e069ce8cb1..636ebfe71f 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuView.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuView.qml @@ -77,12 +77,12 @@ FocusScope { anchors.fill: parent hoverEnabled: true onEntered: { - Tablets.playSound(TabletEnums.ButtonHover); + Tablet.playSound(TabletEnums.ButtonHover); listView.currentIndex = index } onClicked: { - Tablets.playSound(TabletEnums.ButtonClick); + Tablet.playSound(TabletEnums.ButtonClick); root.selected(item); } } diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index 0665b9971e..fcb3e9ff92 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -56,7 +56,7 @@ Item { } function closeDialog() { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (gotoPreviousApp) { tablet.returnToPreviousApp(); @@ -206,7 +206,7 @@ Item { } Component.onCompleted: { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); keyboardEnabled = HMD.active; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 76f8cc1505..7e54c6bf40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5833,10 +5833,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); - scriptEngine->registerGlobalObject("Tablets", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("Tablet", DependencyManager::get().data()); // FIXME remove these deprecated names for the tablet scripting interface scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Tablet", DependencyManager::get().data()); auto toolbarScriptingInterface = DependencyManager::get().data(); DependencyManager::get().data()->setToolbarScriptingInterface(toolbarScriptingInterface); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index d8a2c2c3cb..adb7b4d49b 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -105,12 +105,6 @@ void OffscreenUi::create() { myContext->setContextProperty("OffscreenUi", this); myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags()); myContext->setContextProperty("fileDialogHelper", new FileDialogHelper()); - auto tabletScriptingInterface = DependencyManager::get(); - qRegisterMetaType(); - qRegisterMetaType(); - myContext->setContextProperty("Tablets", tabletScriptingInterface.data()); - TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); - myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } void OffscreenUi::show(const QUrl& url, const QString& name, std::function f) { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index a0c6790b93..76fa5c9ec8 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -391,8 +391,10 @@ void initializeQmlEngine(QQmlEngine* engine, QQuickWindow* window) { qRegisterMetaType(); qRegisterMetaType(); }); - rootContext->setContextProperty("Tablets", DependencyManager::get().data()); + rootContext->setContextProperty("Tablet", DependencyManager::get().data()); rootContext->setContextProperty("Toolbars", DependencyManager::get().data()); + TabletProxy* tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } QQmlEngine* acquireEngine(QQuickWindow* window) { diff --git a/scripts/developer/EZrecord.js b/scripts/developer/EZrecord.js index 3cfc6e9928..049ccbc03d 100644 --- a/scripts/developer/EZrecord.js +++ b/scripts/developer/EZrecord.js @@ -227,7 +227,7 @@ } function setUp() { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } diff --git a/scripts/developer/inputRecording.js b/scripts/developer/inputRecording.js index 574cbbeb3d..6fb8e471cd 100644 --- a/scripts/developer/inputRecording.js +++ b/scripts/developer/inputRecording.js @@ -10,7 +10,7 @@ var recording = false; var onRecordingScreen = false; var passedSaveDirectory = false; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: "IRecord" }); diff --git a/scripts/developer/tests/dynamics/dynamicsTests.js b/scripts/developer/tests/dynamics/dynamicsTests.js index be22e2c5fb..fa51403732 100644 --- a/scripts/developer/tests/dynamics/dynamicsTests.js +++ b/scripts/developer/tests/dynamics/dynamicsTests.js @@ -18,7 +18,7 @@ var DYNAMICS_TESTS_URL = Script.resolvePath("dynamics-tests.html"); var DEFAULT_LIFETIME = 120; // seconds - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: Script.resolvePath("dynamicsTests.svg"), diff --git a/scripts/developer/tests/puck-attach.js b/scripts/developer/tests/puck-attach.js index 6971ec02cd..04d5db5710 100644 --- a/scripts/developer/tests/puck-attach.js +++ b/scripts/developer/tests/puck-attach.js @@ -19,7 +19,7 @@ Script.include("/~/system/libraries/Xform.js"); var TABLET_BUTTON_NAME = "PUCKTACH"; var TABLET_APP_URL = "https://hifi-content.s3.amazonaws.com/seefo/production/puck-attach/puck-attach.html"; -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var tabletButton = tablet.addButton({ text: TABLET_BUTTON_NAME, icon: "https://s3.amazonaws.com/hifi-public/tony/icons/puck-i.svg", diff --git a/scripts/developer/tests/sliderTestMain.js b/scripts/developer/tests/sliderTestMain.js index e7542ef177..22bf4fa911 100644 --- a/scripts/developer/tests/sliderTestMain.js +++ b/scripts/developer/tests/sliderTestMain.js @@ -1,6 +1,6 @@ (function () { var HTML_URL = Script.resolvePath("sliderTest.html"); - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: "SLIDER" }); diff --git a/scripts/developer/tests/tabletEventBridgeTest.js b/scripts/developer/tests/tabletEventBridgeTest.js index 3f988303f2..d386b220fc 100644 --- a/scripts/developer/tests/tabletEventBridgeTest.js +++ b/scripts/developer/tests/tabletEventBridgeTest.js @@ -14,7 +14,7 @@ /* globals Tablets */ -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var tabletButton = tablet.addButton({ text: "SOUNDS", icon: "http://s3.amazonaws.com/hifi-public/tony/icons/trombone-i.png", diff --git a/scripts/developer/tests/tabletTest.js b/scripts/developer/tests/tabletTest.js index 9c1ce0e3bd..438d0a4b99 100644 --- a/scripts/developer/tests/tabletTest.js +++ b/scripts/developer/tests/tabletTest.js @@ -10,7 +10,7 @@ // Adds a BAM! button to the tablet ui. -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: "BAM!!!" }); diff --git a/scripts/developer/utilities/audio/stats.js b/scripts/developer/utilities/audio/stats.js index a828d79340..382e14df5f 100644 --- a/scripts/developer/utilities/audio/stats.js +++ b/scripts/developer/utilities/audio/stats.js @@ -10,7 +10,7 @@ // if (HMD.active && !Settings.getValue("HUDUIEnabled")) { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var qml = Script.resolvePath("TabletStats.qml"); tablet.loadQMLSource(qml); Script.stop(); diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index b2203ce72f..1e2ac1261f 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -27,7 +27,7 @@ } } - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: TABLET_BUTTON_NAME, icon: ICON_URL, diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 375a98e543..0e8eef7352 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -16,7 +16,7 @@ var MODEL_BOUNDING_BOX_DIMENSIONS = {x: 1.0174,y: 1.1925,z: 1.0165}; var PhotoBooth = {}; var photoboothCreated = false; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/snap-i.svg", text: "PHOTOBOOTH" diff --git a/scripts/system/audio.js b/scripts/system/audio.js index ea0626a30c..a93177ca38 100644 --- a/scripts/system/audio.js +++ b/scripts/system/audio.js @@ -54,7 +54,7 @@ function onScreenChanged(type, url) { button.editProperties({isActive: onAudioScreen}); } -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: Audio.muted ? MUTE_ICONS.icon : UNMUTE_ICONS.icon, activeIcon: Audio.muted ? MUTE_ICONS.activeIcon : UNMUTE_ICONS.activeIcon, diff --git a/scripts/system/audioScope.js b/scripts/system/audioScope.js index 268c883983..07efb17046 100644 --- a/scripts/system/audioScope.js +++ b/scripts/system/audioScope.js @@ -17,7 +17,7 @@ var scopePaused = AudioScope.getPause(); var autoPause = false; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var showScopeButton = tablet.addButton({ icon: "icons/tablet-icons/scope.svg", text: "Audio Scope", diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index 2b6924d84f..4ea684ff06 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -183,7 +183,7 @@ // Setup the bubble button var buttonName = "BUBBLE"; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ icon: "icons/tablet-icons/bubble-i.svg", activeIcon: "icons/tablet-icons/bubble-a.svg", diff --git a/scripts/system/chat.js b/scripts/system/chat.js index 220c87195a..fa997e20cc 100644 --- a/scripts/system/chat.js +++ b/scripts/system/chat.js @@ -19,7 +19,7 @@ var tabletButtonIcon = "icons/tablet-icons/menu-i.svg"; // Icon for chat button. var tabletButtonActiveIcon = "icons/tablet-icons/menu-a.svg"; // Active icon for chat button. var tabletButton = null; // The button we create in the tablet. - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); // The awesome tablet. + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); // The awesome tablet. var chatLog = []; // Array of chat messages in the form of [avatarID, displayName, message, data]. var avatarIdentifiers = {}; // Map of avatar ids to dict of identifierParams. var speechBubbleShowing = false; // Is the speech bubble visible? diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 7f05dcf3d8..9b2367b762 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -148,7 +148,7 @@ var walletEnabled = Settings.getValue("commerce", false); function startup() { if (walletEnabled) { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ text: buttonName, icon: "icons/tablet-icons/wallet-i.svg", diff --git a/scripts/system/controllers/godView.js b/scripts/system/controllers/godView.js index eb38308cb9..9551c886c9 100644 --- a/scripts/system/controllers/godView.js +++ b/scripts/system/controllers/godView.js @@ -81,7 +81,7 @@ function endGodView() { } var button; -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); function onClicked() { if (godView) { diff --git a/scripts/system/edit.js b/scripts/system/edit.js index abd69e2697..c4a8f0f54f 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -390,7 +390,7 @@ var toolBar = (function () { } function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.popFromStack(); switch (message.method) { case "newModelDialogAdd": @@ -417,7 +417,7 @@ var toolBar = (function () { var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); activeButton = tablet.addButton({ captionColorOverride: hasRezPermissions ? "" : "#888888", icon: createButtonIconRsrc, @@ -463,7 +463,7 @@ var toolBar = (function () { var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; // tablet version of new-model dialog - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.pushOntoStack("NewModelDialog.qml"); }); @@ -644,7 +644,7 @@ var toolBar = (function () { isActive = active; activeButton.editProperties({isActive: isActive}); - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (!isActive) { entityListTool.setVisible(false); @@ -1850,7 +1850,7 @@ var PropertiesTool = function (opts) { var that = {}; var webView = null; - webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); webView.setVisible = function(value) {}; var visible = false; @@ -2293,7 +2293,7 @@ function selectParticleEntity(entityID) { particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); // Switch to particle explorer - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.sendToQml({method: 'selectTab', params: {id: 'particle'}}); } diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index ad4973890b..06403b77b7 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -414,7 +414,7 @@ } function setUp() { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } diff --git a/scripts/system/generalSettings.js b/scripts/system/generalSettings.js index 8a9001107a..0e917d6ae4 100644 --- a/scripts/system/generalSettings.js +++ b/scripts/system/generalSettings.js @@ -34,7 +34,7 @@ alpha: 0.9 }); } else { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ icon: "icons/tablet-icons/goto-i.svg", text: buttonName, diff --git a/scripts/system/goto.js b/scripts/system/goto.js index 31394c8750..f301af60bd 100644 --- a/scripts/system/goto.js +++ b/scripts/system/goto.js @@ -37,7 +37,7 @@ if (Settings.getValue("HUDUIEnabled")) { alpha: 0.9 }); } else { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ icon: "icons/tablet-icons/goto-i.svg", activeIcon: "icons/tablet-icons/goto-a.svg", diff --git a/scripts/system/help.js b/scripts/system/help.js index 5687c8961f..cf0cd3c003 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -17,7 +17,7 @@ var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; var buttonName = "HELP"; var onHelpScreen = false; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/help-i.svg", activeIcon: "icons/tablet-icons/help-a.svg", diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index a86bbd9a62..e4f6455876 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -38,7 +38,7 @@ function updateControllerDisplay() { } var button; -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); // Independent and Entity mode make people sick; disable them in hmd. var desktopOnlyViews = ['Independent Mode', 'Entity Mode']; diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index cd7c575205..0fb4258f68 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -168,7 +168,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { this.receive = function (channel, senderID, senderUUID, localOnly) { if (_this.homeButtonID == senderID) { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var onHomeScreen = tablet.onHomeScreen(); var isMessageOpen; if (onHomeScreen) { @@ -513,7 +513,7 @@ WebTablet.prototype.mousePressEvent = function (event) { entityPickResults.overlayID === this.tabletEntityID)) { var overlayPickResults = Overlays.findRayIntersection(pickRay, true, [this.webOverlayID, this.homeButtonID], []); if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var onHomeScreen = tablet.onHomeScreen(); var isMessageOpen = tablet.isMessageDialogOpen(); if (onHomeScreen) { diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index a1f5d31a1a..70e0645757 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -15,7 +15,7 @@ EntityListTool = function(opts) { var that = {}; var webView = null; - webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); webView.setVisible = function(value) {}; var filterInView = false; diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 41cbc59502..2c417a9dde 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -237,7 +237,7 @@ GridTool = function(opts) { var listeners = []; var webView = null; - webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); webView.setVisible = function(value) {}; horizontalGrid.addListener(function(data) { diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index 8ea176bbd4..76c248d880 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -354,7 +354,7 @@ flatten = function(array) { getTabletWidthFromSettings = function () { var DEFAULT_TABLET_WIDTH = 0.4375; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var toolbarMode = tablet.toolbarMode; var DEFAULT_TABLET_SCALE = 100; var tabletScalePercentage = DEFAULT_TABLET_SCALE; diff --git a/scripts/system/marketplaces/marketplace.js b/scripts/system/marketplaces/marketplace.js index 6d6550ecbc..d90695c767 100644 --- a/scripts/system/marketplaces/marketplace.js +++ b/scripts/system/marketplaces/marketplace.js @@ -82,7 +82,7 @@ function toggleMarketplace() { } } -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var browseExamplesButton = tablet.addButton({ icon: "icons/tablet-icons/market-i.svg", diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index f65781840d..fd30bde3a0 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -81,7 +81,7 @@ } } - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var marketplaceButton = tablet.addButton({ icon: "icons/tablet-icons/market-i.svg", activeIcon: "icons/tablet-icons/market-a.svg", diff --git a/scripts/system/menu.js b/scripts/system/menu.js index 004ece17c3..c7a44d3e48 100644 --- a/scripts/system/menu.js +++ b/scripts/system/menu.js @@ -13,7 +13,7 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet- // var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; (function() { - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/menu-i.svg", activeIcon: "icons/tablet-icons/menu-a.svg", diff --git a/scripts/system/mod.js b/scripts/system/mod.js index defdb662b3..a3b4974f8d 100644 --- a/scripts/system/mod.js +++ b/scripts/system/mod.js @@ -18,7 +18,7 @@ Script.include("/~/system/libraries/controllers.js"); // grab the toolbar -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var ASSETS_PATH = Script.resolvePath("assets"); var TOOLS_PATH = Script.resolvePath("assets/images/tools/"); diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 612c0e50e2..e1741cfa3b 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -696,7 +696,7 @@ Window.announcement.connect(onNotify); Window.notifyEditError = onEditError; Window.notify = onNotify; - Tablets.tabletNotification.connect(tabletNotification); + Tablet.tabletNotification.connect(tabletNotification); Wallet.walletNotSetup.connect(walletNotSetup); Messages.subscribe(NOTIFICATIONS_MESSAGE_CHANNEL); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 26bec518b4..7ba7c8c0f1 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -677,7 +677,7 @@ var buttonName = "PEOPLE"; var tablet = null; function startup() { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ text: buttonName, icon: "icons/tablet-icons/people-i.svg", diff --git a/scripts/system/particle_explorer/particleExplorerTool.js b/scripts/system/particle_explorer/particleExplorerTool.js index c2231df406..d85fc169b1 100644 --- a/scripts/system/particle_explorer/particleExplorerTool.js +++ b/scripts/system/particle_explorer/particleExplorerTool.js @@ -17,7 +17,7 @@ var PARTICLE_EXPLORER_HTML_URL = Script.resolvePath('particleExplorer.html'); ParticleExplorerTool = function() { var that = {}; that.createWebView = function() { - that.webView = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + that.webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); that.webView.setVisible = function(value) {}; that.webView.webEventReceived.connect(that.webEventReceived); } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 3f29238c24..a14e1f2772 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -22,7 +22,7 @@ var clearOverlayWhenMoving; var buttonName = "SNAP"; var buttonConnected = false; -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/snap-i.svg", activeIcon: "icons/tablet-icons/snap-a.svg", diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js index 41b7b84d4c..8347fcff9a 100644 --- a/scripts/system/tablet-goto.js +++ b/scripts/system/tablet-goto.js @@ -30,7 +30,7 @@ var shouldActivateButton = false; function ignore() { } - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var NORMAL_ICON = "icons/tablet-icons/goto-i.svg"; var NORMAL_ACTIVE = "icons/tablet-icons/goto-a.svg"; var WAITING_ICON = "icons/tablet-icons/goto-msg.svg"; diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 0044ca0496..0032239867 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -33,7 +33,7 @@ function checkTablet() { if (gTablet === null) { - gTablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + gTablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); } } @@ -315,7 +315,7 @@ Script.scriptEnding.connect(function () { // if we reload scripts in tablet mode make sure we close the currently open window, by calling gotoHomeScreen - var tabletProxy = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tabletProxy = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (tabletProxy && tabletProxy.toolbarMode) { tabletProxy.gotoHomeScreen(); } diff --git a/scripts/system/tablet-users.js b/scripts/system/tablet-users.js index 7efd49ae55..6f37cd55eb 100644 --- a/scripts/system/tablet-users.js +++ b/scripts/system/tablet-users.js @@ -33,7 +33,7 @@ GlobalServices.findableBy = myVisibility; } - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/users-i.svg", activeIcon: "icons/tablet-icons/users-a.svg", diff --git a/unpublishedScripts/marketplace/blocks/blocksApp.js b/unpublishedScripts/marketplace/blocks/blocksApp.js index 8088f438de..c9e8682b23 100644 --- a/unpublishedScripts/marketplace/blocks/blocksApp.js +++ b/unpublishedScripts/marketplace/blocks/blocksApp.js @@ -26,7 +26,7 @@ APP_URL = APP_OUTDATED_URL; } - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: APP_ICON, activeIcon: APP_ICON_ACTIVE, diff --git a/unpublishedScripts/marketplace/camera-move/app-camera-move.js b/unpublishedScripts/marketplace/camera-move/app-camera-move.js index 177565a332..f58dd3d3bd 100644 --- a/unpublishedScripts/marketplace/camera-move/app-camera-move.js +++ b/unpublishedScripts/marketplace/camera-move/app-camera-move.js @@ -162,7 +162,7 @@ var globalState = { function main() { log('initializing...', VERSION); - var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), + var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton(BUTTON_CONFIG); Script.scriptEnding.connect(function() { @@ -601,7 +601,7 @@ function _patchCameraModeSetting() { } function getSystemMetadata() { - var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'); + var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'); return { mode: { hmd: HMD.active, diff --git a/unpublishedScripts/marketplace/clap/clapApp.js b/unpublishedScripts/marketplace/clap/clapApp.js index a975d9d8b5..b2d8ce55db 100644 --- a/unpublishedScripts/marketplace/clap/clapApp.js +++ b/unpublishedScripts/marketplace/clap/clapApp.js @@ -16,7 +16,7 @@ // Load up engine var APP_NAME = "CLAP"; var ClapEngine = Script.require(Script.resolvePath("scripts/ClapEngine.js?v9")); -var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); // Define Menu var blackIcon = Script.resolvePath("icons/tablet-icons/clap-a.svg?foxv2"); diff --git a/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js b/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js index 278f4efbaa..c09ad602f8 100644 --- a/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js +++ b/unpublishedScripts/marketplace/doppleganger-attachments/app-doppleganger-attachments.js @@ -45,7 +45,7 @@ var buttonConfig = utils.assign({ activeIcon: require('./doppleganger-a.svg.json'), }); -var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), +var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton(buttonConfig); Script.scriptEnding.connect(function() { diff --git a/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js b/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js index 1cb7610ff3..bc5368ba5b 100644 --- a/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js +++ b/unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js @@ -905,7 +905,7 @@ var buttonConfig = utils.assign({ activeIcon: __webpack_require__(7), }); -var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), +var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton(buttonConfig); Script.scriptEnding.connect(function() { diff --git a/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js b/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js index d02dd3e9ba..f4c7bf99c0 100644 --- a/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js +++ b/unpublishedScripts/marketplace/doppleganger-mirror/app-doppleganger.js @@ -12,7 +12,7 @@ var DopplegangerClass = Script.require('./doppleganger.js'); -var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'), +var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), button = tablet.addButton({ icon: Script.resolvePath('./doppleganger-i.svg'), activeIcon: Script.resolvePath('./doppleganger-a.svg'), diff --git a/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js b/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js index 687c9445cd..b4d01e77cf 100644 --- a/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js +++ b/unpublishedScripts/marketplace/emoji-tablet/emojiTablet.js @@ -19,7 +19,7 @@ var lib = Script.require("https://hifi-content.s3.amazonaws.com/elisalj/emoji_sc var APP_NAME = "EMOJIS"; var APP_URL = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/emojiTabletUI.html?" + Date.now(); var APP_ICON = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/icons/emoji-i.svg"; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: APP_ICON, diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index 32cc75dd42..515a2c3a76 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -17,7 +17,7 @@ var TRIGGER_PRESSURE = 0.95; - var tablet = Tablets.getTablet('com.highfidelity.interface.tablet.system'); + var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'); var button = tablet.addButton({ icon: APP_ICON, diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 6392f10892..68c7ea3f5a 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -631,7 +631,7 @@ } function setUp() { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } @@ -694,7 +694,7 @@ } // FIXME: If setUp() is run immediately at Interface start-up, Interface hangs and crashes because of the line of code: - // tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + // tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); //setUp(); //Script.scriptEnding.connect(tearDown); Script.setTimeout(function () { diff --git a/unpublishedScripts/marketplace/shapes/shapes.js b/unpublishedScripts/marketplace/shapes/shapes.js index de177f435e..cd5f119588 100644 --- a/unpublishedScripts/marketplace/shapes/shapes.js +++ b/unpublishedScripts/marketplace/shapes/shapes.js @@ -1930,7 +1930,7 @@ function setUp() { var hasRezPermissions; - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { App.log("ERROR: Tablet not found! App not started."); return; diff --git a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js index 114bccb034..7bc65722cd 100644 --- a/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js +++ b/unpublishedScripts/marketplace/skyboxChanger/skyboxchanger.js @@ -28,7 +28,7 @@ } } - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: ICONS.icon, activeIcon: ICONS.activeIcon, diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index cc600632e5..27c4eaef7b 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -188,7 +188,7 @@ // -tablet: The tablet instance to be modified. var tablet = null; function startup() { - tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); addOrRemoveButton(false, HMD.active); tablet.screenChanged.connect(onTabletScreenChanged); Window.domainChanged.connect(onDomainChanged); diff --git a/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js index 2f895d5f94..f7702053a4 100644 --- a/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js +++ b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js @@ -20,7 +20,7 @@ var isRaiseHandButtonActive = false; var animHandlerId; - var tablet = Tablets.getTablet("com.highfidelity.interface.tablet.system"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ text: BUTTON_NAME, icon: "icons/tablet-icons/raise-hand-i.svg", From bb2e061d77d2d38cb95b048a10055428330b2d19 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Nov 2017 12:00:52 -0800 Subject: [PATCH 26/81] Fixing global declarations in JS --- interface/resources/qml/LoginDialog/LinkAccountBody.qml | 2 +- interface/resources/qml/LoginDialog/SignUpBody.qml | 2 +- interface/resources/qml/LoginDialog/UsernameCollisionBody.qml | 2 +- scripts/developer/tests/dynamics/dynamicsTests.js | 2 +- scripts/developer/tests/tabletEventBridgeTest.js | 2 +- scripts/developer/utilities/render/photobooth/photoboothApp.js | 2 +- scripts/system/audioMuteOverlay.js | 2 +- scripts/system/audioScope.js | 2 +- scripts/system/controllers/godView.js | 2 +- scripts/system/edit.js | 2 +- scripts/system/fingerPaint.js | 2 +- scripts/system/generalSettings.js | 2 +- scripts/system/goto.js | 2 +- scripts/system/help.js | 2 +- scripts/system/hmd.js | 2 +- scripts/system/libraries/WebTablet.js | 2 +- scripts/system/libraries/entityList.js | 2 +- scripts/system/marketplaces/marketplaces.js | 2 +- scripts/system/notifications.js | 2 +- scripts/system/pal.js | 2 +- scripts/system/snapshot.js | 2 +- scripts/system/tablet-goto.js | 2 +- scripts/system/tablet-ui/tabletUI.js | 2 +- scripts/tutorials/createFloatingLanternBox.js | 2 +- scripts/tutorials/createTetherballStick.js | 2 +- scripts/tutorials/entity_scripts/floatingLantern.js | 2 +- scripts/tutorials/entity_scripts/floatingLanternBox.js | 2 +- scripts/tutorials/entity_scripts/tetherballStick.js | 2 +- .../marketplace/spectator-camera/spectatorCamera.js | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 552291c186..300bcd46f0 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -248,7 +248,7 @@ Item { //dont rise local keyboard keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablets interface + //but rise Tablet's one instead for Tablet interface if (root.isTablet) { root.keyboardEnabled = HMD.active; root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index e521e16a60..9d55998b40 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -221,7 +221,7 @@ Item { root.iconText = "<" //dont rise local keyboard keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablets interface + //but rise Tablet's one instead for Tablet interface if (root.isTablet) { root.keyboardEnabled = HMD.active; root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index 185cbd9d47..5c212578b8 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -131,7 +131,7 @@ Item { root.iconText = "<" //dont rise local keyboard keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablets interface + //but rise Tablet's one instead for Tablet interface if (root.isTablet) { root.keyboardEnabled = HMD.active; root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) diff --git a/scripts/developer/tests/dynamics/dynamicsTests.js b/scripts/developer/tests/dynamics/dynamicsTests.js index fa51403732..c0b001eab3 100644 --- a/scripts/developer/tests/dynamics/dynamicsTests.js +++ b/scripts/developer/tests/dynamics/dynamicsTests.js @@ -11,7 +11,7 @@ "use strict"; -/* global Entities, Script, Tablets, MyAvatar, Vec3 */ +/* global Entities, Script, Tablet, MyAvatar, Vec3 */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/developer/tests/tabletEventBridgeTest.js b/scripts/developer/tests/tabletEventBridgeTest.js index d386b220fc..83031741fc 100644 --- a/scripts/developer/tests/tabletEventBridgeTest.js +++ b/scripts/developer/tests/tabletEventBridgeTest.js @@ -11,7 +11,7 @@ // Adds a button to the tablet that will switch to a web page. // This web page contains buttons that will use the event bridge to trigger sounds. -/* globals Tablets */ +/* globals Tablet */ var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 0e8eef7352..154028f091 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -8,7 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablets, Toolbars, Script, HMD, Controller, Menu */ +/* globals Tablet, Toolbars, Script, HMD, Controller, Menu */ (function () { var SNAPSHOT_DELAY = 500; // 500ms var PHOTOBOOTH_WINDOW_HTML_URL = Script.resolvePath("./html/photobooth.html"); diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 0db4edb85d..731d62017d 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // audioMuteOverlay.js diff --git a/scripts/system/audioScope.js b/scripts/system/audioScope.js index 07efb17046..81d8e8fbd4 100644 --- a/scripts/system/audioScope.js +++ b/scripts/system/audioScope.js @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, Tablets, AudioScope, Audio */ +/* global Script, Tablet, AudioScope, Audio */ (function () { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/controllers/godView.js b/scripts/system/controllers/godView.js index 9551c886c9..4b406399fd 100644 --- a/scripts/system/controllers/godView.js +++ b/scripts/system/controllers/godView.js @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals HMD, Script, Menu, Tablets, Camera */ +/* globals HMD, Script, Menu, Tablet, Camera */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/edit.js b/scripts/system/edit.js index c4a8f0f54f..2bbd422c65 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -11,7 +11,7 @@ // /* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, Overlays, OverlayWebWindow, UserActivityLogger, - Settings, Entities, Tablets, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool */ + Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 06403b77b7..88245503e8 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -419,7 +419,7 @@ return; } - // Tablets button. + // Tablet button. button = tablet.addButton({ icon: "icons/tablet-icons/finger-paint-i.svg", activeIcon: "icons/tablet-icons/finger-paint-a.svg", diff --git a/scripts/system/generalSettings.js b/scripts/system/generalSettings.js index 0e917d6ae4..082528ffc5 100644 --- a/scripts/system/generalSettings.js +++ b/scripts/system/generalSettings.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablets, Toolbars, Script, HMD, DialogsManager */ +/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/goto.js b/scripts/system/goto.js index f301af60bd..d364bf579e 100644 --- a/scripts/system/goto.js +++ b/scripts/system/goto.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablets, Toolbars, Script, HMD, DialogsManager */ +/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/help.js b/scripts/system/help.js index cf0cd3c003..9ab7fa3fb3 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablets, Script, HMD, Controller, Menu */ +/* globals Tablet, Script, HMD, Controller, Menu */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index e4f6455876..b9fd7f725c 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -10,7 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals HMD, Script, Menu, Tablets, Camera */ +/* globals HMD, Script, Menu, Tablet, Camera */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 0fb4258f68..c46cfaa073 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -7,7 +7,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global getControllerWorldLocation, Tablets, WebTablet:true, HMD, Settings, Script, +/* global getControllerWorldLocation, Tablet, WebTablet:true, HMD, Settings, Script, Vec3, Quat, MyAvatar, Entities, Overlays, Camera, Messages, Xform, clamp, Controller, Mat4, resizeTablet */ Script.include(Script.resolvePath("../libraries/utils.js")); diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index 70e0645757..9d9689000e 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global EntityListTool, Tablets, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, +/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */ EntityListTool = function(opts) { diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 750194bed2..4f2e47ee07 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Tablets, Script, HMD, UserActivityLogger, Entities */ +/* global Tablet, Script, HMD, UserActivityLogger, Entities */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function () { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index e1741cfa3b..b6ddd9d33e 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Script, Settings, Window, Controller, Overlays, SoundArray, LODManager, MyAvatar, Tablets, Camera, HMD, Menu, Quat, Vec3*/ +/*global Script, Settings, Window, Controller, Overlays, SoundArray, LODManager, MyAvatar, Tablet, Camera, HMD, Menu, Quat, Vec3*/ // // notifications.js // Version 0.801 diff --git a/scripts/system/pal.js b/scripts/system/pal.js index bd318193cf..ed7059f9f3 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Tablets, Settings, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, HMD, Controller, Account, UserActivityLogger, Messages, Window, XMLHttpRequest, print, location, getControllerWorldLocation*/ +/*global Tablet, Settings, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, HMD, Controller, Account, UserActivityLogger, Messages, Window, XMLHttpRequest, print, location, getControllerWorldLocation*/ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // pal.js diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index a14e1f2772..9afdb4ec53 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -7,7 +7,7 @@ // Distributed under the Apache License, Version 2.0 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablets, Script, HMD, Settings, DialogsManager, Menu, Reticle, OverlayWebWindow, Desktop, Account, MyAvatar, Snapshot */ +/* globals Tablet, Script, HMD, Settings, DialogsManager, Menu, Reticle, OverlayWebWindow, Desktop, Account, MyAvatar, Snapshot */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function () { // BEGIN LOCAL_SCOPE diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js index 8347fcff9a..2a0e827932 100644 --- a/scripts/system/tablet-goto.js +++ b/scripts/system/tablet-goto.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Window, Script, Tablets, HMD, Controller, Account, XMLHttpRequest, location, print*/ +/*global Window, Script, Tablet, HMD, Controller, Account, XMLHttpRequest, location, print*/ // // goto.js diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 0032239867..17821c737e 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablets, Overlays, +/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays, MyAvatar, Menu, AvatarInputs, Vec3 */ (function() { // BEGIN LOCAL_SCOPE diff --git a/scripts/tutorials/createFloatingLanternBox.js b/scripts/tutorials/createFloatingLanternBox.js index c83535fa37..c84214e295 100644 --- a/scripts/tutorials/createFloatingLanternBox.js +++ b/scripts/tutorials/createFloatingLanternBox.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // createFloatinLanternBox.js diff --git a/scripts/tutorials/createTetherballStick.js b/scripts/tutorials/createTetherballStick.js index 3ad0939c2e..35f5fb0344 100644 --- a/scripts/tutorials/createTetherballStick.js +++ b/scripts/tutorials/createTetherballStick.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // createTetherballStick.js diff --git a/scripts/tutorials/entity_scripts/floatingLantern.js b/scripts/tutorials/entity_scripts/floatingLantern.js index c2a79c9c5b..aa25dc0003 100644 --- a/scripts/tutorials/entity_scripts/floatingLantern.js +++ b/scripts/tutorials/entity_scripts/floatingLantern.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // floatinLantern.js diff --git a/scripts/tutorials/entity_scripts/floatingLanternBox.js b/scripts/tutorials/entity_scripts/floatingLanternBox.js index b8e0fbda3e..b5fb0c27d9 100644 --- a/scripts/tutorials/entity_scripts/floatingLanternBox.js +++ b/scripts/tutorials/entity_scripts/floatingLanternBox.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // floatingLanternBox.js diff --git a/scripts/tutorials/entity_scripts/tetherballStick.js b/scripts/tutorials/entity_scripts/tetherballStick.js index 50bac88caf..867074abd4 100644 --- a/scripts/tutorials/entity_scripts/tetherballStick.js +++ b/scripts/tutorials/entity_scripts/tetherballStick.js @@ -1,6 +1,6 @@ "use strict"; /* jslint vars: true, plusplus: true, forin: true*/ -/* globals Tablets, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // tetherballStick.js diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js index 27c4eaef7b..76044d2975 100644 --- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js +++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars:true, plusplus:true, forin:true*/ -/*global Tablets, Script, */ +/*global Tablet, Script, */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // spectatorCamera.js From 0ad399974132417c0181d35af6dd46806730022e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Nov 2017 12:24:00 -0800 Subject: [PATCH 27/81] Fixing misname --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index ebd30f9342..b83e7e3afa 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -394,7 +394,7 @@ void initializeQmlEngine(QQmlEngine* engine, QQuickWindow* window) { rootContext->setContextProperty("Tablet", DependencyManager::get().data()); rootContext->setContextProperty("Toolbars", DependencyManager::get().data()); TabletProxy* tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); - myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); + engine->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } QQmlEngine* acquireEngine(QQuickWindow* window) { From 93c3d5314421256547d8518885993f91e76387b1 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 15 Nov 2017 16:46:00 -0800 Subject: [PATCH 28/81] Fix marketplaces.js URLs --- scripts/system/marketplaces/marketplaces.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 4f2e47ee07..c94db0d0e6 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -20,10 +20,9 @@ var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page. var MARKETPLACES_URL = Script.resolvePath("../html/marketplaces.html"); var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js"); - var MARKETPLACE_CHECKOUT_QML_PATH_BASE = "qml/hifi/commerce/checkout/Checkout.qml"; - var MARKETPLACE_CHECKOUT_QML_PATH = Script.resourcesPath() + MARKETPLACE_CHECKOUT_QML_PATH_BASE; - var MARKETPLACE_PURCHASES_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/purchases/Purchases.qml"; - var MARKETPLACE_WALLET_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/wallet/Wallet.qml"; + var MARKETPLACE_CHECKOUT_QML_PATH = "hifi/commerce/checkout/Checkout.qml"; + var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/purchases/Purchases.qml"; + var MARKETPLACE_WALLET_QML_PATH = "hifi/commerce/wallet/Wallet.qml"; var MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH = "commerce/inspectionCertificate/InspectionCertificate.qml"; var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; @@ -110,7 +109,7 @@ var filterText; // Used for updating Purchases QML function onScreenChanged(type, url) { onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1; - onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH_BASE) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1); + onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1); wireEventBridge(onCommerceScreen); if (url === MARKETPLACE_PURCHASES_QML_PATH) { From d31578abae3a1310b8224e6505a19866c1c54ebd Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 17 Nov 2017 15:47:02 -0800 Subject: [PATCH 29/81] FIXME LATER! Remove mouseareas from passphrase screens --- .../hifi/commerce/wallet/PassphraseModal.qml | 16 +++---- .../commerce/wallet/PassphraseSelection.qml | 48 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index 9f04db7d5c..44dda1b7ad 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -206,15 +206,15 @@ Item { root.isPasswordField = (focus && passphraseField.echoMode === TextInput.Password); } - MouseArea { - anchors.fill: parent; + //MouseArea { + // anchors.fill: parent; - onClicked: { - root.keyboardRaised = true; - root.isPasswordField = (passphraseField.echoMode === TextInput.Password); - mouse.accepted = false; - } - } + // onClicked: { + // root.keyboardRaised = true; + // root.isPasswordField = (passphraseField.echoMode === TextInput.Password); + // mouse.accepted = false; + // } + //} onAccepted: { submitPassphraseInputButton.enabled = false; diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml index 0145f92b96..cc23e6bb4d 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml @@ -87,14 +87,14 @@ Item { } } - MouseArea { - anchors.fill: parent; - onPressed: { - var hidePassword = (currentPassphraseField.echoMode === TextInput.Password); - sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword}); - mouse.accepted = false; - } - } + //MouseArea { + // anchors.fill: parent; + // onPressed: { + // var hidePassword = (currentPassphraseField.echoMode === TextInput.Password); + // sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword}); + // mouse.accepted = false; + // } + //} onAccepted: { passphraseField.focus = true; @@ -115,14 +115,14 @@ Item { activeFocusOnPress: true; activeFocusOnTab: true; - MouseArea { - anchors.fill: parent; - onPressed: { - var hidePassword = (passphraseField.echoMode === TextInput.Password); - sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword}); - mouse.accepted = false; - } - } + //MouseArea { + // anchors.fill: parent; + // onPressed: { + // var hidePassword = (passphraseField.echoMode === TextInput.Password); + // sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword}); + // mouse.accepted = false; + // } + //} onFocusChanged: { if (focus) { @@ -151,14 +151,14 @@ Item { activeFocusOnPress: true; activeFocusOnTab: true; - MouseArea { - anchors.fill: parent; - onPressed: { - var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password); - sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword}); - mouse.accepted = false; - } - } + //MouseArea { + // anchors.fill: parent; + // onPressed: { + // var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password); + // sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword}); + // mouse.accepted = false; + // } + //} onFocusChanged: { if (focus) { From 4374b4f9a83c4775a99719b6fd6c7193cdb402dc Mon Sep 17 00:00:00 2001 From: humbletim Date: Mon, 11 Dec 2017 00:39:23 -0500 Subject: [PATCH 30/81] forward MIDI_CONTROL_CHANGE events --- libraries/midi/src/Midi.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/midi/src/Midi.cpp b/libraries/midi/src/Midi.cpp index ad650cf067..6c2471f680 100644 --- a/libraries/midi/src/Midi.cpp +++ b/libraries/midi/src/Midi.cpp @@ -177,9 +177,10 @@ void Midi::MidiCleanup() { #endif void Midi::noteReceived(int status, int note, int velocity) { - if (((status & MIDI_STATUS_MASK) != MIDI_NOTE_OFF) && - ((status & MIDI_STATUS_MASK) != MIDI_NOTE_ON)) { - return; // NOTE: only sending note-on and note-off to Javascript + if (((status & MIDI_STATUS_MASK) != MIDI_NOTE_OFF) && + ((status & MIDI_STATUS_MASK) != MIDI_NOTE_ON) && + ((status & MIDI_STATUS_MASK) != MIDI_CONTROL_CHANGE)) { + return; // NOTE: only sending note-on, note-off, and control-change to Javascript } QVariantMap eventData; From 2d786451c2a8be3221b9f4c6c618a0b0a4ca10b8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 11 Dec 2017 10:50:24 -0800 Subject: [PATCH 31/81] Add comment --- libraries/ui/src/QmlWindowClass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 1758150e0a..90b91c5ec2 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -61,6 +61,7 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) { } QUrl url { properties[SOURCE_PROPERTY].toString() }; + // If the passed URL doesn't correspond to a known scheme, assume it's a local file path if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" && url.scheme() != "atp" && url.scheme() != "qrc") { properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString(); From 2225352b1e151d574d03356838a3e1e10e65f703 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 11 Dec 2017 17:15:15 -0800 Subject: [PATCH 32/81] Fix wallet setup --- .../qml/hifi/commerce/wallet/Wallet.qml | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml index 74d3b294bc..8ebd3ecc84 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml @@ -49,7 +49,7 @@ Rectangle { } else if (walletStatus === 1) { if (root.activeView !== "walletSetup") { root.activeView = "walletSetup"; - commerce.resetLocalWalletOnly(); + Commerce.resetLocalWalletOnly(); var timestamp = new Date(); walletSetup.startingTimestamp = timestamp; walletSetup.setupAttemptID = generateUUID(); @@ -61,8 +61,10 @@ Rectangle { root.activeView = "passphraseModal"; } } else if (walletStatus === 3) { - root.activeView = "walletHome"; - Commerce.getSecurityImage(); + if (root.activeView !== "walletSetup") { + root.activeView = "walletHome"; + Commerce.getSecurityImage(); + } } else { console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus); } @@ -211,17 +213,19 @@ Rectangle { Connections { onSendSignalToWallet: { - if (msg.method === 'walletSetup_raiseKeyboard') { - root.keyboardRaised = true; - root.isPassword = msg.isPasswordField; - } else if (msg.method === 'walletSetup_lowerKeyboard') { - root.keyboardRaised = false; - } else if (msg.method === 'walletSecurity_changePassphraseCancelled') { - root.activeView = "security"; - } else if (msg.method === 'walletSecurity_changePassphraseSuccess') { - root.activeView = "security"; - } else { - sendToScript(msg); + if (passphraseChange.visible) { + if (msg.method === 'walletSetup_raiseKeyboard') { + root.keyboardRaised = true; + root.isPassword = msg.isPasswordField; + } else if (msg.method === 'walletSetup_lowerKeyboard') { + root.keyboardRaised = false; + } else if (msg.method === 'walletSecurity_changePassphraseCancelled') { + root.activeView = "security"; + } else if (msg.method === 'walletSecurity_changePassphraseSuccess') { + root.activeView = "security"; + } else { + sendToScript(msg); + } } } } From a1f1e7b587959b541cd17c1b5ead0474a20960ac Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 12 Dec 2017 18:20:29 -0700 Subject: [PATCH 33/81] Fix web entities accessing the webcam RC61 --- interface/resources/html/createGlobalEventBridge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/html/createGlobalEventBridge.js b/interface/resources/html/createGlobalEventBridge.js index b85aa33e33..a180fbc6cc 100644 --- a/interface/resources/html/createGlobalEventBridge.js +++ b/interface/resources/html/createGlobalEventBridge.js @@ -34,7 +34,7 @@ var EventBridge; var tempEventBridge = EventBridge; EventBridge = channel.objects.eventBridge; EventBridge.audioOutputDeviceChanged.connect(function(deviceName) { - navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(function(mediaStream) { + navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(function(mediaStream) { navigator.mediaDevices.enumerateDevices().then(function(devices) { devices.forEach(function(device) { if (device.kind == "audiooutput") { From 3a45907df078bdc20bc915ac7103e810fbf28d5c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 12 Dec 2017 17:16:07 -0800 Subject: [PATCH 34/81] Keep connection alive as long as the node is connected --- libraries/networking/src/udt/Connection.cpp | 82 ++++++++------------- libraries/networking/src/udt/Connection.h | 9 +-- libraries/networking/src/udt/SendQueue.cpp | 52 ++++++------- libraries/networking/src/udt/SendQueue.h | 8 +- libraries/networking/src/udt/Socket.cpp | 3 - 5 files changed, 57 insertions(+), 97 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index f42049f107..7a31bbeedc 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -11,6 +11,8 @@ #include "Connection.h" +#include + #include #include @@ -60,6 +62,15 @@ Connection::Connection(Socket* parentSocket, HifiSockAddr destination, std::uniq _ack2Packet = ControlPacket::create(ControlPacket::ACK2, ACK2_PAYLOAD_BYTES); _lossReport = ControlPacket::create(ControlPacket::NAK, NAK_PACKET_PAYLOAD_BYTES); _handshakeACK = ControlPacket::create(ControlPacket::HandshakeACK, HANDSHAKE_ACK_PAYLOAD_BYTES); + + + // setup psuedo-random number generation shared by all connections + static std::random_device rd; + static std::mt19937 generator(rd()); + static std::uniform_int_distribution<> distribution(0, SequenceNumber::MAX); + + // randomize the intial sequence number + _initialSequenceNumber = SequenceNumber(distribution(generator)); } Connection::~Connection() { @@ -81,9 +92,6 @@ void Connection::stopSendQueue() { sendQueue->stop(); sendQueue->deleteLater(); - // since we're stopping the send queue we should consider our handshake ACK not receieved - _hasReceivedHandshakeACK = false; - // wait on the send queue thread so we know the send queue is gone sendQueueThread->quit(); sendQueueThread->wait(); @@ -101,13 +109,22 @@ void Connection::setMaxBandwidth(int maxBandwidth) { SendQueue& Connection::getSendQueue() { if (!_sendQueue) { - // we may have a sequence number from the previous inactive queue - re-use that so that the // receiver is getting the sequence numbers it expects (given that the connection must still be active) // Lasily create send queue - _sendQueue = SendQueue::create(_parentSocket, _destination); - _lastReceivedACK = _sendQueue->getCurrentSequenceNumber(); + + if (!_hasReceivedHandshakeACK) { + // First time creating a send queue for this connection + _sendQueue = SendQueue::create(_parentSocket, _destination, _initialSequenceNumber - 1); + _lastReceivedACK = _sendQueue->getCurrentSequenceNumber(); + } else { + // Connection already has a handshake from a previous send queue + _sendQueue = SendQueue::create(_parentSocket, _destination, _lastReceivedACK); + // This connection has already gone through the handshake + // bypass it in the send queue + _sendQueue->handshakeACK(); + } #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Created SendQueue for connection to" << _destination; @@ -142,14 +159,6 @@ void Connection::queueInactive() { #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Connection to" << _destination << "has stopped its SendQueue."; #endif - - if (!_hasReceivedHandshake || !_isReceivingData) { -#ifdef UDT_CONNECTION_DEBUG - qCDebug(networking) << "Connection SendQueue to" << _destination << "stopped and no data is being received - stopping connection."; -#endif - - deactivate(); - } } void Connection::queueTimeout() { @@ -208,19 +217,6 @@ void Connection::sync() { && duration_cast(sincePacketReceive).count() >= MIN_SECONDS_BEFORE_EXPIRY ) { // the receive side of this connection is expired _isReceivingData = false; - - // if we don't have a send queue that means the whole connection has expired and we can emit our signal - // otherwise we'll wait for it to also timeout before cleaning up - if (!_sendQueue) { - -#ifdef UDT_CONNECTION_DEBUG - qCDebug(networking) << "Connection to" << _destination << "no longer receiving any data and there is currently no send queue - stopping connection."; -#endif - - deactivate(); - - return; - } } // reset the number of light ACKs or non SYN ACKs during this sync interval @@ -242,26 +238,6 @@ void Connection::sync() { sendTimeoutNAK(); } } - } else if (!_sendQueue) { - // we haven't received a packet and we're not sending - // this most likely means we were started erroneously - // check the start time for this connection and auto expire it after 5 seconds of not receiving or sending any data - static const int CONNECTION_NOT_USED_EXPIRY_SECONDS = 5; - auto secondsSinceStart = duration_cast(p_high_resolution_clock::now() - _connectionStart).count(); - - if (secondsSinceStart >= CONNECTION_NOT_USED_EXPIRY_SECONDS) { - // it's been CONNECTION_NOT_USED_EXPIRY_SECONDS and nothing has actually happened with this connection - // consider it inactive and emit our inactivity signal - -#ifdef UDT_CONNECTION_DEBUG - qCDebug(networking) << "Connection to" << _destination << "did not receive or send any data in last" - << CONNECTION_NOT_USED_EXPIRY_SECONDS << "seconds - stopping connection."; -#endif - - deactivate(); - - return; - } } } @@ -827,11 +803,13 @@ void Connection::processHandshakeACK(ControlPacketPointer controlPacket) { SequenceNumber initialSequenceNumber; controlPacket->readPrimitive(&initialSequenceNumber); - // hand off this handshake ACK to the send queue so it knows it can start sending - getSendQueue().handshakeACK(initialSequenceNumber); - - // indicate that handshake ACK was received - _hasReceivedHandshakeACK = true; + if (initialSequenceNumber == _initialSequenceNumber) { + // hand off this handshake ACK to the send queue so it knows it can start sending + getSendQueue().handshakeACK(); + + // indicate that handshake ACK was received + _hasReceivedHandshakeACK = true; + } } } diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index c134081dde..a13c29adc8 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -72,8 +72,6 @@ public: void queueReceivedMessagePacket(std::unique_ptr packet); ConnectionStats::Stats sampleStats() { return _stats.sample(); } - - bool isActive() const { return _isActive; } HifiSockAddr getDestination() const { return _destination; } @@ -83,7 +81,6 @@ public: signals: void packetSent(); - void connectionInactive(const HifiSockAddr& sockAddr); void receiverHandshakeRequestComplete(const HifiSockAddr& sockAddr); private slots: @@ -112,8 +109,6 @@ private: void resetReceiveState(); void resetRTT(); - void deactivate() { _isActive = false; emit connectionInactive(_destination); } - SendQueue& getSendQueue(); SequenceNumber nextACK() const; void updateRTT(int rtt); @@ -138,9 +133,9 @@ private: p_high_resolution_clock::time_point _lastReceiveTime; // holds the last time we received anything from sender bool _isReceivingData { false }; // flag used for expiry of receipt portion of connection - bool _isActive { true }; // flag used for inactivity of connection - SequenceNumber _initialReceiveSequenceNumber; // Randomized by peer SendQueue on creation, identifies connection during re-connect requests + SequenceNumber _initialSequenceNumber; // Randomized on Connection creation, identifies connection during re-connect requests + SequenceNumber _initialReceiveSequenceNumber; // Randomized by peer Connection on creation, identifies connection during re-connect requests LossList _lossList; // List of all missing packets SequenceNumber _lastReceivedSequenceNumber; // The largest sequence number received from the peer diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 0c029751aa..ef249b8f75 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -12,7 +12,6 @@ #include "SendQueue.h" #include -#include #include #include @@ -62,10 +61,10 @@ private: Mutex2& _mutex2; }; -std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination) { +std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber) { Q_ASSERT_X(socket, "SendQueue::create", "Must be called with a valid Socket*"); - auto queue = std::unique_ptr(new SendQueue(socket, destination)); + auto queue = std::unique_ptr(new SendQueue(socket, destination, currentSequenceNumber)); // Setup queue private thread QThread* thread = new QThread; @@ -84,20 +83,12 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin return queue; } -SendQueue::SendQueue(Socket* socket, HifiSockAddr dest) : +SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber) : _socket(socket), _destination(dest) { - // setup psuedo-random number generation for all instances of SendQueue - static std::random_device rd; - static std::mt19937 generator(rd()); - static std::uniform_int_distribution<> distribution(0, SequenceNumber::MAX); - - // randomize the intial sequence number - _initialSequenceNumber = SequenceNumber(distribution(generator)); - - // set our member variables from randomized initial number - _currentSequenceNumber = _initialSequenceNumber - 1; + // set our member variables from current sequence number + _currentSequenceNumber = currentSequenceNumber; _atomicCurrentSequenceNumber = uint32_t(_currentSequenceNumber); _lastACKSequenceNumber = uint32_t(_currentSequenceNumber) - 1; @@ -114,8 +105,8 @@ void SendQueue::queuePacket(std::unique_ptr packet) { // call notify_one on the condition_variable_any in case the send thread is sleeping waiting for packets _emptyCondition.notify_one(); - if (!this->thread()->isRunning() && _state == State::NotStarted) { - this->thread()->start(); + if (!thread()->isRunning() && _state == State::NotStarted) { + thread()->start(); } } @@ -125,8 +116,8 @@ void SendQueue::queuePacketList(std::unique_ptr packetList) { // call notify_one on the condition_variable_any in case the send thread is sleeping waiting for packets _emptyCondition.notify_one(); - if (!this->thread()->isRunning() && _state == State::NotStarted) { - this->thread()->start(); + if (!thread()->isRunning() && _state == State::NotStarted) { + thread()->start(); } } @@ -225,8 +216,11 @@ void SendQueue::sendHandshake() { std::unique_lock handshakeLock { _handshakeMutex }; if (!_hasReceivedHandshakeACK) { // we haven't received a handshake ACK from the client, send another now + // if the handshake hasn't been completed, then the initial sequence number + // should be the current sequence number + 1 + SequenceNumber initialSequenceNumber = _currentSequenceNumber + 1; auto handshakePacket = ControlPacket::create(ControlPacket::Handshake, sizeof(SequenceNumber)); - handshakePacket->writePrimitive(_initialSequenceNumber); + handshakePacket->writePrimitive(initialSequenceNumber); _socket->writeBasePacket(*handshakePacket, _destination); // we wait for the ACK or the re-send interval to expire @@ -235,18 +229,16 @@ void SendQueue::sendHandshake() { } } -void SendQueue::handshakeACK(SequenceNumber initialSequenceNumber) { - if (initialSequenceNumber == _initialSequenceNumber) { - { - std::lock_guard locker { _handshakeMutex }; - _hasReceivedHandshakeACK = true; - } - - _lastReceiverResponse = QDateTime::currentMSecsSinceEpoch(); - - // Notify on the handshake ACK condition - _handshakeACKCondition.notify_one(); +void SendQueue::handshakeACK() { + { + std::lock_guard locker { _handshakeMutex }; + _hasReceivedHandshakeACK = true; } + + _lastReceiverResponse = QDateTime::currentMSecsSinceEpoch(); + + // Notify on the handshake ACK condition + _handshakeACKCondition.notify_one(); } SequenceNumber SendQueue::getNextSequenceNumber() { diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 484afcb88e..b6cec15ffd 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -50,7 +50,7 @@ public: Stopped }; - static std::unique_ptr create(Socket* socket, HifiSockAddr destination); + static std::unique_ptr create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber); virtual ~SendQueue(); @@ -76,7 +76,7 @@ public slots: void nak(SequenceNumber start, SequenceNumber end); void fastRetransmit(SequenceNumber ack); void overrideNAKListFromPacket(ControlPacket& packet); - void handshakeACK(SequenceNumber initialSequenceNumber); + void handshakeACK(); signals: void packetSent(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint); @@ -91,7 +91,7 @@ private slots: void run(); private: - SendQueue(Socket* socket, HifiSockAddr dest); + SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber); SendQueue(SendQueue& other) = delete; SendQueue(SendQueue&& other) = delete; @@ -115,8 +115,6 @@ private: Socket* _socket { nullptr }; // Socket to send packet on HifiSockAddr _destination; // Destination addr - - SequenceNumber _initialSequenceNumber; // Randomized on SendQueue creation, identifies connection during re-connect requests std::atomic _lastACKSequenceNumber { 0 }; // Last ACKed sequence number diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index a3374a0f47..55643985c8 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -257,9 +257,6 @@ Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) { congestionControl->setMaxBandwidth(_maxBandwidth); auto connection = std::unique_ptr(new Connection(this, sockAddr, std::move(congestionControl))); - // we queue the connection to cleanup connection in case it asks for it during its own rate control sync - QObject::connect(connection.get(), &Connection::connectionInactive, this, &Socket::cleanupConnection); - // allow higher-level classes to find out when connections have completed a handshake QObject::connect(connection.get(), &Connection::receiverHandshakeRequestComplete, this, &Socket::clientHandshakeRequestComplete); From 44190f16c09fa3aae2330318c426364bbe0e8c47 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 13 Dec 2017 16:55:08 -0800 Subject: [PATCH 35/81] Reset ACK in ctor --- libraries/networking/src/udt/Connection.cpp | 7 ++----- libraries/networking/src/udt/SendQueue.cpp | 15 +++++++++++---- libraries/networking/src/udt/SendQueue.h | 4 ++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 7a31bbeedc..5f632fa25f 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -116,14 +116,11 @@ SendQueue& Connection::getSendQueue() { if (!_hasReceivedHandshakeACK) { // First time creating a send queue for this connection - _sendQueue = SendQueue::create(_parentSocket, _destination, _initialSequenceNumber - 1); + _sendQueue = SendQueue::create(_parentSocket, _destination, _initialSequenceNumber - 1, _hasReceivedHandshakeACK); _lastReceivedACK = _sendQueue->getCurrentSequenceNumber(); } else { // Connection already has a handshake from a previous send queue - _sendQueue = SendQueue::create(_parentSocket, _destination, _lastReceivedACK); - // This connection has already gone through the handshake - // bypass it in the send queue - _sendQueue->handshakeACK(); + _sendQueue = SendQueue::create(_parentSocket, _destination, _lastReceivedACK, _hasReceivedHandshakeACK); } #ifdef UDT_CONNECTION_DEBUG diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index ef249b8f75..3dbfb35fbe 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -61,10 +61,10 @@ private: Mutex2& _mutex2; }; -std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber) { +std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK) { Q_ASSERT_X(socket, "SendQueue::create", "Must be called with a valid Socket*"); - auto queue = std::unique_ptr(new SendQueue(socket, destination, currentSequenceNumber)); + auto queue = std::unique_ptr(new SendQueue(socket, destination, currentSequenceNumber, hasReceivedHandshakeACK)); // Setup queue private thread QThread* thread = new QThread; @@ -83,14 +83,21 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin return queue; } -SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber) : +SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK) : _socket(socket), _destination(dest) { // set our member variables from current sequence number _currentSequenceNumber = currentSequenceNumber; _atomicCurrentSequenceNumber = uint32_t(_currentSequenceNumber); - _lastACKSequenceNumber = uint32_t(_currentSequenceNumber) - 1; + + if (hasReceivedHandshakeACK) { + _lastACKSequenceNumber = uint32_t(_currentSequenceNumber); + } else { + _lastACKSequenceNumber = uint32_t(_currentSequenceNumber - 1); + } + + _hasReceivedHandshakeACK = hasReceivedHandshakeACK; // default the last receiver response to the current time _lastReceiverResponse = QDateTime::currentMSecsSinceEpoch(); diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index b6cec15ffd..29fe6b35ff 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -50,7 +50,7 @@ public: Stopped }; - static std::unique_ptr create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber); + static std::unique_ptr create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK); virtual ~SendQueue(); @@ -91,7 +91,7 @@ private slots: void run(); private: - SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber); + SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK); SendQueue(SendQueue& other) = delete; SendQueue(SendQueue&& other) = delete; From 553e4e24493080d66b1787bf534595144f97e77c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 13 Dec 2017 17:26:23 -0800 Subject: [PATCH 36/81] fix RPATH for oven so it loads things from macdeployqt --- tools/oven/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/oven/CMakeLists.txt b/tools/oven/CMakeLists.txt index 321f81ba8f..5e30b84803 100644 --- a/tools/oven/CMakeLists.txt +++ b/tools/oven/CMakeLists.txt @@ -8,13 +8,14 @@ setup_memory_debugger() if (WIN32) package_libraries_for_deployment() -endif () - -if (UNIX) +elseif (UNIX) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) target_compile_options(PUBLIC oven "-pthread") endif() -endif () +elseif (APPLE) + # Fix up the rpath so macdeployqt works + set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks") +endif() install_beside_console() From 1f57ac608124b54e1e69d0dd18a52ebf93f19187 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 13 Dec 2017 18:08:39 -0800 Subject: [PATCH 37/81] don't trigger unix step on apple for oven --- tools/oven/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/oven/CMakeLists.txt b/tools/oven/CMakeLists.txt index 5e30b84803..00344179bd 100644 --- a/tools/oven/CMakeLists.txt +++ b/tools/oven/CMakeLists.txt @@ -8,7 +8,7 @@ setup_memory_debugger() if (WIN32) package_libraries_for_deployment() -elseif (UNIX) +elseif (UNIX AND NOT APPLE) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) target_compile_options(PUBLIC oven "-pthread") From ad547f483d76cb488f929dbc95874795e144e503 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 13 Dec 2017 19:25:24 -0800 Subject: [PATCH 38/81] Keep track of message numbers --- libraries/networking/src/udt/Connection.cpp | 10 ++++++---- libraries/networking/src/udt/Connection.h | 2 ++ libraries/networking/src/udt/PacketQueue.cpp | 2 +- libraries/networking/src/udt/PacketQueue.h | 4 +++- libraries/networking/src/udt/SendQueue.cpp | 19 +++++++++---------- libraries/networking/src/udt/SendQueue.h | 8 ++++++-- 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 5f632fa25f..fc590c3a66 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -90,6 +90,9 @@ void Connection::stopSendQueue() { // tell the send queue to stop and be deleted sendQueue->stop(); + + _lastMessageNumber = sendQueue->getCurrentMessageNumber(); + sendQueue->deleteLater(); // wait on the send queue thread so we know the send queue is gone @@ -116,11 +119,11 @@ SendQueue& Connection::getSendQueue() { if (!_hasReceivedHandshakeACK) { // First time creating a send queue for this connection - _sendQueue = SendQueue::create(_parentSocket, _destination, _initialSequenceNumber - 1, _hasReceivedHandshakeACK); + _sendQueue = SendQueue::create(_parentSocket, _destination, _initialSequenceNumber - 1, _lastMessageNumber, _hasReceivedHandshakeACK); _lastReceivedACK = _sendQueue->getCurrentSequenceNumber(); } else { // Connection already has a handshake from a previous send queue - _sendQueue = SendQueue::create(_parentSocket, _destination, _lastReceivedACK, _hasReceivedHandshakeACK); + _sendQueue = SendQueue::create(_parentSocket, _destination, _lastReceivedACK, _lastMessageNumber, _hasReceivedHandshakeACK); } #ifdef UDT_CONNECTION_DEBUG @@ -417,7 +420,6 @@ void Connection::sendHandshakeRequest() { } bool Connection::processReceivedSequenceNumber(SequenceNumber sequenceNumber, int packetSize, int payloadSize) { - if (!_hasReceivedHandshake) { // Refuse to process any packets until we've received the handshake // Send handshake request to re-request a handshake @@ -509,7 +511,7 @@ bool Connection::processReceivedSequenceNumber(SequenceNumber sequenceNumber, in } else { _stats.recordReceivedPackets(payloadSize, packetSize); } - + return !wasDuplicate; } diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index a13c29adc8..4f979750f9 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -137,6 +137,8 @@ private: SequenceNumber _initialSequenceNumber; // Randomized on Connection creation, identifies connection during re-connect requests SequenceNumber _initialReceiveSequenceNumber; // Randomized by peer Connection on creation, identifies connection during re-connect requests + MessageNumber _lastMessageNumber; + LossList _lossList; // List of all missing packets SequenceNumber _lastReceivedSequenceNumber; // The largest sequence number received from the peer SequenceNumber _lastReceivedACK; // The last ACK received diff --git a/libraries/networking/src/udt/PacketQueue.cpp b/libraries/networking/src/udt/PacketQueue.cpp index 9560f2f187..0560855ecb 100644 --- a/libraries/networking/src/udt/PacketQueue.cpp +++ b/libraries/networking/src/udt/PacketQueue.cpp @@ -15,7 +15,7 @@ using namespace udt; -PacketQueue::PacketQueue() { +PacketQueue::PacketQueue(MessageNumber messageNumber) : _currentMessageNumber(messageNumber) { _channels.emplace_back(new std::list()); } diff --git a/libraries/networking/src/udt/PacketQueue.h b/libraries/networking/src/udt/PacketQueue.h index 2b3d3a4b5b..bc4c5e3432 100644 --- a/libraries/networking/src/udt/PacketQueue.h +++ b/libraries/networking/src/udt/PacketQueue.h @@ -34,7 +34,7 @@ class PacketQueue { using Channels = std::vector; public: - PacketQueue(); + PacketQueue(MessageNumber messageNumber = 0); void queuePacket(PacketPointer packet); void queuePacketList(PacketListPointer packetList); @@ -42,6 +42,8 @@ public: PacketPointer takePacket(); Mutex& getLock() { return _packetsLock; } + + MessageNumber getCurrentMessageNumber() const { return _currentMessageNumber; } private: MessageNumber getNextMessageNumber(); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 3dbfb35fbe..43477e4562 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -61,10 +61,12 @@ private: Mutex2& _mutex2; }; -std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK) { +std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber, + MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK) { Q_ASSERT_X(socket, "SendQueue::create", "Must be called with a valid Socket*"); - auto queue = std::unique_ptr(new SendQueue(socket, destination, currentSequenceNumber, hasReceivedHandshakeACK)); + auto queue = std::unique_ptr(new SendQueue(socket, destination, currentSequenceNumber, + currentMessageNumber, hasReceivedHandshakeACK)); // Setup queue private thread QThread* thread = new QThread; @@ -83,19 +85,16 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin return queue; } -SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK) : +SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, + MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK) : _socket(socket), - _destination(dest) + _destination(dest), + _packets(currentMessageNumber) { // set our member variables from current sequence number _currentSequenceNumber = currentSequenceNumber; _atomicCurrentSequenceNumber = uint32_t(_currentSequenceNumber); - - if (hasReceivedHandshakeACK) { - _lastACKSequenceNumber = uint32_t(_currentSequenceNumber); - } else { - _lastACKSequenceNumber = uint32_t(_currentSequenceNumber - 1); - } + _lastACKSequenceNumber = uint32_t(_currentSequenceNumber); _hasReceivedHandshakeACK = hasReceivedHandshakeACK; diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 29fe6b35ff..b33180c1e2 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -50,7 +50,9 @@ public: Stopped }; - static std::unique_ptr create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK); + static std::unique_ptr create(Socket* socket, HifiSockAddr destination, + SequenceNumber currentSequenceNumber, MessageNumber currentMessageNumber, + bool hasReceivedHandshakeACK); virtual ~SendQueue(); @@ -58,6 +60,7 @@ public: void queuePacketList(std::unique_ptr packetList); SequenceNumber getCurrentSequenceNumber() const { return SequenceNumber(_atomicCurrentSequenceNumber); } + MessageNumber getCurrentMessageNumber() const { return _packets.getCurrentMessageNumber(); } void setFlowWindowSize(int flowWindowSize) { _flowWindowSize = flowWindowSize; } @@ -91,7 +94,8 @@ private slots: void run(); private: - SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, bool hasReceivedHandshakeACK); + SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, + MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK); SendQueue(SendQueue& other) = delete; SendQueue(SendQueue&& other) = delete; From 77b102669e454b59f394e768b1752ff831719ee9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 12 Dec 2017 12:38:01 -0800 Subject: [PATCH 39/81] try harder to keep setTimeout loop going in controller-dispatcher --- scripts/system/controllers/controllerDispatcher.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 57f3b4fd8b..af3b1d2ed6 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -154,6 +154,15 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.update = function () { + try { + this.updateInternal(); + } catch (e) { + print(e); + } + Script.setTimeout(_this.update, BASIC_TIMER_INTERVAL_MS); + }; + + this.updateInternal = function () { if (PROFILE) { Script.beginProfileRange("dispatch.pre"); } @@ -376,7 +385,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); if (PROFILE) { Script.endProfileRange("dispatch.run"); } - Script.setTimeout(_this.update, BASIC_TIMER_INTERVAL_MS); }; this.setBlacklist = function() { From 9863458fef38ca0243c6d7945e16ba7a1192d6c5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 12 Dec 2017 12:59:35 -0800 Subject: [PATCH 40/81] oops --- scripts/system/controllers/controllerDispatcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index af3b1d2ed6..915b3b3680 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -155,7 +155,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.update = function () { try { - this.updateInternal(); + _this.updateInternal(); } catch (e) { print(e); } From 7f948586dd09afd464f7b5bb53756a29f45abd59 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 14 Dec 2017 12:07:32 -0800 Subject: [PATCH 41/81] fix message erase in conn, SendQueue ctor order --- libraries/networking/src/udt/Connection.cpp | 13 +++++++++---- libraries/networking/src/udt/Connection.h | 1 - libraries/networking/src/udt/SendQueue.cpp | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index fc590c3a66..2f57523f79 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -193,11 +193,16 @@ void Connection::queueReceivedMessagePacket(std::unique_ptr packet) { while (pendingMessage.hasAvailablePackets()) { auto packet = pendingMessage.removeNextPacket(); - _parentSocket->messageReceived(std::move(packet)); - } - if (pendingMessage.isComplete()) { - _pendingReceivedMessages.erase(messageNumber); + auto packetPosition = packet->getPacketPosition(); + + _parentSocket->messageReceived(std::move(packet)); + + // if this was the last or only packet, then we can remove the pending message from our hash + if (packetPosition == Packet::PacketPosition::LAST || + packetPosition == Packet::PacketPosition::ONLY) { + _pendingReceivedMessages.erase(messageNumber); + } } } diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index 4f979750f9..8a96b1ded3 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -37,7 +37,6 @@ class Socket; class PendingReceivedMessage { public: void enqueuePacket(std::unique_ptr packet); - bool isComplete() const { return _hasLastPacket && _numPackets == _packets.size(); } bool hasAvailablePackets() const; std::unique_ptr removeNextPacket(); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 43477e4562..e7d1ab104a 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -87,9 +87,9 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK) : + _packets(currentMessageNumber), _socket(socket), - _destination(dest), - _packets(currentMessageNumber) + _destination(dest) { // set our member variables from current sequence number _currentSequenceNumber = currentSequenceNumber; From 1d4801adf5edad026571b84dae96c3bce0a938b4 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 13:48:31 -0800 Subject: [PATCH 42/81] Fix for Haze crash (bug 10537) --- libraries/render-utils/src/DrawHaze.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 4431c1bbc3..da07f5bd9b 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -169,7 +169,12 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu auto hazeStage = args->_scene->getStage(); if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { model::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); - batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); + if (hazePointer) { + batch.setUniformBuffer(HazeEffect_ParamsSlot, hazePointer->getHazeParametersBuffer()); + } else { + // Something is wrong, so just quit Haze + return; + } } batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer()); @@ -178,7 +183,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu if (lightStage) { model::LightPointer keyLight; keyLight = lightStage->getCurrentKeyLight(); - if (keyLight != nullptr) { + if (keyLight) { batch.setUniformBuffer(HazeEffect_LightingMapSlot, keyLight->getLightSchemaBuffer()); } } From 8b5e8f8d0843ead1df30949ad2900390de938a00 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 14 Dec 2017 15:30:25 -0800 Subject: [PATCH 43/81] only de-activate the SendQueue when it has nothing to send --- libraries/networking/src/udt/SendQueue.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index e7d1ab104a..4a0500f642 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -538,28 +538,6 @@ bool SendQueue::maybeResendPacket() { bool SendQueue::isInactive(bool attemptedToSendPacket) { // check for connection timeout first - // that will be the case if we have had 16 timeouts since hearing back from the client, and it has been - // at least 5 seconds - static const int NUM_TIMEOUTS_BEFORE_INACTIVE = 16; - static const int MIN_MS_BEFORE_INACTIVE = 5 * 1000; - - auto sinceLastResponse = (QDateTime::currentMSecsSinceEpoch() - _lastReceiverResponse); - - if (sinceLastResponse > 0 && - sinceLastResponse >= int64_t(NUM_TIMEOUTS_BEFORE_INACTIVE * (_estimatedTimeout / USECS_PER_MSEC)) && - sinceLastResponse > MIN_MS_BEFORE_INACTIVE) { - // If the flow window has been full for over CONSIDER_INACTIVE_AFTER, - // then signal the queue is inactive and return so it can be cleaned up - -#ifdef UDT_CONNECTION_DEBUG - qCDebug(networking) << "SendQueue to" << _destination << "reached" << NUM_TIMEOUTS_BEFORE_INACTIVE << "timeouts" - << "and" << MIN_MS_BEFORE_INACTIVE << "milliseconds before receiving any ACK/NAK and is now inactive. Stopping."; -#endif - - deactivate(); - return true; - } - if (!attemptedToSendPacket) { // During our processing above we didn't send any packets From da56d4730747bfa5ff8073249694cb3f9adc0a16 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 14 Dec 2017 15:30:51 -0800 Subject: [PATCH 44/81] make the _lastMessageNumber in Connection default to 0 --- libraries/networking/src/udt/Connection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index 8a96b1ded3..0017eb204a 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -136,7 +136,7 @@ private: SequenceNumber _initialSequenceNumber; // Randomized on Connection creation, identifies connection during re-connect requests SequenceNumber _initialReceiveSequenceNumber; // Randomized by peer Connection on creation, identifies connection during re-connect requests - MessageNumber _lastMessageNumber; + MessageNumber _lastMessageNumber { 0 }; LossList _lossList; // List of all missing packets SequenceNumber _lastReceivedSequenceNumber; // The largest sequence number received from the peer From 00a2013b6064b71e14a90aa19148fb3c8818dff0 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 15:38:07 -0800 Subject: [PATCH 45/81] Added missing space before { --- libraries/model/src/model/Haze.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index 5c916c3b91..2a575eb151 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -128,7 +128,7 @@ namespace model { Parameters() {} }; - UniformBufferView _hazeParametersBuffer{ nullptr }; + UniformBufferView _hazeParametersBuffer { nullptr }; }; using HazePointer = std::shared_ptr; From d5d4c22a3d4aedd7de0d27bea1d6b71610352589 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 15:55:31 -0800 Subject: [PATCH 46/81] Removed dual calls to getViewInverse(). --- libraries/render-utils/src/Haze.slf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index d758756975..e394207d16 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -48,8 +48,10 @@ void main(void) { vec4 fragColor = texture(colorMap, varTexCoord0); vec4 eyeFragPos = unpackPositionFromZeye(varTexCoord0); - vec4 worldFragPos = getViewInverse() * eyeFragPos; - vec4 worldEyePos = getViewInverse()[3]; + + mat4 viewInverse = getViewInverse(); + vec4 worldFragPos = viewInverse * eyeFragPos; + vec4 worldEyePos = viewInverse[3]; outFragColor = computeHazeColor(fragColor, eyeFragPos, worldFragPos, worldEyePos); } From 05e47ae668254ea2437da0bb6ac2e93fb43048b0 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 16:14:08 -0800 Subject: [PATCH 47/81] Removed unneeded 'mix'. Defined EPSILON. --- libraries/render-utils/src/Haze.slh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index 97284f1c2a..ddc4e6e945 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -89,9 +89,7 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, Light directionalLight, vec // hazeIntegral *= (1.0 - exp (-t)) / t; hazeIntegral *= 0.3171178; - float hazeAmount = 1.0 - exp(-hazeIntegral); - - return mix(color, vec3(0.0, 0.0, 0.0), hazeAmount); + return color * exp(-hazeIntegral); } // Input: @@ -177,7 +175,8 @@ vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec4 w if (abs(deltaHeight) > slopeThreshold) { float t = hazeParams.hazeHeightFactor * deltaHeight; // Protect from wild values - if (abs(t) > 0.0000001) { + const float EPSILON = 0.0000001f; + if (abs(t) > EPSILON) { hazeIntegral *= (1.0 - exp (-t)) / t; } } @@ -189,7 +188,7 @@ vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec4 w } // Mix with background at far range - const float BLEND_DISTANCE = 27000.0; + const float BLEND_DISTANCE = 27000.0f; vec4 outFragColor; if (distance > BLEND_DISTANCE) { outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend); From 026b19d770f121bad061bd7375525626e7c69227 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 16:17:50 -0800 Subject: [PATCH 48/81] Set 4th position component from 0.0 to 1.0 --- libraries/render-utils/src/DeferredGlobalLight.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 311012716a..831f5732ab 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -224,7 +224,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( vec4 colorV4 = computeHazeColor( vec4(color, 0.0), // fragment original color vec4(position, 0.0), // fragment position in eye coordinates - vec4(fragEyeVector, 0.0), // fragment position in world coordinates + vec4(fragEyeVector, 1.0), // fragment position in world coordinates invViewMat[3]); // eye position in world coordinates color = colorV4.rgb; From c352d5fc23c52ee12eb5fb4875caf157a21c4ff0 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 16:23:14 -0800 Subject: [PATCH 49/81] Passed light direction instead of light object into `computeHazeColorKeyLightAttenuation`. --- libraries/render-utils/src/DeferredGlobalLight.slh | 6 +----- libraries/render-utils/src/Haze.slh | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 831f5732ab..9de7c7eb3a 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -121,10 +121,6 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += ambientDiffuse; color += ambientSpecular; - // Directional - // Get directional light (used by both directional light and haze attenuation) - Light directionalLight = getLight(); - vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation @@ -137,7 +133,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Attenuate the light if haze effect selected if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - color = computeHazeColorKeyLightAttenuation(color, directionalLight, position); + color = computeHazeColorKeyLightAttenuation(color, lightDirection, position); } return color; diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index ddc4e6e945..7e74b91ede 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -50,13 +50,12 @@ layout(std140) uniform hazeBuffer { // // General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission // -vec3 computeHazeColorKeyLightAttenuation(vec3 color, Light directionalLight, vec3 worldFragPos) { +vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 worldFragPos) { // Directional light attenuation is simulated by assuming the light source is at a fixed height above the // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height // // The distance is computed from the height and the directional light orientation // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees - vec3 lightDirection = getLightDirection(directionalLight); // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen) float height_95p = 2000.0; From a4696cc2b3ac311739b43266aa4f876b2b056e2d Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 8 Dec 2017 00:20:35 +0300 Subject: [PATCH 50/81] 8992 Login window is small in tablet --- interface/resources/qml/LoginDialog/LinkAccountBody.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 300bcd46f0..0e2f2a5282 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -52,7 +52,11 @@ Item { targetHeight += hifi.dimensions.contentSpacing.y + additionalInformation.height } - parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)); + var newWidth = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)); + if(!isNaN(newWidth)) { + parent.width = root.width = newWidth; + } + parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + (keyboardEnabled && keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : hifi.dimensions.contentSpacing.y); } From 82b94eaacd58d33157017f03c47d5a23198f8ff1 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 14 Dec 2017 18:50:41 -0800 Subject: [PATCH 51/81] Reduced size of parameters in (shader) function call. --- .../render-utils/src/DeferredGlobalLight.slh | 9 ++++---- libraries/render-utils/src/Haze.slf | 2 +- libraries/render-utils/src/Haze.slh | 22 +++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 9de7c7eb3a..6cdc02b7a5 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -218,10 +218,11 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( // Haze if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { vec4 colorV4 = computeHazeColor( - vec4(color, 0.0), // fragment original color - vec4(position, 0.0), // fragment position in eye coordinates - vec4(fragEyeVector, 1.0), // fragment position in world coordinates - invViewMat[3]); // eye position in world coordinates + vec4(color, 1.0), // fragment original color + position, // fragment position in eye coordinates + fragEyeVector, // fragment position in world coordinates + invViewMat[3].y // eye height in world coordinates + ); color = colorV4.rgb; } diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index e394207d16..5f05d52f83 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -53,6 +53,6 @@ void main(void) { vec4 worldFragPos = viewInverse * eyeFragPos; vec4 worldEyePos = viewInverse[3]; - outFragColor = computeHazeColor(fragColor, eyeFragPos, worldFragPos, worldEyePos); + outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y); } diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index 7e74b91ede..2fcf5f4418 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -92,24 +92,24 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 w } // Input: -// fragColor - fragment original color -// eyeFragPos - fragment position in eye coordinates -// worldFragPos - fragment position in world coordinates -// worldEyePos - eye position in world coordinates +// fragColor - fragment original color +// eyeFragPos - fragment position in eye coordinates +// worldFragPos - fragment position in world coordinates +// worldEyeHeight - eye height in world coordinates // Output: // fragment colour after haze effect // // General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission // -vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec4 worldEyePos) { +vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float worldEyeHeight) { // Distance to fragment - float distance = length(eyeFragPos.xyz); + float distance = length(eyeFragPos); // Convert haze colour from uniform into a vec4 vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0); // Directional light component is a function of the angle from the eye, between the fragment and the sun - vec3 eyeFragDir = normalize(worldFragPos.xyz); + vec3 eyeFragDir = normalize(worldFragPos); Light light = getLight(); vec3 lightDirection = getLightDirection(light); @@ -137,12 +137,12 @@ vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec4 w // Note that the haze base reference affects only the haze density as function of altitude vec3 hazeDensityDistribution = hazeParams.colorModulationFactor * - exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + exp(-hazeParams.hazeHeightFactor * (worldEyeHeight - hazeParams.hazeBaseReference)); vec3 hazeIntegral = hazeDensityDistribution * distance; const float slopeThreshold = 0.01; - float deltaHeight = worldFragPos.y - worldEyePos.y; + float deltaHeight = worldFragPos.y - worldEyeHeight; if (abs(deltaHeight) > slopeThreshold) { float t = hazeParams.hazeHeightFactor * deltaHeight; hazeIntegral *= (1.0 - exp (-t)) / t; @@ -165,12 +165,12 @@ vec4 computeHazeColor(vec4 fragColor, vec4 eyeFragPos, vec4 worldFragPos, vec4 w // Note that the haze base reference affects only the haze density as function of altitude float hazeDensityDistribution = hazeParams.hazeRangeFactor * - exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + exp(-hazeParams.hazeHeightFactor * (worldEyeHeight - hazeParams.hazeBaseReference)); float hazeIntegral = hazeDensityDistribution * distance; const float slopeThreshold = 0.01; - float deltaHeight = worldFragPos.y - worldEyePos.y; + float deltaHeight = worldFragPos.y - worldEyeHeight; if (abs(deltaHeight) > slopeThreshold) { float t = hazeParams.hazeHeightFactor * deltaHeight; // Protect from wild values From 52c4aef72125ed834c444e3a1868aab827621bdb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 15 Dec 2017 16:23:53 -0800 Subject: [PATCH 52/81] keep _cacheFile alive --- libraries/gpu/src/gpu/Texture.h | 5 ++--- libraries/gpu/src/gpu/Texture_ktx.cpp | 29 +++++---------------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 1877b494cf..26de5a0804 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -324,9 +324,8 @@ public: protected: std::shared_ptr maybeOpenFile() const; - mutable std::mutex _cacheFileCreateMutex; - mutable std::mutex _cacheFileWriteMutex; - mutable std::weak_ptr _cacheFile; + mutable std::mutex _cacheFileMutex; + mutable std::shared_ptr _cacheFile; std::string _filename; cache::FilePointer _cacheEntry; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 08fc4ec101..49e18aaf78 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -188,35 +188,17 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { } std::shared_ptr KtxStorage::maybeOpenFile() const { - // 1. Try to get the shared ptr - // 2. If it doesn't exist, grab the mutex around its creation - // 3. If it was created before we got the mutex, return it - // 4. Otherwise, create it - - std::shared_ptr file = _cacheFile.lock(); - if (file) { - return file; + if (!_cacheFile) { + _cacheFile = std::make_shared(_filename.c_str()); } - - { - std::lock_guard lock{ _cacheFileCreateMutex }; - - file = _cacheFile.lock(); - if (file) { - return file; - } - - file = std::make_shared(_filename.c_str()); - _cacheFile = file; - } - - return file; + return _cacheFile; } PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); if (faceSize != 0 && faceOffset != 0) { + std::lock_guard lock(_cacheFileMutex); auto file = maybeOpenFile(); if (file) { auto storageView = file->createView(faceSize, faceOffset); @@ -262,6 +244,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor return; } + std::lock_guard lock(_cacheFileMutex); auto file = maybeOpenFile(); if (!file) { qWarning() << "Failed to open file to assign mip data " << QString::fromStdString(_filename); @@ -279,8 +262,6 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor imageData += ktx::IMAGE_SIZE_WIDTH; { - std::lock_guard lock { _cacheFileWriteMutex }; - if (level != _minMipLevelAvailable - 1) { qWarning() << "Invalid level to be stored"; return; From 3477aa57a8980413a66d7cd2ed3c55f03eeadd9a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 15 Dec 2017 16:36:07 -0800 Subject: [PATCH 53/81] remove extra recycle --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 0993daaa8b..cb9d06dce1 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -685,11 +685,6 @@ void OpenGLDisplayPlugin::present() { } incrementPresentCount(); - { - PROFILE_RANGE_EX(render, "recycle", 0xff00ff00, frameId) - _gpuContext->recycle(); - } - if (_currentFrame) { { withPresentThreadLock([&] { From 3ae52c0e0ef2cc54b2c31c6e02ddb71e7a13b6c8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 15 Dec 2017 17:52:48 -0800 Subject: [PATCH 54/81] clear all _cacheFiles on recycle --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/Texture.h | 7 ++++++- libraries/gpu/src/gpu/Texture_ktx.cpp | 18 ++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 6fb0d7b152..fa336665a5 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -772,7 +772,7 @@ void GLBackend::recycle() const { GLVariableAllocationSupport::manageMemory(); GLVariableAllocationSupport::_frameTexturesCreated = 0; - + Texture::KtxStorage::clearKtxFiles(); } void GLBackend::setCameraCorrection(const Mat4& correction) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 26de5a0804..10edd895c0 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -321,10 +321,15 @@ public: void reset() override { } + // Don't keep files open forever. We close them at the beginning of each frame (GLBackend::recycle) + static std::vector, std::shared_ptr>> _cachedKtxFiles; + static std::mutex _cachedKtxFilesMutex; + static void clearKtxFiles(); + protected: std::shared_ptr maybeOpenFile() const; - mutable std::mutex _cacheFileMutex; + mutable std::shared_ptr _cacheFileMutex { std::make_shared() }; mutable std::shared_ptr _cacheFile; std::string _filename; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 49e18aaf78..46804b4b44 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -23,6 +23,9 @@ using namespace gpu; using PixelsPointer = Texture::PixelsPointer; using KtxStorage = Texture::KtxStorage; +std::vector, std::shared_ptr>> KtxStorage::_cachedKtxFiles; +std::mutex KtxStorage::_cachedKtxFilesMutex; + struct GPUKTXPayload { using Version = uint8; @@ -190,15 +193,26 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { std::shared_ptr KtxStorage::maybeOpenFile() const { if (!_cacheFile) { _cacheFile = std::make_shared(_filename.c_str()); + std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); + _cachedKtxFiles.emplace_back(_cacheFile, _cacheFileMutex); } return _cacheFile; } +void KtxStorage::clearKtxFiles() { + std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); + for (auto& cacheFileAndMutex : KtxStorage::_cachedKtxFiles) { + std::lock_guard lock(*(cacheFileAndMutex.second)); + cacheFileAndMutex.first.reset(); + } + _cachedKtxFiles.clear(); +} + PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); if (faceSize != 0 && faceOffset != 0) { - std::lock_guard lock(_cacheFileMutex); + std::lock_guard lock(*_cacheFileMutex); auto file = maybeOpenFile(); if (file) { auto storageView = file->createView(faceSize, faceOffset); @@ -244,7 +258,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor return; } - std::lock_guard lock(_cacheFileMutex); + std::lock_guard lock(*_cacheFileMutex); auto file = maybeOpenFile(); if (!file) { qWarning() << "Failed to open file to assign mip data " << QString::fromStdString(_filename); From d69297c02e9c9724cf093ad6cd1a5c09c933536f Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Sat, 16 Dec 2017 00:22:26 -0800 Subject: [PATCH 55/81] Replace `evalGlobalLightingAlphaBlended` with `evalGlobalLightingAlphaBlendedWithHaze` in all shaders. --- libraries/render-utils/src/forward_model_translucent.slf | 2 +- libraries/render-utils/src/model_translucent_fade.slf | 2 +- libraries/render-utils/src/overlay3D_model_translucent.slf | 2 +- libraries/render-utils/src/simple_transparent_textured.slf | 2 +- libraries/render-utils/src/simple_transparent_textured_fade.slf | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/forward_model_translucent.slf b/libraries/render-utils/src/forward_model_translucent.slf index 52e8ce50e7..906393db1f 100644 --- a/libraries/render-utils/src/forward_model_translucent.slf +++ b/libraries/render-utils/src/forward_model_translucent.slf @@ -66,7 +66,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); - _fragColor = vec4(evalGlobalLightingAlphaBlended( + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index c46b396ebc..9d5477304c 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -76,7 +76,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); - _fragColor = vec4(evalGlobalLightingAlphaBlended( + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf index 748eea329c..b26e70f465 100644 --- a/libraries/render-utils/src/overlay3D_model_translucent.slf +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -65,7 +65,7 @@ void main(void) { vec3 fragNormal; <$transformEyeToWorldDir(cam, _normal, fragNormal)$> - vec4 color = vec4(evalGlobalLightingAlphaBlended( + vec4 color = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index b9eb921e9d..b16b19c8b4 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -45,7 +45,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); - _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, 1.0, diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 20c7907bbe..ad260210a7 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -57,7 +57,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); - _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, 1.0, From 6990dda48d9d4504f732871968a44da3ff9cd5df Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Sun, 17 Dec 2017 15:56:34 -0800 Subject: [PATCH 56/81] cr and cleanup --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/Texture.h | 7 ++++--- libraries/gpu/src/gpu/Texture_ktx.cpp | 13 ++++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index fa336665a5..f93d430152 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -772,7 +772,7 @@ void GLBackend::recycle() const { GLVariableAllocationSupport::manageMemory(); GLVariableAllocationSupport::_frameTexturesCreated = 0; - Texture::KtxStorage::clearKtxFiles(); + Texture::KtxStorage::releaseOpenKtxFiles(); } void GLBackend::setCameraCorrection(const Mat4& correction) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 10edd895c0..7c087fec2b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -322,9 +322,7 @@ public: void reset() override { } // Don't keep files open forever. We close them at the beginning of each frame (GLBackend::recycle) - static std::vector, std::shared_ptr>> _cachedKtxFiles; - static std::mutex _cachedKtxFilesMutex; - static void clearKtxFiles(); + static void releaseOpenKtxFiles(); protected: std::shared_ptr maybeOpenFile() const; @@ -332,6 +330,9 @@ public: mutable std::shared_ptr _cacheFileMutex { std::make_shared() }; mutable std::shared_ptr _cacheFile; + static std::vector, std::shared_ptr>> _cachedKtxFiles; + static std::mutex _cachedKtxFilesMutex; + std::string _filename; cache::FilePointer _cacheEntry; std::atomic _minMipLevelAvailable; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 46804b4b44..8b054816bb 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -193,19 +193,22 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { std::shared_ptr KtxStorage::maybeOpenFile() const { if (!_cacheFile) { _cacheFile = std::make_shared(_filename.c_str()); - std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); + std::lock_guard lock(_cachedKtxFilesMutex); _cachedKtxFiles.emplace_back(_cacheFile, _cacheFileMutex); } return _cacheFile; } -void KtxStorage::clearKtxFiles() { - std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); - for (auto& cacheFileAndMutex : KtxStorage::_cachedKtxFiles) { +void KtxStorage::releaseOpenKtxFiles() { + std::vector, std::shared_ptr>> localKtxFiles; + { + std::lock_guard lock(_cachedKtxFilesMutex); + localKtxFiles.swap(_cachedKtxFiles); + } + for (auto& cacheFileAndMutex : localKtxFiles) { std::lock_guard lock(*(cacheFileAndMutex.second)); cacheFileAndMutex.first.reset(); } - _cachedKtxFiles.clear(); } PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { From 6814dfcbfc5eee145e6201ebb86de729842952bf Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Sun, 17 Dec 2017 22:09:20 -0800 Subject: [PATCH 57/81] weak_ptr _cacheFile --- libraries/gpu/src/gpu/Texture.h | 2 +- libraries/gpu/src/gpu/Texture_ktx.cpp | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 7c087fec2b..06208179e0 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -328,7 +328,7 @@ public: std::shared_ptr maybeOpenFile() const; mutable std::shared_ptr _cacheFileMutex { std::make_shared() }; - mutable std::shared_ptr _cacheFile; + mutable std::weak_ptr _cacheFile; static std::vector, std::shared_ptr>> _cachedKtxFiles; static std::mutex _cachedKtxFilesMutex; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 8b054816bb..883d9abf15 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -190,13 +190,25 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { } } +// maybeOpenFile should be called with _cacheFileMutex already held to avoid modifying the file from multiple threads std::shared_ptr KtxStorage::maybeOpenFile() const { - if (!_cacheFile) { - _cacheFile = std::make_shared(_filename.c_str()); - std::lock_guard lock(_cachedKtxFilesMutex); - _cachedKtxFiles.emplace_back(_cacheFile, _cacheFileMutex); + // Try to get the shared_ptr + std::shared_ptr file = _cacheFile.lock(); + if (file) { + return file; } - return _cacheFile; + + // If the file isn't open, create it and save a weak_ptr to it + file = std::make_shared(_filename.c_str()); + _cacheFile = file; + + { + // Add the shared_ptr to the global list of open KTX files, to be released at the beginning of the next present thread frame + std::lock_guard lock(_cachedKtxFilesMutex); + _cachedKtxFiles.emplace_back(file, _cacheFileMutex); + } + + return file; } void KtxStorage::releaseOpenKtxFiles() { From 355ceddcc6a0b839bb20a515fc329d6939b98e68 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 15 Dec 2017 16:23:53 -0800 Subject: [PATCH 58/81] keep _cacheFile alive --- libraries/gpu/src/gpu/Texture.h | 5 ++--- libraries/gpu/src/gpu/Texture_ktx.cpp | 29 +++++---------------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 1877b494cf..26de5a0804 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -324,9 +324,8 @@ public: protected: std::shared_ptr maybeOpenFile() const; - mutable std::mutex _cacheFileCreateMutex; - mutable std::mutex _cacheFileWriteMutex; - mutable std::weak_ptr _cacheFile; + mutable std::mutex _cacheFileMutex; + mutable std::shared_ptr _cacheFile; std::string _filename; cache::FilePointer _cacheEntry; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 08fc4ec101..49e18aaf78 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -188,35 +188,17 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { } std::shared_ptr KtxStorage::maybeOpenFile() const { - // 1. Try to get the shared ptr - // 2. If it doesn't exist, grab the mutex around its creation - // 3. If it was created before we got the mutex, return it - // 4. Otherwise, create it - - std::shared_ptr file = _cacheFile.lock(); - if (file) { - return file; + if (!_cacheFile) { + _cacheFile = std::make_shared(_filename.c_str()); } - - { - std::lock_guard lock{ _cacheFileCreateMutex }; - - file = _cacheFile.lock(); - if (file) { - return file; - } - - file = std::make_shared(_filename.c_str()); - _cacheFile = file; - } - - return file; + return _cacheFile; } PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); if (faceSize != 0 && faceOffset != 0) { + std::lock_guard lock(_cacheFileMutex); auto file = maybeOpenFile(); if (file) { auto storageView = file->createView(faceSize, faceOffset); @@ -262,6 +244,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor return; } + std::lock_guard lock(_cacheFileMutex); auto file = maybeOpenFile(); if (!file) { qWarning() << "Failed to open file to assign mip data " << QString::fromStdString(_filename); @@ -279,8 +262,6 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor imageData += ktx::IMAGE_SIZE_WIDTH; { - std::lock_guard lock { _cacheFileWriteMutex }; - if (level != _minMipLevelAvailable - 1) { qWarning() << "Invalid level to be stored"; return; From 90b97aba59214e9d5b5a70dd94141f95c0fb82ed Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 15 Dec 2017 16:36:07 -0800 Subject: [PATCH 59/81] remove extra recycle --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 0993daaa8b..cb9d06dce1 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -685,11 +685,6 @@ void OpenGLDisplayPlugin::present() { } incrementPresentCount(); - { - PROFILE_RANGE_EX(render, "recycle", 0xff00ff00, frameId) - _gpuContext->recycle(); - } - if (_currentFrame) { { withPresentThreadLock([&] { From 9bdcf34c9162cb3651d6eabbb32903fdec0cfa15 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 15 Dec 2017 17:52:48 -0800 Subject: [PATCH 60/81] clear all _cacheFiles on recycle --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/Texture.h | 7 ++++++- libraries/gpu/src/gpu/Texture_ktx.cpp | 18 ++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index f138244fa2..0a71ee513a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -776,7 +776,7 @@ void GLBackend::recycle() const { GLVariableAllocationSupport::manageMemory(); GLVariableAllocationSupport::_frameTexturesCreated = 0; - + Texture::KtxStorage::clearKtxFiles(); } void GLBackend::setCameraCorrection(const Mat4& correction) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 26de5a0804..10edd895c0 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -321,10 +321,15 @@ public: void reset() override { } + // Don't keep files open forever. We close them at the beginning of each frame (GLBackend::recycle) + static std::vector, std::shared_ptr>> _cachedKtxFiles; + static std::mutex _cachedKtxFilesMutex; + static void clearKtxFiles(); + protected: std::shared_ptr maybeOpenFile() const; - mutable std::mutex _cacheFileMutex; + mutable std::shared_ptr _cacheFileMutex { std::make_shared() }; mutable std::shared_ptr _cacheFile; std::string _filename; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 49e18aaf78..46804b4b44 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -23,6 +23,9 @@ using namespace gpu; using PixelsPointer = Texture::PixelsPointer; using KtxStorage = Texture::KtxStorage; +std::vector, std::shared_ptr>> KtxStorage::_cachedKtxFiles; +std::mutex KtxStorage::_cachedKtxFilesMutex; + struct GPUKTXPayload { using Version = uint8; @@ -190,15 +193,26 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { std::shared_ptr KtxStorage::maybeOpenFile() const { if (!_cacheFile) { _cacheFile = std::make_shared(_filename.c_str()); + std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); + _cachedKtxFiles.emplace_back(_cacheFile, _cacheFileMutex); } return _cacheFile; } +void KtxStorage::clearKtxFiles() { + std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); + for (auto& cacheFileAndMutex : KtxStorage::_cachedKtxFiles) { + std::lock_guard lock(*(cacheFileAndMutex.second)); + cacheFileAndMutex.first.reset(); + } + _cachedKtxFiles.clear(); +} + PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); if (faceSize != 0 && faceOffset != 0) { - std::lock_guard lock(_cacheFileMutex); + std::lock_guard lock(*_cacheFileMutex); auto file = maybeOpenFile(); if (file) { auto storageView = file->createView(faceSize, faceOffset); @@ -244,7 +258,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor return; } - std::lock_guard lock(_cacheFileMutex); + std::lock_guard lock(*_cacheFileMutex); auto file = maybeOpenFile(); if (!file) { qWarning() << "Failed to open file to assign mip data " << QString::fromStdString(_filename); From a39eea5a34812497203d42be1b885c504356cdce Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Sun, 17 Dec 2017 15:56:34 -0800 Subject: [PATCH 61/81] cr and cleanup --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/Texture.h | 7 ++++--- libraries/gpu/src/gpu/Texture_ktx.cpp | 13 ++++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 0a71ee513a..a36a6e0fb5 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -776,7 +776,7 @@ void GLBackend::recycle() const { GLVariableAllocationSupport::manageMemory(); GLVariableAllocationSupport::_frameTexturesCreated = 0; - Texture::KtxStorage::clearKtxFiles(); + Texture::KtxStorage::releaseOpenKtxFiles(); } void GLBackend::setCameraCorrection(const Mat4& correction) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 10edd895c0..7c087fec2b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -322,9 +322,7 @@ public: void reset() override { } // Don't keep files open forever. We close them at the beginning of each frame (GLBackend::recycle) - static std::vector, std::shared_ptr>> _cachedKtxFiles; - static std::mutex _cachedKtxFilesMutex; - static void clearKtxFiles(); + static void releaseOpenKtxFiles(); protected: std::shared_ptr maybeOpenFile() const; @@ -332,6 +330,9 @@ public: mutable std::shared_ptr _cacheFileMutex { std::make_shared() }; mutable std::shared_ptr _cacheFile; + static std::vector, std::shared_ptr>> _cachedKtxFiles; + static std::mutex _cachedKtxFilesMutex; + std::string _filename; cache::FilePointer _cacheEntry; std::atomic _minMipLevelAvailable; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 46804b4b44..8b054816bb 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -193,19 +193,22 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { std::shared_ptr KtxStorage::maybeOpenFile() const { if (!_cacheFile) { _cacheFile = std::make_shared(_filename.c_str()); - std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); + std::lock_guard lock(_cachedKtxFilesMutex); _cachedKtxFiles.emplace_back(_cacheFile, _cacheFileMutex); } return _cacheFile; } -void KtxStorage::clearKtxFiles() { - std::lock_guard lock(KtxStorage::_cachedKtxFilesMutex); - for (auto& cacheFileAndMutex : KtxStorage::_cachedKtxFiles) { +void KtxStorage::releaseOpenKtxFiles() { + std::vector, std::shared_ptr>> localKtxFiles; + { + std::lock_guard lock(_cachedKtxFilesMutex); + localKtxFiles.swap(_cachedKtxFiles); + } + for (auto& cacheFileAndMutex : localKtxFiles) { std::lock_guard lock(*(cacheFileAndMutex.second)); cacheFileAndMutex.first.reset(); } - _cachedKtxFiles.clear(); } PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { From c39da5094ba883d3c5edcce1c1adb6207f66477e Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Sun, 17 Dec 2017 22:09:20 -0800 Subject: [PATCH 62/81] weak_ptr _cacheFile --- libraries/gpu/src/gpu/Texture.h | 2 +- libraries/gpu/src/gpu/Texture_ktx.cpp | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 7c087fec2b..06208179e0 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -328,7 +328,7 @@ public: std::shared_ptr maybeOpenFile() const; mutable std::shared_ptr _cacheFileMutex { std::make_shared() }; - mutable std::shared_ptr _cacheFile; + mutable std::weak_ptr _cacheFile; static std::vector, std::shared_ptr>> _cachedKtxFiles; static std::mutex _cachedKtxFilesMutex; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 8b054816bb..883d9abf15 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -190,13 +190,25 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { } } +// maybeOpenFile should be called with _cacheFileMutex already held to avoid modifying the file from multiple threads std::shared_ptr KtxStorage::maybeOpenFile() const { - if (!_cacheFile) { - _cacheFile = std::make_shared(_filename.c_str()); - std::lock_guard lock(_cachedKtxFilesMutex); - _cachedKtxFiles.emplace_back(_cacheFile, _cacheFileMutex); + // Try to get the shared_ptr + std::shared_ptr file = _cacheFile.lock(); + if (file) { + return file; } - return _cacheFile; + + // If the file isn't open, create it and save a weak_ptr to it + file = std::make_shared(_filename.c_str()); + _cacheFile = file; + + { + // Add the shared_ptr to the global list of open KTX files, to be released at the beginning of the next present thread frame + std::lock_guard lock(_cachedKtxFilesMutex); + _cachedKtxFiles.emplace_back(file, _cacheFileMutex); + } + + return file; } void KtxStorage::releaseOpenKtxFiles() { From b0ecaa10d4511a70ed6a80e2a659df46d84fc604 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 18 Dec 2017 12:38:25 -0800 Subject: [PATCH 63/81] fix equirectangular skybox loading --- libraries/image/src/image/Image.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 9e4ab2e43f..f78ed1a583 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -981,7 +981,7 @@ public: static QImage extractEquirectangularFace(const QImage& source, gpu::Texture::CubeFace face, int faceWidth) { QImage image(faceWidth, faceWidth, source.format()); - glm::vec2 dstInvSize(1.0f / (float)source.width(), 1.0f / (float)source.height()); + glm::vec2 dstInvSize(1.0f / faceWidth); struct CubeToXYZ { gpu::Texture::CubeFace _face; From 2fcf11455bfefa3107a533d9622610fa143bd887 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 18 Dec 2017 14:03:13 -0800 Subject: [PATCH 64/81] Fixing edit state detection --- scripts/system/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1d9398fda8..e28f877d85 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -427,7 +427,7 @@ var toolBar = (function () { }); createButton = activeButton; tablet.screenChanged.connect(function (type, url) { - if (isActive && (type !== "QML" || url !== "Edit.qml")) { + if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml")) { that.setActive(false) } }); From 63ac426bf27c9782c0406224275862790aed1c3f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 18 Dec 2017 17:30:56 -0800 Subject: [PATCH 65/81] fix logic that resets own-avatar collisions after a parenting grab is released --- libraries/entities/src/EntityItem.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 48370b02fd..ddc5e9795f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1626,6 +1626,10 @@ void EntityItem::setParentID(const QUuid& value) { newParentNoBootstrapping |= Simulation::NO_BOOTSTRAPPING; } + if (!oldParentID.isNull() && (oldParentID == Physics::getSessionUUID() || oldParentID == AVATAR_SELF_ID)) { + oldParentNoBootstrapping |= Simulation::NO_BOOTSTRAPPING; + } + if ((bool)(oldParentNoBootstrapping ^ newParentNoBootstrapping)) { if ((bool)(newParentNoBootstrapping & Simulation::NO_BOOTSTRAPPING)) { markDirtyFlags(Simulation::NO_BOOTSTRAPPING); From 661a63bd0ca5d2935c88c32066c538989fda240d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 18 Dec 2017 11:05:27 -0800 Subject: [PATCH 66/81] fix crash for bad QVector index --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e578e4858d..cf555203dc 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -998,7 +998,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { // in the case where the last frame is greater than the framecount then clamp // it to the end of the animation until it loops around. - if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { + if (animationCurrentFrame < 0 || animationCurrentFrame >= frameCount) { animationCurrentFrame = 0; } From 559cb33563b794ce84f39232a164bbc04307fd31 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 18 Dec 2017 11:13:11 -0800 Subject: [PATCH 67/81] remove incorrect comment --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index cf555203dc..543c3bfbe9 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -993,11 +993,8 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { } { - // the current frame is set on the server in update() in ModelEntityItem.cpp + // the current frame is set on the server in update() in ModelEntityItem.cpp int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); - - // in the case where the last frame is greater than the framecount then clamp - // it to the end of the animation until it loops around. if (animationCurrentFrame < 0 || animationCurrentFrame >= frameCount) { animationCurrentFrame = 0; } From bad2c1df7693f9794a6f935483a0c64529d9bfc8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 18 Dec 2017 12:21:23 -0800 Subject: [PATCH 68/81] proper modulus of animation frame --- .../src/RenderableModelEntityItem.cpp | 13 ++++++------- libraries/entities/src/ModelEntityItem.cpp | 6 ++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 543c3bfbe9..bc99522d0f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -993,16 +993,15 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { } { - // the current frame is set on the server in update() in ModelEntityItem.cpp - int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); - if (animationCurrentFrame < 0 || animationCurrentFrame >= frameCount) { - animationCurrentFrame = 0; + float currentFrame = fmod(entity->getAnimationCurrentFrame(), (float)(frameCount)); + if (currentFrame < 0.0f) { + currentFrame += (float)frameCount; } - - if (animationCurrentFrame == _lastKnownCurrentFrame) { + int currentIntegerFrame = (int)(glm::floor(currentFrame)); + if (currentIntegerFrame == _lastKnownCurrentFrame) { return; } - _lastKnownCurrentFrame = animationCurrentFrame; + _lastKnownCurrentFrame = currentIntegerFrame; } if (_jointMapping.size() != _model->getJointStateCount()) { diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 323584c7ee..3a79df34c6 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -245,7 +245,7 @@ void ModelEntityItem::updateFrameCount() { if (_currentFrame < 0.0f) { return; } - + if (!_lastAnimated) { _lastAnimated = usecTimestampNow(); return; @@ -263,7 +263,7 @@ void ModelEntityItem::updateFrameCount() { } int updatedFrameCount = getAnimationLastFrame() - getAnimationFirstFrame() + 1; - + if (!getAnimationHold() && getAnimationIsPlaying()) { float deltaTime = (float)interval / (float)USECS_PER_SECOND; _currentFrame += (deltaTime * getAnimationFPS()); @@ -283,8 +283,6 @@ void ModelEntityItem::updateFrameCount() { // qCDebug(entities) << "in update frame " << _currentFrame; setAnimationCurrentFrame(_currentFrame); } - - } void ModelEntityItem::debugDump() const { From 2c6868b03ead25a00986fa6b9c94734d23d8a6c7 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 19 Dec 2017 11:12:27 -0800 Subject: [PATCH 69/81] Pass keylight direction as parameter to the shader. --- libraries/render-utils/src/DeferredGlobalLight.slh | 3 ++- libraries/render-utils/src/Haze.slf | 6 ++++-- libraries/render-utils/src/Haze.slh | 7 ++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 6cdc02b7a5..de2d41be6b 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -221,7 +221,8 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( vec4(color, 1.0), // fragment original color position, // fragment position in eye coordinates fragEyeVector, // fragment position in world coordinates - invViewMat[3].y // eye height in world coordinates + invViewMat[3].y, // eye height in world coordinates + lightDirection // keylight direction vector ); color = colorV4.rgb; diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 5f05d52f83..0270aa58f0 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -53,6 +53,8 @@ void main(void) { vec4 worldFragPos = viewInverse * eyeFragPos; vec4 worldEyePos = viewInverse[3]; - outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y); -} + Light light = getLight(); + vec3 lightDirection = getLightDirection(light); + outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y, lightDirection); +} diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index 2fcf5f4418..15e484e055 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -43,7 +43,7 @@ layout(std140) uniform hazeBuffer { // Input: // color - fragment original color -// directionalLight - parameters of the keylight +// lightDirection - parameters of the keylight // worldFragPos - fragment position in world coordinates // Output: // fragment colour after haze effect @@ -101,7 +101,7 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 w // // General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission // -vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float worldEyeHeight) { +vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float worldEyeHeight, vec3 lightDirection) { // Distance to fragment float distance = length(eyeFragPos); @@ -111,9 +111,6 @@ vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float // Directional light component is a function of the angle from the eye, between the fragment and the sun vec3 eyeFragDir = normalize(worldFragPos); - Light light = getLight(); - vec3 lightDirection = getLightDirection(light); - float glareComponent = max(0.0, dot(eyeFragDir, -lightDirection)); float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend)); From ed5da4f83b59797ed81b0706a8616a6aa38ac9f3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 19 Dec 2017 15:07:50 -0800 Subject: [PATCH 70/81] Fix bug preventing 'get' buttons from working in marketplace --- scripts/system/html/js/marketplacesInject.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 96c1916889..63d36f1a72 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -415,7 +415,7 @@ } purchaseButton.on('click', function () { - if ('availabile' === availability) { + if ('available' === availability) { buyButtonClicked(window.location.pathname.split("/")[3], $('#top-center').find('h1').text(), $('#creator').find('.value').text(), From 5da49d156ebdeaac49de2e6e753d06894ea4f295 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 19 Dec 2017 16:26:58 -0800 Subject: [PATCH 71/81] Commerce: Fix the behavior of the 'cancel' button in Wallet Setup --- .../qml/hifi/commerce/checkout/Checkout.qml | 4 +++- .../qml/hifi/commerce/wallet/WalletSetup.qml | 2 +- scripts/system/commerce/wallet.js | 16 +++++++++++++++- scripts/system/html/js/marketplacesInject.js | 11 +++++++---- scripts/system/marketplaces/marketplaces.js | 2 +- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index c9e5d2aaec..79332d08fa 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -41,6 +41,7 @@ Rectangle { property bool debugCheckoutSuccess: false; property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); property bool isWearable; + property string referrer; // Style color: hifi.colors.white; Hifi.QmlCommerce { @@ -131,7 +132,7 @@ Rectangle { id: notSetUpTimer; interval: 200; onTriggered: { - sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId}); + sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId, referrer: referrer}); } } @@ -877,6 +878,7 @@ Rectangle { itemName = message.params.itemName; root.itemPrice = message.params.itemPrice; itemHref = message.params.itemHref; + referrer = message.params.referrer; setBuyText(); break; default: diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml index 1f9b56ca22..5d05b8fba3 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml @@ -252,7 +252,7 @@ Item { height: 50; text: "Cancel"; onClicked: { - sendSignalToWallet({method: 'walletSetup_cancelClicked'}); + sendSignalToWallet({method: 'walletSetup_cancelClicked', referrer: root.referrer ? root.referrer : "" }); } } } diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index a4cdc5b097..a37f2bfe91 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -61,10 +61,24 @@ function fromQml(message) { switch (message.method) { case 'passphrasePopup_cancelClicked': - case 'walletSetup_cancelClicked': case 'needsLogIn_cancelClicked': tablet.gotoHomeScreen(); break; + case 'walletSetup_cancelClicked': + switch (message.referrer) { + case '': // User clicked "Wallet" app + tablet.gotoHomeScreen(); + break; + case 'purchases': + case 'marketplace cta': + case 'mainPage': + tablet.gotoWebScreen(MARKETPLACE_URL, MARKETPLACES_INJECT_SCRIPT_URL); + break; + default: // User needs to return to an individual marketplace item URL + tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.referrer, MARKETPLACES_INJECT_SCRIPT_URL); + break; + } + break; case 'needsLogIn_loginClicked': openLoginWindow(); break; diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 63d36f1a72..698dd93f29 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -243,13 +243,14 @@ }); } - function buyButtonClicked(id, name, author, price, href) { + function buyButtonClicked(id, name, author, price, href, referrer) { EventBridge.emitWebEvent(JSON.stringify({ type: "CHECKOUT", itemId: id, itemName: name, itemPrice: price ? parseInt(price, 10) : 0, - itemHref: href + itemHref: href, + referrer: referrer })); } @@ -316,7 +317,8 @@ $(this).closest('.grid-item').find('.item-title').text(), $(this).closest('.grid-item').find('.creator').find('.value').text(), $(this).closest('.grid-item').find('.item-cost').text(), - $(this).attr('data-href')); + $(this).attr('data-href'), + "mainPage"); }); } @@ -420,7 +422,8 @@ $('#top-center').find('h1').text(), $('#creator').find('.value').text(), cost, - href); + href, + "itemPage"); } }); maybeAddPurchasesButton(); diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 004375bff7..a365730cd5 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -437,7 +437,7 @@ var selectionDisplay = null; // for gridTool.js to ignore wireEventBridge(true); tablet.sendToQml({ method: 'updateWalletReferrer', - referrer: message.itemId + referrer: message.referrer === "itemPage" ? message.itemId : message.referrer }); openWallet(); break; From a72ed27a25c5faf8034a7aa73544e5b877e75c47 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 19 Dec 2017 16:57:48 -0800 Subject: [PATCH 72/81] CR feedback --- interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml | 2 +- scripts/system/commerce/wallet.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml index 5d05b8fba3..36f29b3f31 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml @@ -252,7 +252,7 @@ Item { height: 50; text: "Cancel"; onClicked: { - sendSignalToWallet({method: 'walletSetup_cancelClicked', referrer: root.referrer ? root.referrer : "" }); + sendSignalToWallet({method: 'walletSetup_cancelClicked', referrer: root.referrer }); } } } diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index a37f2bfe91..4ad043f71e 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -67,6 +67,8 @@ case 'walletSetup_cancelClicked': switch (message.referrer) { case '': // User clicked "Wallet" app + case undefined: + case null: tablet.gotoHomeScreen(); break; case 'purchases': From e02e6790fea7397befa2da9d624830904ab55a4b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 20 Dec 2017 13:46:02 -0800 Subject: [PATCH 73/81] Fix error state for Commerce passphrase TextInputs --- .../resources/qml/hifi/commerce/wallet/PassphraseModal.qml | 3 +++ .../resources/qml/hifi/commerce/wallet/PassphraseSelection.qml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index 379a217adb..87430246f3 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -50,9 +50,11 @@ Item { submitPassphraseInputButton.enabled = true; if (!isAuthenticated) { errorText.text = "Authentication failed - please try again."; + passphraseField.error = true; UserActivityLogger.commercePassphraseAuthenticationStatus("auth failure"); } else { sendSignalToParent({method: 'authSuccess'}); + passphraseField.error = false; UserActivityLogger.commercePassphraseAuthenticationStatus("auth success"); } } @@ -72,6 +74,7 @@ Item { // TODO: Fix this unlikely bug onVisibleChanged: { if (visible) { + passphraseField.error = false; passphraseField.focus = true; sendSignalToParent({method: 'disableHmdPreview'}); } else { diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml index 3ed66f703b..50e58f8cc4 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml @@ -54,6 +54,9 @@ Item { // TODO: Fix this unlikely bug onVisibleChanged: { if (visible) { + passphraseField.error = false; + passphraseFieldAgain.error = false; + currentPassphraseField.error = false; if (root.shouldImmediatelyFocus) { focusFirstTextField(); } From 7a9d566e023dd4b7080bfc1f8d4758ef281fe56d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 18 Dec 2017 13:56:20 -0800 Subject: [PATCH 74/81] remove unnecessary whitespace --- interface/src/LODManager.cpp | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 01ccbd0d9a..7b99c89cee 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -64,11 +64,11 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta // translate into fps for legacy implementation float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; - + _fpsAverageStartWindow.updateAverage(currentFPS); _fpsAverageDownWindow.updateAverage(currentFPS); _fpsAverageUpWindow.updateAverage(currentFPS); - + quint64 now = usecTimestampNow(); quint64 elapsedSinceDownShift = now - _lastDownShift; @@ -76,22 +76,22 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta quint64 lastStableOrUpshift = glm::max(_lastUpShift, _lastStable); quint64 elapsedSinceStableOrUpShift = now - lastStableOrUpshift; - + if (_automaticLODAdjust) { bool changed = false; - - // LOD Downward adjustment + + // LOD Downward adjustment // If we've been downshifting, we watch a shorter downshift window so that we will quickly move toward our // target frame rate. But if we haven't just done a downshift (either because our last shift was an upshift, // or because we've just started out) then we look at a much longer window to consider whether or not to start // downshifting. - bool doDownShift = false; + bool doDownShift = false; if (_isDownshifting) { // only consider things if our DOWN_SHIFT time has elapsed... if (elapsedSinceDownShift > DOWN_SHIFT_ELPASED) { doDownShift = _fpsAverageDownWindow.getAverage() < getLODDecreaseFPS(); - + if (!doDownShift) { qCDebug(interfaceapp) << "---- WE APPEAR TO BE DONE DOWN SHIFTING -----"; _isDownshifting = false; @@ -99,10 +99,10 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta } } } else { - doDownShift = (elapsedSinceStableOrUpShift > START_SHIFT_ELPASED + doDownShift = (elapsedSinceStableOrUpShift > START_SHIFT_ELPASED && _fpsAverageStartWindow.getAverage() < getLODDecreaseFPS()); } - + if (doDownShift) { // Octree items... stepwise adjustment @@ -118,17 +118,17 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta if (_isDownshifting) { // subsequent downshift qCDebug(interfaceapp) << "adjusting LOD DOWN..." - << "average fps for last "<< DOWN_SHIFT_WINDOW_IN_SECS <<"seconds was " - << _fpsAverageDownWindow.getAverage() - << "minimum is:" << getLODDecreaseFPS() + << "average fps for last "<< DOWN_SHIFT_WINDOW_IN_SECS <<"seconds was " + << _fpsAverageDownWindow.getAverage() + << "minimum is:" << getLODDecreaseFPS() << "elapsedSinceDownShift:" << elapsedSinceDownShift << " NEW _octreeSizeScale=" << _octreeSizeScale; } else { // first downshift qCDebug(interfaceapp) << "adjusting LOD DOWN after initial delay..." - << "average fps for last "<< START_DELAY_WINDOW_IN_SECS <<"seconds was " - << _fpsAverageStartWindow.getAverage() - << "minimum is:" << getLODDecreaseFPS() + << "average fps for last "<< START_DELAY_WINDOW_IN_SECS <<"seconds was " + << _fpsAverageStartWindow.getAverage() + << "minimum is:" << getLODDecreaseFPS() << "elapsedSinceUpShift:" << elapsedSinceUpShift << " NEW _octreeSizeScale=" << _octreeSizeScale; } @@ -139,10 +139,10 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta emit LODDecreased(); } } else { - + // LOD Upward adjustment if (elapsedSinceUpShift > UP_SHIFT_ELPASED) { - + if (_fpsAverageUpWindow.getAverage() > getLODIncreaseFPS()) { // Octee items... stepwise adjustment @@ -158,11 +158,11 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta changed = true; } } - + if (changed) { - qCDebug(interfaceapp) << "adjusting LOD UP... average fps for last "<< UP_SHIFT_WINDOW_IN_SECS <<"seconds was " + qCDebug(interfaceapp) << "adjusting LOD UP... average fps for last "<< UP_SHIFT_WINDOW_IN_SECS <<"seconds was " << _fpsAverageUpWindow.getAverage() - << "upshift point is:" << getLODIncreaseFPS() + << "upshift point is:" << getLODIncreaseFPS() << "elapsedSinceUpShift:" << elapsedSinceUpShift << " NEW _octreeSizeScale=" << _octreeSizeScale; @@ -173,7 +173,7 @@ void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float delta } } } - + if (changed) { auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); if (lodToolsDialog) { From 5c84c5f84572e1882b6cc42f552b924a3a6d2e02 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Dec 2017 13:03:36 -0800 Subject: [PATCH 75/81] measure average time of 'present' --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 2 ++ libraries/plugins/src/plugins/DisplayPlugin.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index cb9d06dce1..e646ba27f5 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -679,6 +679,7 @@ void OpenGLDisplayPlugin::internalPresent() { void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) + uint64_t startPresent = usecTimestampNow(); { PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId) updateFrameData(); @@ -713,6 +714,7 @@ void OpenGLDisplayPlugin::present() { gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory()); } + _movingAveragePresent.addSample((float)(usecTimestampNow() - startPresent)); } float OpenGLDisplayPlugin::newFramePresentRate() const { diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index efce158864..2c717f629c 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -21,8 +21,10 @@ #include #include +#include #include #include +#include #include #include "Plugin.h" @@ -203,6 +205,7 @@ public: virtual void cycleDebugOutput() {} void waitForPresent(); + float getAveragePresentTime() { return _movingAveragePresent.average / (float)USECS_PER_MSEC; } // in msec std::function getHUDOperator(); @@ -220,6 +223,8 @@ protected: std::function _hudOperator { std::function() }; + MovingAverage _movingAveragePresent; + private: QMutex _presentMutex; QWaitCondition _presentCondition; From 8e0d367a2d7fa0a8a6636dfd82153794c7aa96ea Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Dec 2017 13:13:13 -0800 Subject: [PATCH 76/81] use full 'present' time for FPS calculation also, refactor LOD adjust logic --- interface/src/Application.cpp | 4 +- interface/src/LODManager.cpp | 189 ++++++++++------------------------ interface/src/LODManager.h | 42 ++------ 3 files changed, 68 insertions(+), 167 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 81ed5a0578..174424f4ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4323,9 +4323,9 @@ void Application::updateLOD(float deltaTime) const { PerformanceTimer perfTimer("LOD"); // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode if (!isThrottleRendering()) { - float batchTime = (float)_gpuContext->getFrameTimerBatchAverage(); + float presentTime = getActiveDisplayPlugin()->getAveragePresentTime(); float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime()); - DependencyManager::get()->autoAdjustLOD(batchTime, engineRunTime, deltaTime); + DependencyManager::get()->autoAdjustLOD(presentTime, engineRunTime, deltaTime); } else { DependencyManager::get()->resetLODAdjust(); } diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 7b99c89cee..c416e6a6c7 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -19,6 +19,11 @@ #include "LODManager.h" +const uint64_t LOD_AUTO_ADJUST_PERIOD = 500 * USECS_PER_MSEC; +const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f; +const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f; + + Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); @@ -39,156 +44,74 @@ float LODManager::getLODIncreaseFPS() { return getDesktopLODIncreaseFPS(); } -void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float deltaTimeSec) { - - // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't - // really want to count them in our average, so we will ignore the real frame rates and stuff - // our moving average with simulated good data - const int IGNORE_THESE_SAMPLES = 100; - if (_fpsAverageUpWindow.getSampleCount() < IGNORE_THESE_SAMPLES) { - _lastStable = _lastUpShift = _lastDownShift = usecTimestampNow(); - } - +void LODManager::autoAdjustLOD(float presentTime, float engineRunTime, float deltaTimeSec) { // compute time-weighted running average renderTime - const float OVERLAY_AND_SWAP_TIME_BUDGET = 2.0f; // msec - float renderTime = batchTime + OVERLAY_AND_SWAP_TIME_BUDGET; - float maxTime = glm::max(renderTime, engineRunTime); - const float BLEND_TIMESCALE = 0.3f; // sec - const float MIN_DELTA_TIME = 0.001f; - const float safeDeltaTime = glm::max(deltaTimeSec, MIN_DELTA_TIME); - float blend = BLEND_TIMESCALE / safeDeltaTime; - if (blend > 1.0f) { - blend = 1.0f; - } + float maxTime = glm::max(presentTime, engineRunTime); + const float LOD_ADJUST_TIMESCALE = 0.1f; // sec + float blend = (deltaTimeSec < LOD_ADJUST_TIMESCALE) ? deltaTimeSec / LOD_ADJUST_TIMESCALE : 1.0f; _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxTime; // msec + if (!_automaticLODAdjust) { + // early exit + return; + } - // translate into fps for legacy implementation + float oldOctreeSizeScale = _octreeSizeScale; float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; - - _fpsAverageStartWindow.updateAverage(currentFPS); - _fpsAverageDownWindow.updateAverage(currentFPS); - _fpsAverageUpWindow.updateAverage(currentFPS); - - quint64 now = usecTimestampNow(); - - quint64 elapsedSinceDownShift = now - _lastDownShift; - quint64 elapsedSinceUpShift = now - _lastUpShift; - - quint64 lastStableOrUpshift = glm::max(_lastUpShift, _lastStable); - quint64 elapsedSinceStableOrUpShift = now - lastStableOrUpshift; - - if (_automaticLODAdjust) { - bool changed = false; - - // LOD Downward adjustment - // If we've been downshifting, we watch a shorter downshift window so that we will quickly move toward our - // target frame rate. But if we haven't just done a downshift (either because our last shift was an upshift, - // or because we've just started out) then we look at a much longer window to consider whether or not to start - // downshifting. - bool doDownShift = false; - - if (_isDownshifting) { - // only consider things if our DOWN_SHIFT time has elapsed... - if (elapsedSinceDownShift > DOWN_SHIFT_ELPASED) { - doDownShift = _fpsAverageDownWindow.getAverage() < getLODDecreaseFPS(); - - if (!doDownShift) { - qCDebug(interfaceapp) << "---- WE APPEAR TO BE DONE DOWN SHIFTING -----"; - _isDownshifting = false; - _lastStable = now; - } - } - } else { - doDownShift = (elapsedSinceStableOrUpShift > START_SHIFT_ELPASED - && _fpsAverageStartWindow.getAverage() < getLODDecreaseFPS()); - } - - if (doDownShift) { - - // Octree items... stepwise adjustment + uint64_t now = usecTimestampNow(); + if (currentFPS < getLODDecreaseFPS()) { + if (now > _decreaseFPSExpiry) { + _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; if (_octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { - _octreeSizeScale *= ADJUST_LOD_DOWN_BY; + _octreeSizeScale *= LOD_AUTO_ADJUST_DECREMENT_FACTOR; if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; } - changed = true; + qCDebug(interfaceapp) << "adjusting LOD UP" + << "fps =" << currentFPS + << "targetFPS =" << getLODDecreaseFPS(); } - - if (changed) { - if (_isDownshifting) { - // subsequent downshift - qCDebug(interfaceapp) << "adjusting LOD DOWN..." - << "average fps for last "<< DOWN_SHIFT_WINDOW_IN_SECS <<"seconds was " - << _fpsAverageDownWindow.getAverage() - << "minimum is:" << getLODDecreaseFPS() - << "elapsedSinceDownShift:" << elapsedSinceDownShift - << " NEW _octreeSizeScale=" << _octreeSizeScale; + _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; + } + _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; + } else if (currentFPS > getLODIncreaseFPS()) { + if (now > _increaseFPSExpiry) { + _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; + if (_octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { + if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { + _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; } else { - // first downshift - qCDebug(interfaceapp) << "adjusting LOD DOWN after initial delay..." - << "average fps for last "<< START_DELAY_WINDOW_IN_SECS <<"seconds was " - << _fpsAverageStartWindow.getAverage() - << "minimum is:" << getLODDecreaseFPS() - << "elapsedSinceUpShift:" << elapsedSinceUpShift - << " NEW _octreeSizeScale=" << _octreeSizeScale; - } - - _lastDownShift = now; - _isDownshifting = true; - - emit LODDecreased(); - } - } else { - - // LOD Upward adjustment - if (elapsedSinceUpShift > UP_SHIFT_ELPASED) { - - if (_fpsAverageUpWindow.getAverage() > getLODIncreaseFPS()) { - - // Octee items... stepwise adjustment - if (_octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { - if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; - } else { - _octreeSizeScale *= ADJUST_LOD_UP_BY; - } - if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; - } - changed = true; - } - } - - if (changed) { - qCDebug(interfaceapp) << "adjusting LOD UP... average fps for last "<< UP_SHIFT_WINDOW_IN_SECS <<"seconds was " - << _fpsAverageUpWindow.getAverage() - << "upshift point is:" << getLODIncreaseFPS() - << "elapsedSinceUpShift:" << elapsedSinceUpShift - << " NEW _octreeSizeScale=" << _octreeSizeScale; - - _lastUpShift = now; - _isDownshifting = false; - - emit LODIncreased(); + _octreeSizeScale *= LOD_AUTO_ADJUST_INCREMENT_FACTOR; } + if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { + _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; + } + qCDebug(interfaceapp) << "adjusting LOD DOWN" + << "fps =" << currentFPS + << "targetFPS =" << getLODDecreaseFPS(); } + _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; } + _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; + } else { + _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; + _decreaseFPSExpiry = _increaseFPSExpiry; + } - if (changed) { - auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); - if (lodToolsDialog) { - lodToolsDialog->reloadSliders(); - } + if (oldOctreeSizeScale != _octreeSizeScale) { + auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); + if (lodToolsDialog) { + lodToolsDialog->reloadSliders(); } + // Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime + // to be at middle of target zone. It will drift close to its true value within + // about three few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary. + float expectedFPS = 0.5f * (getLODIncreaseFPS() + getLODDecreaseFPS()); + _avgRenderTime = MSECS_PER_SECOND / expectedFPS; } } void LODManager::resetLODAdjust() { - _fpsAverageStartWindow.reset(); - _fpsAverageDownWindow.reset(); - _fpsAverageUpWindow.reset(); - _lastUpShift = _lastDownShift = usecTimestampNow(); - _isDownshifting = false; + _decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD; } const float MIN_DECREASE_FPS = 0.5f; @@ -206,7 +129,7 @@ float LODManager::getDesktopLODDecreaseFPS() const { } float LODManager::getDesktopLODIncreaseFPS() const { - return glm::max(((float)MSECS_PER_SECOND / _desktopMaxRenderTime) + INCREASE_LOD_GAP, MAX_LIKELY_DESKTOP_FPS); + return glm::max(((float)MSECS_PER_SECOND / _desktopMaxRenderTime) + INCREASE_LOD_GAP_FPS, MAX_LIKELY_DESKTOP_FPS); } void LODManager::setHMDLODDecreaseFPS(float fps) { @@ -222,7 +145,7 @@ float LODManager::getHMDLODDecreaseFPS() const { } float LODManager::getHMDLODIncreaseFPS() const { - return glm::max(((float)MSECS_PER_SECOND / _hmdMaxRenderTime) + INCREASE_LOD_GAP, MAX_LIKELY_HMD_FPS); + return glm::max(((float)MSECS_PER_SECOND / _hmdMaxRenderTime) + INCREASE_LOD_GAP_FPS, MAX_LIKELY_HMD_FPS); } QString LODManager::getLODFeedbackText() { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 1b3797a0ca..4ec36e613b 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -19,29 +19,13 @@ #include #include -const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 20.0; -const float DEFAULT_HMD_LOD_DOWN_FPS = 20.0; +const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 20.0f; +const float DEFAULT_HMD_LOD_DOWN_FPS = 45.0f; const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec -const float MAX_LIKELY_DESKTOP_FPS = 59.0; // this is essentially, V-synch - 1 fps -const float MAX_LIKELY_HMD_FPS = 74.0; // this is essentially, V-synch - 1 fps -const float INCREASE_LOD_GAP = 15.0f; - -const float START_DELAY_WINDOW_IN_SECS = 3.0f; // wait at least this long after steady state/last upshift to consider downshifts -const float DOWN_SHIFT_WINDOW_IN_SECS = 0.5f; -const float UP_SHIFT_WINDOW_IN_SECS = 2.5f; - -const int ASSUMED_FPS = 60; -const quint64 START_SHIFT_ELPASED = USECS_PER_SECOND * START_DELAY_WINDOW_IN_SECS; -const quint64 DOWN_SHIFT_ELPASED = USECS_PER_SECOND * DOWN_SHIFT_WINDOW_IN_SECS; // Consider adjusting LOD down after half a second -const quint64 UP_SHIFT_ELPASED = USECS_PER_SECOND * UP_SHIFT_WINDOW_IN_SECS; - -const int START_DELAY_SAMPLES_OF_FRAMES = ASSUMED_FPS * START_DELAY_WINDOW_IN_SECS; -const int DOWN_SHIFT_SAMPLES_OF_FRAMES = ASSUMED_FPS * DOWN_SHIFT_WINDOW_IN_SECS; -const int UP_SHIFT_SAMPLES_OF_FRAMES = ASSUMED_FPS * UP_SHIFT_WINDOW_IN_SECS; - -const float ADJUST_LOD_DOWN_BY = 0.9f; -const float ADJUST_LOD_UP_BY = 1.1f; +const float MAX_LIKELY_DESKTOP_FPS = 59.0f; // this is essentially, V-synch - 1 fps +const float MAX_LIKELY_HMD_FPS = 74.0f; // this is essentially, V-synch - 1 fps +const float INCREASE_LOD_GAP_FPS = 15.0f; // fps // The default value DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision). const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; @@ -78,7 +62,7 @@ public: Q_INVOKABLE float getLODIncreaseFPS(); static bool shouldRender(const RenderArgs* args, const AABox& bounds); - void autoAdjustLOD(float batchTime, float engineRunTime, float deltaTimeSec); + void autoAdjustLOD(float presentTime, float engineRunTime, float deltaTimeSec); void loadSettings(); void saveSettings(); @@ -92,21 +76,15 @@ private: LODManager(); bool _automaticLODAdjust = true; - float _avgRenderTime { 0.0 }; + float _avgRenderTime { 0.0f }; float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME }; float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME }; float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; - - quint64 _lastDownShift = 0; - quint64 _lastUpShift = 0; - quint64 _lastStable = 0; - bool _isDownshifting = false; // start out as if we're not downshifting - - SimpleMovingAverage _fpsAverageStartWindow = START_DELAY_SAMPLES_OF_FRAMES; - SimpleMovingAverage _fpsAverageDownWindow = DOWN_SHIFT_SAMPLES_OF_FRAMES; - SimpleMovingAverage _fpsAverageUpWindow = UP_SHIFT_SAMPLES_OF_FRAMES; + + uint64_t _decreaseFPSExpiry { 0 }; + uint64_t _increaseFPSExpiry { 0 }; }; #endif // hifi_LODManager_h From 9c4a0c8c702b6f3565c2c1c1945aa058503d48e4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Dec 2017 14:12:46 -0800 Subject: [PATCH 77/81] tweak LOD adjustment logging --- interface/src/LODManager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index c416e6a6c7..77aabccb78 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -66,9 +66,10 @@ void LODManager::autoAdjustLOD(float presentTime, float engineRunTime, float del if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; } - qCDebug(interfaceapp) << "adjusting LOD UP" + qCDebug(interfaceapp) << "adjusting LOD DOWN" << "fps =" << currentFPS - << "targetFPS =" << getLODDecreaseFPS(); + << "targetFPS =" << getLODDecreaseFPS() + << "octreeSizeScale =" << _octreeSizeScale; } _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; } @@ -85,9 +86,10 @@ void LODManager::autoAdjustLOD(float presentTime, float engineRunTime, float del if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; } - qCDebug(interfaceapp) << "adjusting LOD DOWN" + qCDebug(interfaceapp) << "adjusting LOD UP" << "fps =" << currentFPS - << "targetFPS =" << getLODDecreaseFPS(); + << "targetFPS =" << getLODDecreaseFPS() + << "octreeSizeScale =" << _octreeSizeScale; } _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; } From 4fb9680f3b96654675cff9fcec91b6efcb64755f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Dec 2017 16:43:49 -0800 Subject: [PATCH 78/81] also consider GPU render time for LOD adjust --- interface/src/Application.cpp | 4 +++- interface/src/LODManager.cpp | 5 ++--- interface/src/LODManager.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 174424f4ca..f17e06cb35 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4325,7 +4325,9 @@ void Application::updateLOD(float deltaTime) const { if (!isThrottleRendering()) { float presentTime = getActiveDisplayPlugin()->getAveragePresentTime(); float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime()); - DependencyManager::get()->autoAdjustLOD(presentTime, engineRunTime, deltaTime); + float gpuTime = getGPUContext()->getFrameTimerGPUAverage(); + float maxRenderTime = glm::max(gpuTime, glm::max(presentTime, engineRunTime)); + DependencyManager::get()->autoAdjustLOD(maxRenderTime, deltaTime); } else { DependencyManager::get()->resetLODAdjust(); } diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 77aabccb78..c369920cf3 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -44,12 +44,11 @@ float LODManager::getLODIncreaseFPS() { return getDesktopLODIncreaseFPS(); } -void LODManager::autoAdjustLOD(float presentTime, float engineRunTime, float deltaTimeSec) { +void LODManager::autoAdjustLOD(float renderTime, float deltaTimeSec) { // compute time-weighted running average renderTime - float maxTime = glm::max(presentTime, engineRunTime); const float LOD_ADJUST_TIMESCALE = 0.1f; // sec float blend = (deltaTimeSec < LOD_ADJUST_TIMESCALE) ? deltaTimeSec / LOD_ADJUST_TIMESCALE : 1.0f; - _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxTime; // msec + _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * renderTime; // msec if (!_automaticLODAdjust) { // early exit return; diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 4ec36e613b..eadb3f2e5c 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -62,7 +62,7 @@ public: Q_INVOKABLE float getLODIncreaseFPS(); static bool shouldRender(const RenderArgs* args, const AABox& bounds); - void autoAdjustLOD(float presentTime, float engineRunTime, float deltaTimeSec); + void autoAdjustLOD(float renderTime, float deltaTimeSec); void loadSettings(); void saveSettings(); From 5c11ae346962639c57fb8a89fc1b4979cec5a079 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Dec 2017 16:50:31 -0800 Subject: [PATCH 79/81] bump desktop min FPS from 20 to 30 msec --- interface/src/LODManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index eadb3f2e5c..374f6a2e73 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -19,7 +19,7 @@ #include #include -const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 20.0f; +const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0f; const float DEFAULT_HMD_LOD_DOWN_FPS = 45.0f; const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec From 721e9d426aa3462c63e141ff55ebe5c874bde722 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 20 Dec 2017 09:14:53 -0800 Subject: [PATCH 80/81] restore signals on LOD change --- interface/src/LODManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index c369920cf3..714cc31f13 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -69,6 +69,7 @@ void LODManager::autoAdjustLOD(float renderTime, float deltaTimeSec) { << "fps =" << currentFPS << "targetFPS =" << getLODDecreaseFPS() << "octreeSizeScale =" << _octreeSizeScale; + emit LODDecreased(); } _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; } @@ -89,6 +90,7 @@ void LODManager::autoAdjustLOD(float renderTime, float deltaTimeSec) { << "fps =" << currentFPS << "targetFPS =" << getLODDecreaseFPS() << "octreeSizeScale =" << _octreeSizeScale; + emit LODIncreased(); } _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; } From c1906215ba455113fc7c24ad3d89f21b76782b62 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 20 Dec 2017 11:36:51 -0800 Subject: [PATCH 81/81] add comments --- interface/src/LODManager.cpp | 28 +++++++++++++++++++++------- interface/src/LODManager.h | 2 +- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 714cc31f13..9e6fabd439 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -19,10 +19,6 @@ #include "LODManager.h" -const uint64_t LOD_AUTO_ADJUST_PERIOD = 500 * USECS_PER_MSEC; -const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f; -const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f; - Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); @@ -44,10 +40,28 @@ float LODManager::getLODIncreaseFPS() { return getDesktopLODIncreaseFPS(); } -void LODManager::autoAdjustLOD(float renderTime, float deltaTimeSec) { +// We use a "time-weighted running average" of the renderTime and compare it against min/max thresholds +// to determine if we should adjust the level of detail (LOD). +// +// A time-weighted running average has a timescale which determines how fast the average tracks the measured +// value in real-time. Given a step-function in the mesured value, and assuming measurements happen +// faster than the runningAverage is computed, the error between the value and its runningAverage will be +// reduced by 1/e every timescale of real-time that passes. +const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.1f; // sec +// +// Assuming the measured value is affected by logic invoked by the runningAverage bumping up against its +// thresholds, we expect the adjustment to introduce a step-function. We want the runningAverage settle +// to the new value BEFORE we test it aginst its thresholds again. Hence we test on a period that is a few +// multiples of the running average timescale: +const uint64_t LOD_AUTO_ADJUST_PERIOD = 5 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec + +const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f; +const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f; + +void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) { // compute time-weighted running average renderTime - const float LOD_ADJUST_TIMESCALE = 0.1f; // sec - float blend = (deltaTimeSec < LOD_ADJUST_TIMESCALE) ? deltaTimeSec / LOD_ADJUST_TIMESCALE : 1.0f; + // Note: we MUST clamp the blend to 1.0 for stability + float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f; _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * renderTime; // msec if (!_automaticLODAdjust) { // early exit diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 374f6a2e73..cf38342db0 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -62,7 +62,7 @@ public: Q_INVOKABLE float getLODIncreaseFPS(); static bool shouldRender(const RenderArgs* args, const AABox& bounds); - void autoAdjustLOD(float renderTime, float deltaTimeSec); + void autoAdjustLOD(float renderTime, float realTimeDelta); void loadSettings(); void saveSettings();