diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 0a5a68717e..59728c4157 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -24,6 +24,7 @@ Item { property alias webView: webview property alias profile: webview.profile property bool remove: false + property bool closeButtonVisible: true // Manage own browse history because WebEngineView history is wiped when a new URL is loaded via // onNewViewRequested, e.g., as happens when a social media share button is clicked. @@ -64,6 +65,7 @@ Item { disabledColor: hifi.colors.lightGrayText enabled: true text: "CLOSE" + visible: closeButtonVisible MouseArea { anchors.fill: parent diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index c7df6ac64f..bbf56c7827 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -93,6 +93,11 @@ Item { loader.source = ""; loader.source = "TabletWebView.qml"; } + + function loadTabletWebBase() { + loader.source = ""; + loader.source = "../../controls/TabletWebView.qml"; + } function returnToPreviousApp() { tabletApps.remove(currentApp); @@ -121,6 +126,9 @@ Item { loader.item.url = url; loader.item.scriptURL = injectedJavaScriptUrl; tabletApps.append({"appUrl": "TabletWebView.qml", "isWebUrl": true, "scriptUrl": injectedJavaScriptUrl, "appWebUrl": url}); + if (loader.item.hasOwnProperty("closeButtonVisible")) { + loader.item.closeButtonVisible = false; + } } // used to send a message from qml to interface script. diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index fdfcfcf806..8596007956 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -42,9 +42,17 @@ Windows.ScrollingWindow { loader.source = "WindowWebView.qml"; } + function loadTabletWebBase() { + loader.source = ""; + loader.source = "../../controls/TabletWebView.qml"; + } + function loadWebUrl(url, injectedJavaScriptUrl) { loader.item.url = url; loader.item.scriptURL = injectedJavaScriptUrl; + if (loader.item.hasOwnProperty("closeButtonVisible")) { + loader.item.closeButtonVisible = false; + } } // used to send a message from qml to interface script. diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 482af2de5c..398b2dbdb4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2851,6 +2851,18 @@ bool Application::importSVOFromURL(const QString& urlString) { return true; } +bool Application::importFromZIP(const QString& filePath) { + qDebug() << "A zip file has been dropped in: " << filePath; + QUrl empty; + // handle Blocks download from Marketplace + if (filePath.contains("vr.google.com/downloads")) { + addAssetToWorldFromURL(filePath); + } else { + qApp->getFileDownloadInterface()->runUnzip(filePath, empty, true, true, false); + } + return true; +} + void Application::onPresent(quint32 frameCount) { if (shouldPaint()) { postEvent(this, new QEvent(static_cast(Idle)), Qt::HighEventPriority); @@ -2858,13 +2870,6 @@ void Application::onPresent(quint32 frameCount) { } } -bool Application::importFromZIP(const QString& filePath) { - qDebug() << "A zip file has been dropped in: " << filePath; - QUrl empty; - qApp->getFileDownloadInterface()->runUnzip(filePath, empty, true, true); - return true; -} - bool _renderRequested { false }; bool Application::event(QEvent* event) { @@ -6354,8 +6359,15 @@ void Application::showAssetServerWidget(QString filePath) { void Application::addAssetToWorldFromURL(QString url) { qInfo(interfaceapp) << "Download model and add to world from" << url; - - QString filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. + + QString filename; + if (url.contains("filename")) { + filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. + } + if (url.contains("vr.google.com/downloads")) { + filename = url.section('/', -1); + filename.remove(".zip?noDownload=false"); + } if (!DependencyManager::get()->getThisNodeCanWriteAssets()) { QString errorInfo = "You do not have permissions to write to the Asset Server."; @@ -6376,7 +6388,17 @@ void Application::addAssetToWorldFromURLRequestFinished() { auto url = request->getUrl().toString(); auto result = request->getResult(); - QString filename = url.section("filename=", 1, 1); // Filename from trailing "?filename=" URL parameter. + QString filename; + bool isBlocks = false; + + if (url.contains("filename")) { + filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. + } + if (url.contains("vr.google.com/downloads")) { + filename = url.section('/', -1); + filename.remove(".zip?noDownload=false"); + isBlocks = true; + } if (result == ResourceRequest::Success) { qInfo(interfaceapp) << "Downloaded model from" << url; @@ -6391,7 +6413,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { if (tempFile.open(QIODevice::WriteOnly)) { tempFile.write(request->getData()); addAssetToWorldInfoClear(filename); // Remove message from list; next one added will have a different key. - qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false); + qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocks); } else { QString errorInfo = "Couldn't open temporary file for download"; qWarning(interfaceapp) << errorInfo; @@ -6421,7 +6443,7 @@ void Application::addAssetToWorldUnzipFailure(QString filePath) { addAssetToWorldError(filename, "Couldn't unzip file " + filename + "."); } -void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip) { +void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocks) { // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). QString mapping; QString path = filePath; @@ -6430,6 +6452,11 @@ void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip) QString assetFolder = zipFile.section("/", -1); assetFolder.remove(".zip"); mapping = "/" + assetFolder + "/" + filename; + } else if (isBlocks) { + qCDebug(interfaceapp) << "Path to asset folder: " << zipFile; + QString assetFolder = zipFile.section('/', -1); + assetFolder.remove(".zip?noDownload=false"); + mapping = "/" + assetFolder + "/" + filename; } else { mapping = "/" + filename; } @@ -6809,12 +6836,12 @@ void Application::onAssetToWorldMessageBoxClosed() { } -void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip) { +void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocks) { if (autoAdd) { if (!unzipFile.isEmpty()) { for (int i = 0; i < unzipFile.length(); i++) { qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i); - addAssetToWorld(unzipFile.at(i), zipFile, isZip); + addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocks); } } else { addAssetToWorldUnzipFailure(zipFile); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5d4f8876ac..c951b25930 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -339,14 +339,14 @@ public slots: // FIXME: Move addAssetToWorld* methods to own class? void addAssetToWorldFromURL(QString url); void addAssetToWorldFromURLRequestFinished(); - void addAssetToWorld(QString filePath, QString zipFile, bool isZip); + void addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocks); void addAssetToWorldUnzipFailure(QString filePath); void addAssetToWorldWithNewMapping(QString filePath, QString mapping, int copy); void addAssetToWorldUpload(QString filePath, QString mapping); void addAssetToWorldSetMapping(QString filePath, QString mapping, QString hash); void addAssetToWorldAddEntity(QString filePath, QString mapping); - void handleUnzip(QString sourceFile, QStringList destinationFile, bool autoAdd, bool isZip); + void handleUnzip(QString sourceFile, QStringList destinationFile, bool autoAdd, bool isZip, bool isBlocks); FileScriptingInterface* getFileDownloadInterface() { return _fileDownload; } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index a19055d4da..084e540ff4 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -216,7 +216,17 @@ int main(int argc, const char* argv[]) { SandboxUtils::runLocalSandbox(serverContentPath, true, noUpdater); } - Application app(argc, const_cast(argv), startupTime, runningMarkerExisted); + // to enable WebGL rendering + char* additionalCommandLineArg = (char*)"--ignore-gpu-blacklist"; + int newArgc = argc + 1; + char** newArgv = new char*[newArgc]; + for (int i = 0; i < argc; ++i) { + newArgv[i] = (char*)argv[i]; + } + newArgv[argc] = additionalCommandLineArg; + + Application app(newArgc, const_cast(newArgv), startupTime, runningMarkerExisted); + delete[] newArgv; // If we failed the OpenGLVersion check, log it. if (override) { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 277989439c..f63c128cf5 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -264,6 +264,10 @@ void WindowScriptingInterface::showAssetServer(const QString& upload) { QMetaObject::invokeMethod(qApp, "showAssetServerWidget", Qt::QueuedConnection, Q_ARG(QString, upload)); } +QString WindowScriptingInterface::checkVersion() { + return QCoreApplication::applicationVersion(); +} + int WindowScriptingInterface::getInnerWidth() { return qApp->getWindow()->geometry().width(); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 28f1bafa5d..4b5e2e81fc 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -58,6 +58,7 @@ public slots: QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); QScriptValue browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); void showAssetServer(const QString& upload = ""); + QString checkVersion(); void copyToClipboard(const QString& text); void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f); void takeSecondaryCameraSnapshot(); diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 5f2460be78..68a141ad97 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -32,10 +32,11 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent // nothing for now } -void FileScriptingInterface::runUnzip(QString path, QUrl url, bool autoAdd, bool isZip) { +void FileScriptingInterface::runUnzip(QString path, QUrl url, bool autoAdd, bool isZip, bool isBlocks) { qCDebug(scriptengine) << "Url that was downloaded: " + url.toString(); qCDebug(scriptengine) << "Path where download is saved: " + path; QString fileName = "/" + path.section("/", -1); + qCDebug(scriptengine) << "Filename: " << fileName; QString tempDir = path; if (!isZip) { tempDir.remove(fileName); @@ -52,14 +53,17 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url, bool autoAdd, bool } QStringList fileList = unzipFile(path, tempDir); - QString filename = QUrl::fromLocalFile(fileList.first()).toString(); - if (filename != "") { - qCDebug(scriptengine) << "File to upload: " + filename; + if (!fileList.isEmpty()) { + qCDebug(scriptengine) << "File to upload: " + fileList.first(); } else { qCDebug(scriptengine) << "Unzip failed"; } - emit unzipResult(path, fileList, autoAdd, isZip); + + if (path.contains("vr.google.com/downloads")) { + isZip = true; + } + emit unzipResult(path, fileList, autoAdd, isZip, isBlocks); } diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 4069e7cc78..e4c27dbf7f 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -24,11 +24,11 @@ public: public slots: QString convertUrlToPath(QUrl url); - void runUnzip(QString path, QUrl url, bool autoAdd, bool isZip); + void runUnzip(QString path, QUrl url, bool autoAdd, bool isZip, bool isBlocks); QString getTempDir(); signals: - void unzipResult(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip); + void unzipResult(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocks); private: bool isTempDir(QString tempDir); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 984d743ebf..adff219e0f 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -604,9 +604,9 @@ void TabletProxy::loadWebScreenOnTop(const QVariant& url, const QString& injectJ _state = State::Web; } -void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl) { +void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "gotoWebScreen", Q_ARG(QString, url), Q_ARG(QString, injectedJavaScriptUrl)); + QMetaObject::invokeMethod(this, "gotoWebScreen", Q_ARG(QString, url), Q_ARG(QString, injectedJavaScriptUrl), Q_ARG(bool, loadOtherBase)); return; } @@ -619,7 +619,11 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS if (root) { removeButtonsFromHomeScreen(); - QMetaObject::invokeMethod(root, "loadWebBase"); + if (loadOtherBase) { + QMetaObject::invokeMethod(root, "loadTabletWebBase"); + } else { + QMetaObject::invokeMethod(root, "loadWebBase"); + } QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index af38cb9351..822bae839e 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -122,7 +122,7 @@ public: * @param [injectedJavaScriptUrl] {string} optional url to an additional JS script to inject into the web page. */ Q_INVOKABLE void gotoWebScreen(const QString& url); - Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl); + Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false); Q_INVOKABLE void loadQMLSource(const QVariant& path); // FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success); diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 80c8f8a0e4..26f51278e0 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -81,6 +81,7 @@ letUsKnow.replaceWith(letUsKnow.html()); // Add button links. + $('#exploreClaraMarketplace').on('click', function () { window.location = "https://clara.io/library?gameCheck=true&public=true"; }); @@ -221,7 +222,7 @@ // One file request at a time. if (isPreparing) { - console.log("WARNIKNG: Clara.io FBX: Prepare only one download at a time"); + console.log("WARNING: Clara.io FBX: Prepare only one download at a time"); return; } @@ -397,8 +398,8 @@ var pageType = DIRECTORY; if (location.href.indexOf("highfidelity.com/") !== -1) { pageType = HIFI; } - if (location.href.indexOf("highfidelity.com/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } if (location.href.indexOf("clara.io/") !== -1) { pageType = CLARA; } + if (location.href.indexOf("highfidelity.com/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } injectCommonCode(pageType === DIRECTORY); switch (pageType) { @@ -408,12 +409,13 @@ case HIFI: injectHiFiCode(); break; - case HIFI_ITEM_PAGE: - injectHiFiItemPageCode(); - break; case CLARA: injectClaraCode(); break; + case HIFI_ITEM_PAGE: + injectHiFiItemPageCode(); + break; + } } diff --git a/unpublishedScripts/marketplace/blocks/blocksApp.js b/unpublishedScripts/marketplace/blocks/blocksApp.js new file mode 100644 index 0000000000..2c20e13005 --- /dev/null +++ b/unpublishedScripts/marketplace/blocks/blocksApp.js @@ -0,0 +1,43 @@ +/// +/// blocksApp.js +/// A tablet app for downloading 3D assets from Google Blocks +/// +/// Author: Elisa Lupin-Jimenez +/// Copyright High Fidelity 2017 +/// +/// Licensed under the Apache 2.0 License +/// See accompanying license file or http://apache.org/ +/// +/// All assets are under CC Attribution Non-Commerical +/// http://creativecommons.org/licenses/ +/// + +(function () { + var APP_NAME = "BLOCKS"; + var APP_URL = "https://vr.google.com/objects/"; + var APP_ICON = "https://hifi-content.s3.amazonaws.com/elisalj/blocks/blocks-i.svg"; + + try { + print("Current Interface version: " + Window.checkVersion()); + } catch(err) { + print("Outdated Interface version does not support Blocks"); + APP_URL = "https://hifi-content.s3.amazonaws.com/elisalj/blocks/updateToBlocks.html"; + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + icon: APP_ICON, + text: APP_NAME + }); + + function onClicked() { + tablet.gotoWebScreen(APP_URL, "", true); + } + button.clicked.connect(onClicked); + + function cleanup() { + tablet.removeButton(button); + } + + Script.scriptEnding.connect(cleanup); +}());