diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 549e5338a0..2bc1d1e20e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -229,6 +229,7 @@ static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; static const QString WEB_VIEW_TAG = "noDownload=true"; +static const QString ZIP_EXTENSION = ".zip"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; @@ -260,7 +261,8 @@ const QHash Application::_acceptedExtensi { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }, { JSON_EXTENSION, &Application::importJSONFromURL }, { JS_EXTENSION, &Application::askToLoadScript }, - { FST_EXTENSION, &Application::askToSetAvatarUrl } + { FST_EXTENSION, &Application::askToSetAvatarUrl }, + { ZIP_EXTENSION, &Application::importFromZIP } }; class DeadlockWatchdogThread : public QThread { @@ -2779,6 +2781,15 @@ 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) { if (!Menu::getInstance()) { return false; @@ -6218,7 +6229,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); + qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false); } else { QString errorInfo = "Couldn't open temporary file for download"; qWarning(interfaceapp) << errorInfo; @@ -6248,12 +6259,18 @@ void Application::addAssetToWorldUnzipFailure(QString filePath) { addAssetToWorldError(filename, "Couldn't unzip file " + filename + "."); } -void Application::addAssetToWorld(QString filePath) { +void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip) { // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). - - QString path = QUrl(filePath).toLocalFile(); + QString mapping; + QString path = filePath; QString filename = filenameFromPath(path); - QString mapping = "/" + filename; + if (isZip) { + QString assetFolder = zipFile.section("/", -1); + assetFolder.remove(".zip"); + mapping = "/" + assetFolder + "/" + filename; + } else { + mapping = "/" + filename; + } // Test repeated because possibly different code paths. if (!DependencyManager::get()->getThisNodeCanWriteAssets()) { @@ -6334,7 +6351,13 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q qWarning(interfaceapp) << "Error downloading model: " + errorInfo; addAssetToWorldError(filenameFromPath(filePath), errorInfo); } else { - addAssetToWorldAddEntity(filePath, mapping); + // to prevent files that aren't models from being loaded into world automatically + if (filePath.endsWith(".obj") || filePath.endsWith(".fbx")) { + addAssetToWorldAddEntity(filePath, mapping); + } else { + qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; + addAssetToWorldInfoDone(filenameFromPath(filePath)); + } } request->deleteLater(); }); @@ -6624,15 +6647,18 @@ void Application::onAssetToWorldMessageBoxClosed() { } -void Application::handleUnzip(QString zipFile, QString unzipFile, bool autoAdd) { +void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip) { if (autoAdd) { if (!unzipFile.isEmpty()) { - addAssetToWorld(unzipFile); + for (int i = 0; i < unzipFile.length(); i++) { + qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i); + addAssetToWorld(unzipFile.at(i), zipFile, isZip); + } } else { addAssetToWorldUnzipFailure(zipFile); } } else { - showAssetServerWidget(unzipFile); + showAssetServerWidget(unzipFile.first()); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 300bd4ac02..f8eb393f9e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -331,14 +331,14 @@ public slots: // FIXME: Move addAssetToWorld* methods to own class? void addAssetToWorldFromURL(QString url); void addAssetToWorldFromURLRequestFinished(); - void addAssetToWorld(QString filePath); + void addAssetToWorld(QString filePath, QString zipFile, bool isZip); 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, QString destinationFile, bool autoAdd); + void handleUnzip(QString sourceFile, QStringList destinationFile, bool autoAdd, bool isZip); FileScriptingInterface* getFileDownloadInterface() { return _fileDownload; } @@ -481,6 +481,7 @@ private: bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); + bool importFromZIP(const QString& filePath); bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 30d0a3a201..5f2460be78 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -32,26 +32,54 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent // nothing for now } -void FileScriptingInterface::runUnzip(QString path, QUrl url, bool autoAdd) { +void FileScriptingInterface::runUnzip(QString path, QUrl url, bool autoAdd, bool isZip) { qCDebug(scriptengine) << "Url that was downloaded: " + url.toString(); qCDebug(scriptengine) << "Path where download is saved: " + path; QString fileName = "/" + path.section("/", -1); QString tempDir = path; - tempDir.remove(fileName); + if (!isZip) { + tempDir.remove(fileName); + } else { + QTemporaryDir zipTemp; + tempDir = zipTemp.path(); + path.remove("file:///"); + } + qCDebug(scriptengine) << "Temporary directory at: " + tempDir; if (!isTempDir(tempDir)) { qCDebug(scriptengine) << "Temporary directory mismatch; risk of losing files"; return; } - QString file = unzipFile(path, tempDir); - QString filename = QUrl::fromLocalFile(file).toString(); - if (file != "") { + QStringList fileList = unzipFile(path, tempDir); + QString filename = QUrl::fromLocalFile(fileList.first()).toString(); + + if (filename != "") { qCDebug(scriptengine) << "File to upload: " + filename; } else { qCDebug(scriptengine) << "Unzip failed"; } - emit unzipResult(path, filename, autoAdd); + emit unzipResult(path, fileList, autoAdd, isZip); + +} + +QStringList FileScriptingInterface::unzipFile(QString path, QString tempDir) { + + QDir dir(path); + QString dirName = dir.path(); + qCDebug(scriptengine) << "Directory to unzip: " << dirName; + QString target = tempDir + "/model_repo"; + QStringList list = JlCompress::extractDir(dirName, target); + + qCDebug(scriptengine) << list; + + if (!list.isEmpty()) { + return list; + } else { + qCDebug(scriptengine) << "Extraction failed"; + return list; + } + } // fix to check that we are only referring to a temporary directory @@ -92,24 +120,6 @@ void FileScriptingInterface::downloadZip(QString path, const QString link) { request->send(); } -QString FileScriptingInterface::unzipFile(QString path, QString tempDir) { - - QDir dir(path); - QString dirName = dir.path(); - QString target = tempDir + "/model_repo"; - QStringList list = JlCompress::extractDir(dirName, target); - - qCDebug(scriptengine) << list; - - if (!list.isEmpty()) { - return list.front(); - } else { - qCDebug(scriptengine) << "Extraction failed"; - return ""; - } - -} - // this function is not in use void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) { /*if (!file.isDir()) { diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 5e9a6029e8..4069e7cc78 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -24,15 +24,15 @@ public: public slots: QString convertUrlToPath(QUrl url); - void runUnzip(QString path, QUrl url, bool autoAdd); + void runUnzip(QString path, QUrl url, bool autoAdd, bool isZip); QString getTempDir(); signals: - void unzipResult(QString zipFile, QString unzipFile, bool autoAdd); + void unzipResult(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip); private: bool isTempDir(QString tempDir); - QString unzipFile(QString path, QString tempDir); + QStringList unzipFile(QString path, QString tempDir); void recursiveFileScan(QFileInfo file, QString* dirName); void downloadZip(QString path, const QString link); diff --git a/scripts/system/html/img/blocks-tile.png b/scripts/system/html/img/blocks-tile.png new file mode 100644 index 0000000000..49de535c1c Binary files /dev/null and b/scripts/system/html/img/blocks-tile.png differ diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 3b3d4b4937..8a8cf62008 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -33,8 +33,8 @@ $("head").append( '