From 69b0691eb6ff10aa0f067e3af0d01d6b43014196 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 18 May 2017 16:35:56 -0700 Subject: [PATCH 01/49] Update content set URL for RC40 --- server-console/src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server-console/src/main.js b/server-console/src/main.js index 4ce1ccfb02..98bda9a10f 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -42,7 +42,7 @@ const appIcon = path.join(__dirname, '../resources/console.png'); const DELETE_LOG_FILES_OLDER_THAN_X_SECONDS = 60 * 60 * 24 * 7; // 7 Days const LOG_FILE_REGEX = /(domain-server|ac-monitor|ac)-.*-std(out|err).txt/; -const HOME_CONTENT_URL = "http://cdn.highfidelity.com/content-sets/home-tutorial-RC39.tar.gz"; +const HOME_CONTENT_URL = "http://cdn.highfidelity.com/content-sets/home-tutorial-RC40.tar.gz"; function getBuildInfo() { var buildInfoPath = null; From d7d4ff1f822ce3390e276ee48525b12ef5542c5c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 May 2017 11:11:00 -0700 Subject: [PATCH 02/49] Add notes to KtxStorage::maybeOpenFile --- libraries/gpu/src/gpu/Texture_ktx.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 92ead5f616..9799aecdf5 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -184,6 +184,11 @@ 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; From 50f5ae6e7799c1a4f38fc4167674f49911d441dd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 May 2017 11:16:20 -0700 Subject: [PATCH 03/49] Fix FileStorage to not close files after they are opened This is particularly an issue with KTX file reading/writing where we do both concurrently. --- libraries/gpu/src/gpu/Texture_ktx.cpp | 12 +++++--- libraries/shared/src/shared/Storage.cpp | 41 ++++++------------------- libraries/shared/src/shared/Storage.h | 3 +- 3 files changed, 18 insertions(+), 38 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 9799aecdf5..bf5b4d7965 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -210,7 +210,6 @@ std::shared_ptr KtxStorage::maybeOpenFile() const { } PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { - storage::StoragePointer result; auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); if (faceSize != 0 && faceOffset != 0) { @@ -226,7 +225,7 @@ PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { qWarning() << "Failed to get a valid file out of maybeOpenFile " << QString::fromStdString(_filename); } } - return result; + return nullptr; } Size KtxStorage::getMipFaceSize(uint16 level, uint8 face) const { @@ -260,8 +259,13 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor } auto file = maybeOpenFile(); + if (!file) { + qWarning() << "Failed to open file to assign mip data " << QString::fromStdString(_filename); + return; + } - auto imageData = file->mutableData(); + auto fileData = file->mutableData(); + auto imageData = fileData; imageData += ktx::KTX_HEADER_SIZE + _ktxDescriptor->header.bytesOfKeyValueData + _ktxDescriptor->images[level]._imageOffset; imageData += ktx::IMAGE_SIZE_WIDTH; @@ -276,7 +280,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor memcpy(imageData, storage->data(), storage->size()); _minMipLevelAvailable = level; if (_offsetToMinMipKV > 0) { - auto minMipKeyData = file->mutableData() + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV; + auto minMipKeyData = fileData + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV; memcpy(minMipKeyData, (void*)&_minMipLevelAvailable, 1); } } diff --git a/libraries/shared/src/shared/Storage.cpp b/libraries/shared/src/shared/Storage.cpp index e479559e6a..b07f896df0 100644 --- a/libraries/shared/src/shared/Storage.cpp +++ b/libraries/shared/src/shared/Storage.cpp @@ -70,7 +70,15 @@ StoragePointer FileStorage::create(const QString& filename, size_t size, const u } FileStorage::FileStorage(const QString& filename) : _file(filename) { - if (_file.open(QFile::ReadOnly)) { + bool opened = _file.open(QFile::ReadWrite); + if (opened) { + _hasWriteAccess = true; + } else { + _hasWriteAccess = false; + opened = _file.open(QFile::ReadOnly); + } + + if (opened) { _mapped = _file.map(0, _file.size()); if (_mapped) { _valid = true; @@ -91,35 +99,4 @@ FileStorage::~FileStorage() { if (_file.isOpen()) { _file.close(); } -} - -void FileStorage::ensureWriteAccess() { - if (_hasWriteAccess) { - return; - } - - if (_mapped) { - if (!_file.unmap(_mapped)) { - throw std::runtime_error("Unable to unmap file"); - } - } - if (_file.isOpen()) { - _file.close(); - } - _valid = false; - _mapped = nullptr; - - if (_file.open(QFile::ReadWrite)) { - _mapped = _file.map(0, _file.size()); - if (_mapped) { - _valid = true; - _hasWriteAccess = true; - } else { - qCWarning(storagelogging) << "Failed to map file " << _file.fileName(); - throw std::runtime_error("Failed to map file"); - } - } else { - qCWarning(storagelogging) << "Failed to open file " << _file.fileName(); - throw std::runtime_error("Failed to open file"); - } } \ No newline at end of file diff --git a/libraries/shared/src/shared/Storage.h b/libraries/shared/src/shared/Storage.h index 4cad9fa083..d7946738cf 100644 --- a/libraries/shared/src/shared/Storage.h +++ b/libraries/shared/src/shared/Storage.h @@ -60,11 +60,10 @@ namespace storage { FileStorage& operator=(const FileStorage& other) = delete; const uint8_t* data() const override { return _mapped; } - uint8_t* mutableData() override { ensureWriteAccess(); return _mapped; } + uint8_t* mutableData() override { return _hasWriteAccess ? _mapped : nullptr; } size_t size() const override { return _file.size(); } operator bool() const override { return _valid; } private: - void ensureWriteAccess(); bool _valid { false }; bool _hasWriteAccess { false }; From 53a963726d2c1d76341ab3707ce73d565363d6d1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 May 2017 15:00:53 -0700 Subject: [PATCH 04/49] Add check for valid mutableData in assignMipData --- libraries/gpu/src/gpu/Texture_ktx.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index bf5b4d7965..14282ec525 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -265,6 +265,11 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor } auto fileData = file->mutableData(); + if (!fileData) { + qWarning() << "Failed to get mutable data for " << QString::fromStdString(_filename); + return; + } + auto imageData = fileData; imageData += ktx::KTX_HEADER_SIZE + _ktxDescriptor->header.bytesOfKeyValueData + _ktxDescriptor->images[level]._imageOffset; imageData += ktx::IMAGE_SIZE_WIDTH; From 5cb25b1ef1692c5daffc647efd86e0bf9a2a668e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 19 May 2017 16:53:25 -0700 Subject: [PATCH 05/49] Increment _identitySequenceId before sending ID packet for agents --- assignment-client/src/Agent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 5864cadc15..96b2336af8 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -584,6 +584,7 @@ void Agent::setIsAvatar(bool isAvatar) { void Agent::sendAvatarIdentityPacket() { if (_isAvatar) { auto scriptedAvatar = DependencyManager::get(); + scriptedAvatar->markIdentityDataChanged(); scriptedAvatar->sendIdentityPacket(); } } From 2928507e4898cc863d701398598895d360f9f6ba Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 19 May 2017 10:48:38 -0700 Subject: [PATCH 06/49] Fix "Reset Settings" window poping up every time --- interface/src/Application.cpp | 8 ++++---- interface/src/Application.h | 2 +- interface/src/CrashHandler.cpp | 5 +---- interface/src/CrashHandler.h | 2 +- interface/src/main.cpp | 3 ++- libraries/shared/src/RunningMarker.cpp | 7 ++++++- libraries/shared/src/RunningMarker.h | 4 +++- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c39f7294c0..bd66a96879 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -431,7 +431,7 @@ static const QString STATE_ADVANCED_MOVEMENT_CONTROLS = "AdvancedMovement"; static const QString STATE_GROUNDED = "Grounded"; static const QString STATE_NAV_FOCUSED = "NavigationFocused"; -bool setupEssentials(int& argc, char** argv) { +bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { const char** constArgv = const_cast(argv); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); const int listenPort = portStr ? atoi(portStr) : INVALID_PORT; @@ -458,7 +458,7 @@ bool setupEssentials(int& argc, char** argv) { static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset"; bool suppressPrompt = cmdOptionExists(argc, const_cast(argv), SUPPRESS_SETTINGS_RESET); - bool previousSessionCrashed = CrashHandler::checkForResetSettings(suppressPrompt); + bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); @@ -563,11 +563,11 @@ const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true; const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false; const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false; -Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : +Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) : QApplication(argc, argv), _window(new MainWindow(desktop())), _sessionRunTimer(startupTimer), - _previousSessionCrashed(setupEssentials(argc, argv)), + _previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)), _undoStackScriptingInterface(&_undoStack), _entitySimulation(new PhysicalEntitySimulation()), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), diff --git a/interface/src/Application.h b/interface/src/Application.h index 5cf3580c09..d9dc3f389f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,7 +136,7 @@ public: static void initPlugins(const QStringList& arguments); static void shutdownPlugins(); - Application(int& argc, char** argv, QElapsedTimer& startup_time); + Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runningMarkerExisted); ~Application(); void postLambdaEvent(std::function f) override; diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index b254cd58de..8081dd3ffc 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -28,7 +28,7 @@ #include -bool CrashHandler::checkForResetSettings(bool suppressPrompt) { +bool CrashHandler::checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt) { Settings settings; settings.beginGroup("Developer"); QVariant displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions); @@ -39,9 +39,6 @@ bool CrashHandler::checkForResetSettings(bool suppressPrompt) { // If option does not exist in Interface.ini so assume default behavior. bool displaySettingsResetOnCrash = !displayCrashOptions.isValid() || displayCrashOptions.toBool(); - QFile runningMarkerFile(RunningMarker::getMarkerFilePath(RUNNING_MARKER_FILENAME)); - bool wasLikelyCrash = runningMarkerFile.exists(); - if (suppressPrompt) { return wasLikelyCrash; } diff --git a/interface/src/CrashHandler.h b/interface/src/CrashHandler.h index 308cac3411..da2e1575db 100644 --- a/interface/src/CrashHandler.h +++ b/interface/src/CrashHandler.h @@ -17,7 +17,7 @@ class CrashHandler { public: - static bool checkForResetSettings(bool suppressPrompt = false); + static bool checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt = false); private: enum Action { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 3430ffbd15..49517eb38e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -192,6 +192,7 @@ int main(int argc, const char* argv[]) { int exitCode; { RunningMarker runningMarker(nullptr, RUNNING_MARKER_FILENAME); + bool runningMarkerExisted = runningMarker.fileExists(); runningMarker.writeRunningMarkerFile(); bool noUpdater = parser.isSet(noUpdaterOption); @@ -202,7 +203,7 @@ int main(int argc, const char* argv[]) { SandboxUtils::runLocalSandbox(serverContentPath, true, RUNNING_MARKER_FILENAME, noUpdater); } - Application app(argc, const_cast(argv), startupTime); + Application app(argc, const_cast(argv), startupTime, runningMarkerExisted); // Now that the main event loop is setup, launch running marker thread runningMarker.startRunningMarker(); diff --git a/libraries/shared/src/RunningMarker.cpp b/libraries/shared/src/RunningMarker.cpp index f8aaee42df..0c1fd06df8 100644 --- a/libraries/shared/src/RunningMarker.cpp +++ b/libraries/shared/src/RunningMarker.cpp @@ -53,6 +53,11 @@ RunningMarker::~RunningMarker() { _runningMarkerThread->deleteLater(); } +bool RunningMarker::fileExists() const { + QFile runningMarkerFile(getFilePath()); + return runningMarkerFile.exists(); +} + void RunningMarker::writeRunningMarkerFile() { QFile runningMarkerFile(getFilePath()); @@ -69,7 +74,7 @@ void RunningMarker::deleteRunningMarkerFile() { } } -QString RunningMarker::getFilePath() { +QString RunningMarker::getFilePath() const { return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + _name; } diff --git a/libraries/shared/src/RunningMarker.h b/libraries/shared/src/RunningMarker.h index 1137dbf5fa..f9c8e72d37 100644 --- a/libraries/shared/src/RunningMarker.h +++ b/libraries/shared/src/RunningMarker.h @@ -25,9 +25,11 @@ public: void startRunningMarker(); - QString getFilePath(); + QString getFilePath() const; static QString getMarkerFilePath(QString name); + bool fileExists() const; + void writeRunningMarkerFile(); void deleteRunningMarkerFile(); From 0c4cd96bfddd85c2587f56821043635a46b169b0 Mon Sep 17 00:00:00 2001 From: volansystech Date: Wed, 24 May 2017 12:25:21 +0530 Subject: [PATCH 07/49] Initial Commit : Switch from HMD [Oculus Rift] mode to Desktop mode automatically when user removing Oculus Rift. --- interface/src/Application.cpp | 40 +++++++++++++++++++++++++++++++++++ interface/src/Application.h | 8 +++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae490c05e7..ced5e51565 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1338,6 +1338,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); + if (isOculusRiftPluginAvailable()){ + qCDebug(interfaceapp) << "Oculus Rift Plugin is available"; + QTimer *switchModeTimer = new QTimer(this); + connect(switchModeTimer, SIGNAL(timeout()), this, SLOT(switchmode())); + switchModeTimer->start(500); + } + auto glInfo = getGLContextData(); properties["gl_info"] = glInfo; properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemory()); @@ -6833,6 +6840,39 @@ void Application::updateDisplayMode() { Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } +bool Application::isOculusRiftPluginAvailable(){ + bool isOculusRiftPluginAvailable = false; + auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); + // Default to the first item on the list, in case none of the menu items match + DisplayPluginPointer defaultplugin = displayPlugins.at(0); + if (defaultplugin->isHmd() && defaultplugin->getName() == "Oculus Rift"){ + oculusRiftPlugin = defaultplugin; + return true; // No need to iterate again,so return + } + // Iterate to check If Oculus Rift Plugin is available + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { + QString pluginname = displayPlugin->getName(); + if (displayPlugin->isHmd() && pluginname == "Oculus Rift") { + oculusRiftPlugin = displayPlugin; + _isDisplayVisible = displayPlugin->isDisplayVisible(); + isOculusRiftPluginAvailable = true; + break; + } + } + return isOculusRiftPluginAvailable; +} + +void Application::switchmode(){ + bool isDisplayVisible = oculusRiftPlugin->isDisplayVisible(); + if (isDisplayVisible != _isDisplayVisible){ + if (isDisplayVisible == false && _isDisplayVisible == true){ + qCDebug(interfaceapp) << "switching from HMD to desktop mode"; + setActiveDisplayPlugin("Desktop"); + } + } + _isDisplayVisible = isDisplayVisible; // assign current status +} + mat4 Application::getEyeProjection(int eye) const { QMutexLocker viewLocker(&_viewMutex); if (isHMDMode()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index d9dc3f389f..c181e74c74 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -152,7 +152,7 @@ public: void paintGL(); void resizeGL(); - bool event(QEvent* event) override; + bool event(QEvent* event) override; bool eventFilter(QObject* object, QEvent* event) override; glm::uvec2 getCanvasSize() const; @@ -443,7 +443,7 @@ private slots: void addAssetToWorldErrorTimeout(); void handleSandboxStatus(QNetworkReply* reply); - + void switchmode(); private: static void initDisplay(); void init(); @@ -683,6 +683,10 @@ private: FileScriptingInterface* _fileDownload; AudioInjector* _snapshotSoundInjector { nullptr }; SharedSoundPointer _snapshotSound; + + bool isOculusRiftPluginAvailable(); + DisplayPluginPointer oculusRiftPlugin; + bool _isDisplayVisible; }; From ac55908e42984a27c91cd386609808f61073376b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 16:50:06 -0700 Subject: [PATCH 08/49] add additional information to stats/launch activities --- interface/src/Application.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd66a96879..253277b37f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -946,6 +946,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3; } + // add firstRun flag from settings to launch event + Setting::Handle firstRun { Settings::firstRun, true }; + properties["first_run"] = firstRun.get(); + UserActivityLogger::getInstance().logAction("launch", properties); // Tell our entity edit sender about our known jurisdictions @@ -1305,6 +1309,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(); properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond(); + properties["asset_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer); + auto nodeList = DependencyManager::get(); SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); @@ -1317,10 +1323,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["asset_ping"] = assetServerNode ? assetServerNode->getPingMs() : -1; properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1; + auto loadingRequests = ResourceCache::getLoadingRequests(); properties["active_downloads"] = loadingRequests.size(); properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); + properties["processing_resources"] = DependencyManager::get()->getStat("Processing").toInt(); + properties["pending_processing_resources"] = DependencyManager::get()->getStat("PendingProcessing").toInt(); + properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; auto myAvatar = getMyAvatar(); @@ -1335,6 +1345,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount; properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount; + NodeToOctreeSceneStats* octreeServerSceneStats = getOcteeSceneStats(); + unsigned long totalServerOctreeElements = 0; + for (NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) { + totalServerOctreeElements += i->second.getTotalElements(); + } + + properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount(); + properties["server_octree_elements"] = (qint64) totalServerOctreeElements; + properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); From 3743cd23b4fe6d74092d34ba3c62b1bb32b7f8fa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:20:24 -0700 Subject: [PATCH 09/49] add detailed download stats for file/http/atp --- interface/src/Application.cpp | 33 +++++++++++++++++-- .../networking/src/AssetResourceRequest.cpp | 22 +++++++++++-- .../networking/src/FileResourceRequest.cpp | 11 +++++++ .../networking/src/HTTPResourceRequest.cpp | 16 +++++++++ libraries/networking/src/ResourceRequest.h | 12 +++++++ 5 files changed, 90 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 253277b37f..08981ee6c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -111,6 +111,7 @@ #include #include #include +#include #include #include #include @@ -1328,8 +1329,36 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_downloads"] = loadingRequests.size(); properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); - properties["processing_resources"] = DependencyManager::get()->getStat("Processing").toInt(); - properties["pending_processing_resources"] = DependencyManager::get()->getStat("PendingProcessing").toInt(); + auto statTracker = DependencyManager::get(); + + properties["processing_resources"] = statTracker->getStat("Processing").toInt(); + properties["pending_processing_resources"] = statTracker->getStat("PendingProcessing").toInt(); + + properties["started_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt(); + properties["started_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt(); + properties["started_file_requests"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt(); + auto totalRequestsStarted = properties["started_atp_requests"].toInt() + + properties["started_http_requests"].toInt() + properties["started_file_requests"].toInt(); + properties["started_requests"] = totalRequestsStarted; + + properties["successful_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt(); + properties["successful_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt(); + properties["successful_file_requests"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt(); + auto totalRequestsSuccessful = properties["successful_atp_requests"].toInt() + + properties["successful_http_requests"].toInt() + properties["successful_file_requests"].toInt(); + properties["successful_requests"] = totalRequestsSuccessful; + + properties["failed_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt(); + properties["failed_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); + properties["failed_file_requests"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt(); + auto totalRequestsFailed = properties["failed_atp_requests"].toInt() + + properties["failed_http_requests"].toInt() + properties["failed_file_requests"].toInt(); + properties["failed_requests"] = totalRequestsFailed; + + properties["cache_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt(); + properties["cache_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); + auto totalRequestsCache = properties["cache_atp_requests"].toInt() + properties["cache_http_requests"].toInt(); + properties["cache_requests"] = totalRequestsCache; properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index a4d5d66923..d23d85d79e 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -13,12 +13,14 @@ #include +#include +#include +#include + #include "AssetClient.h" #include "AssetUtils.h" #include "MappingRequest.h" #include "NetworkLogging.h" -#include -#include static const int DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS = 5; @@ -48,6 +50,8 @@ bool AssetResourceRequest::urlIsAssetHash(const QUrl& url) { } void AssetResourceRequest::doSend() { + DependencyManager::get()->incrementStat(STAT_ATP_REQUEST_STARTED); + // We'll either have a hash or an ATP path to a file (that maps to a hash) if (urlIsAssetHash(_url)) { // We've detected that this is a hash - simply use AssetClient to request that asset @@ -100,6 +104,8 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { _state = Finished; emit finished(); + DependencyManager::get()->incrementStat(STAT_ATP_REQUEST_FAILED); + break; } } @@ -140,10 +146,22 @@ void AssetResourceRequest::requestHash(const AssetHash& hash) { _result = Error; break; } + + auto statTracker = DependencyManager::get(); _state = Finished; emit finished(); + if (_result == Success) { + statTracker->incrementStat(STAT_ATP_REQUEST_SUCCESS); + + if (loadedFromCache()) { + statTracker->incrementStat(STAT_ATP_REQUEST_CACHE); + } + } else { + statTracker->incrementStat(STAT_ATP_REQUEST_FAILED); + } + _assetRequest->deleteLater(); _assetRequest = nullptr; }); diff --git a/libraries/networking/src/FileResourceRequest.cpp b/libraries/networking/src/FileResourceRequest.cpp index 1e549e5fa3..d0e2721679 100644 --- a/libraries/networking/src/FileResourceRequest.cpp +++ b/libraries/networking/src/FileResourceRequest.cpp @@ -15,7 +15,12 @@ #include +#include + void FileResourceRequest::doSend() { + auto statTracker = DependencyManager::get(); + statTracker->incrementStat(STAT_FILE_REQUEST_STARTED); + QString filename = _url.toLocalFile(); // sometimes on windows, we see the toLocalFile() return null, @@ -60,4 +65,10 @@ void FileResourceRequest::doSend() { _state = Finished; emit finished(); + + if (_result == ResourceRequest::Success) { + statTracker->incrementStat(STAT_FILE_REQUEST_SUCCESS); + } else { + statTracker->incrementStat(STAT_FILE_REQUEST_FAILED); + } } diff --git a/libraries/networking/src/HTTPResourceRequest.cpp b/libraries/networking/src/HTTPResourceRequest.cpp index c6a4b93e51..266ea429a0 100644 --- a/libraries/networking/src/HTTPResourceRequest.cpp +++ b/libraries/networking/src/HTTPResourceRequest.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "NetworkAccessManager.h" #include "NetworkLogging.h" @@ -49,6 +50,8 @@ void HTTPResourceRequest::cleanupTimer() { } void HTTPResourceRequest::doSend() { + DependencyManager::get()->incrementStat(STAT_HTTP_REQUEST_STARTED); + QNetworkRequest networkRequest(_url); networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); @@ -178,6 +181,17 @@ void HTTPResourceRequest::onRequestFinished() { _state = Finished; emit finished(); + + auto statTracker = DependencyManager::get(); + if (_result == Success) { + statTracker->incrementStat(STAT_HTTP_REQUEST_SUCCESS); + + if (loadedFromCache()) { + statTracker->incrementStat(STAT_HTTP_REQUEST_CACHE); + } + } else { + statTracker->incrementStat(STAT_HTTP_REQUEST_FAILED); + } } void HTTPResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { @@ -202,4 +216,6 @@ void HTTPResourceRequest::onTimeout() { _result = Timeout; _state = Finished; emit finished(); + + DependencyManager::get()->incrementStat(STAT_HTTP_REQUEST_FAILED); } diff --git a/libraries/networking/src/ResourceRequest.h b/libraries/networking/src/ResourceRequest.h index ef40cb3455..452380f2f3 100644 --- a/libraries/networking/src/ResourceRequest.h +++ b/libraries/networking/src/ResourceRequest.h @@ -19,6 +19,18 @@ #include "ByteRange.h" +const QString STAT_ATP_REQUEST_STARTED = "StartedATPRequest"; +const QString STAT_HTTP_REQUEST_STARTED = "StartedHTTPRequest"; +const QString STAT_FILE_REQUEST_STARTED = "StartedFileRequest"; +const QString STAT_ATP_REQUEST_SUCCESS = "SuccessfulATPRequest"; +const QString STAT_HTTP_REQUEST_SUCCESS = "SuccessfulHTTPRequest"; +const QString STAT_FILE_REQUEST_SUCCESS = "SuccessfulFileRequest"; +const QString STAT_ATP_REQUEST_FAILED = "FailedATPRequest"; +const QString STAT_HTTP_REQUEST_FAILED = "FailedHTTPRequest"; +const QString STAT_FILE_REQUEST_FAILED = "FailedFileRequest"; +const QString STAT_ATP_REQUEST_CACHE = "CacheATPRequest"; +const QString STAT_HTTP_REQUEST_CACHE = "CacheHTTPRequest"; + class ResourceRequest : public QObject { Q_OBJECT public: From 48c4db1ca4a6bfcd687a76caaa66c6194d055142 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:36:21 -0700 Subject: [PATCH 10/49] nest the download stats so they are cleaner --- interface/src/Application.cpp | 55 +++++++++++-------- .../networking/src/AssetResourceRequest.cpp | 10 +++- libraries/networking/src/ResourceRequest.h | 3 + 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 08981ee6c1..4d18c26296 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1324,7 +1324,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["asset_ping"] = assetServerNode ? assetServerNode->getPingMs() : -1; properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1; - auto loadingRequests = ResourceCache::getLoadingRequests(); properties["active_downloads"] = loadingRequests.size(); properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); @@ -1334,31 +1333,41 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["processing_resources"] = statTracker->getStat("Processing").toInt(); properties["pending_processing_resources"] = statTracker->getStat("PendingProcessing").toInt(); - properties["started_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt(); - properties["started_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt(); - properties["started_file_requests"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt(); - auto totalRequestsStarted = properties["started_atp_requests"].toInt() - + properties["started_http_requests"].toInt() + properties["started_file_requests"].toInt(); - properties["started_requests"] = totalRequestsStarted; + QJsonObject startedRequests; + startedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt(); + startedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt(); + startedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt(); + startedRequests["total"] = startedRequests["atp"].toInt() + startedRequests["http"].toInt() + + startedRequests["file"].toInt(); + properties["started_requests"] = startedRequests; - properties["successful_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt(); - properties["successful_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt(); - properties["successful_file_requests"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt(); - auto totalRequestsSuccessful = properties["successful_atp_requests"].toInt() - + properties["successful_http_requests"].toInt() + properties["successful_file_requests"].toInt(); - properties["successful_requests"] = totalRequestsSuccessful; + QJsonObject successfulRequests; + successfulRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt(); + successfulRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt(); + successfulRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt(); + successfulRequests["total"] = successfulRequests["atp"].toInt() + successfulRequests["http"].toInt() + + successfulRequests["file"].toInt(); + properties["successful_requests"] = successfulRequests; - properties["failed_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt(); - properties["failed_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); - properties["failed_file_requests"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt(); - auto totalRequestsFailed = properties["failed_atp_requests"].toInt() - + properties["failed_http_requests"].toInt() + properties["failed_file_requests"].toInt(); - properties["failed_requests"] = totalRequestsFailed; + QJsonObject failedRequests; + failedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt(); + failedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); + failedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt(); + failedRequests["total"] = failedRequests["atp"].toInt() + failedRequests["http"].toInt() + + failedRequests["file"].toInt(); + properties["failed_requests"] = failedRequests; - properties["cache_atp_requests"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt(); - properties["cache_http_requests"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); - auto totalRequestsCache = properties["cache_atp_requests"].toInt() + properties["cache_http_requests"].toInt(); - properties["cache_requests"] = totalRequestsCache; + QJsonObject cacheRequests; + cacheRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt(); + cacheRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); + cacheRequests["total"] = cacheRequests["atp"].toInt() + cacheRequests["http"].toInt(); + properties["cache_requests"] = cacheRequests; + + QJsonObject atpMappingRequests; + atpMappingRequests["started"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_STARTED).toInt(); + atpMappingRequests["failed"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_FAILED).toInt(); + atpMappingRequests["successful"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_SUCCESS).toInt(); + properties["atp_mapping_requests"] = atpMappingRequests; properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index d23d85d79e..fc83fb6cae 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -69,11 +69,14 @@ void AssetResourceRequest::doSend() { } void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { + auto statTracker = DependencyManager::get(); + statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_STARTED); + auto assetClient = DependencyManager::get(); _assetMappingRequest = assetClient->createGetMappingRequest(path); // make sure we'll hear about the result of the get mapping request - connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path](GetMappingRequest* request){ + connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path, statTracker](GetMappingRequest* request){ Q_ASSERT(_state == InProgress); Q_ASSERT(request == _assetMappingRequest); @@ -84,6 +87,8 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { requestHash(request->getHash()); + statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_SUCCESS); + break; default: { switch (request->getError()) { @@ -104,7 +109,8 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { _state = Finished; emit finished(); - DependencyManager::get()->incrementStat(STAT_ATP_REQUEST_FAILED); + statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_FAILED); + statTracker->incrementStat(STAT_ATP_REQUEST_FAILED); break; } diff --git a/libraries/networking/src/ResourceRequest.h b/libraries/networking/src/ResourceRequest.h index 452380f2f3..39bcb3fe93 100644 --- a/libraries/networking/src/ResourceRequest.h +++ b/libraries/networking/src/ResourceRequest.h @@ -30,6 +30,9 @@ const QString STAT_HTTP_REQUEST_FAILED = "FailedHTTPRequest"; const QString STAT_FILE_REQUEST_FAILED = "FailedFileRequest"; const QString STAT_ATP_REQUEST_CACHE = "CacheATPRequest"; const QString STAT_HTTP_REQUEST_CACHE = "CacheHTTPRequest"; +const QString STAT_ATP_MAPPING_REQUEST_STARTED = "StartedATPMappingRequest"; +const QString STAT_ATP_MAPPING_REQUEST_FAILED = "FailedATPMappingRequest"; +const QString STAT_ATP_MAPPING_REQUEST_SUCCESS = "SuccessfulATPMappingRequest"; class ResourceRequest : public QObject { Q_OBJECT From 5e61f20df8d5c59cf02108579040245c51654805 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:37:42 -0700 Subject: [PATCH 11/49] add more details about pending downloads --- interface/src/Application.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4d18c26296..28d183a18b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1325,8 +1325,20 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1; auto loadingRequests = ResourceCache::getLoadingRequests(); + + QJsonArray loadingRequestsStats; + for (const auto& request : loadingRequests) { + QJsonObject requestStats; + requestStats["filename"] = request->getURL().fileName(); + requestStats["received"] = request->getBytesReceived(); + requestStats["total"] = request->getBytesTotal(); + requestStats["attempts"] = (int)request->getDownloadAttempts(); + loadingRequestsStats.append(requestStats); + } + properties["active_downloads"] = loadingRequests.size(); properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); + properties["active_downloads_details"] = loadingRequestsStats; auto statTracker = DependencyManager::get(); From c37fd335e1d6560692fdc1a3bfd0db642751cf38 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:41:52 -0700 Subject: [PATCH 12/49] track the number of local socket changes --- interface/src/Application.cpp | 2 ++ libraries/networking/src/LimitedNodeList.cpp | 4 ++-- libraries/networking/src/LimitedNodeList.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 28d183a18b..1f5eebee84 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1429,6 +1429,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo lastLeftHandPose = leftHandPose; lastRightHandPose = rightHandPose; + properties["local_socket_changes"] = DependencyManager::get()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt(); + UserActivityLogger::getInstance().logAction("stats", properties); }); sendStatsTimer->start(); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 8feb695c79..cba1e664ab 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "AccountManager.h" @@ -37,7 +38,6 @@ #include "HifiSockAddr.h" #include "NetworkLogging.h" #include "udt/Packet.h" -#include static Setting::Handle LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0); @@ -1044,10 +1044,10 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { qCInfo(networking) << "Local socket is" << sockAddr; } else { qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr; + DependencyManager::get()->incrementStat(LOCAL_SOCKET_CHANGE_STAT); } _localSockAddr = sockAddr; - emit localSockAddrChanged(_localSockAddr); } } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 3eb898463a..056a4d16cf 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -66,6 +66,8 @@ const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::Lo const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username"; +const QString LOCAL_SOCKET_CHANGE_STAT = "LocalSocketChanges"; + using namespace tbb; typedef std::pair UUIDNodePair; typedef concurrent_unordered_map NodeHash; From fefb34512d399fa2f164ab37ebe82ed205fc94c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:44:09 -0700 Subject: [PATCH 13/49] change asset inbound key to atp --- 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 1f5eebee84..e73d46185e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1310,7 +1310,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(); properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond(); - properties["asset_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer); + properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer); auto nodeList = DependencyManager::get(); SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer); From c671817fa3985967f9bc3dfb310e85ccc74158d0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:47:40 -0700 Subject: [PATCH 14/49] fix cache http request count in stats --- 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 e73d46185e..0b05efbadb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1371,7 +1371,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QJsonObject cacheRequests; cacheRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt(); - cacheRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); + cacheRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_CACHE).toInt(); cacheRequests["total"] = cacheRequests["atp"].toInt() + cacheRequests["http"].toInt(); properties["cache_requests"] = cacheRequests; From a04fc41e17587853a3d6ebcf2e7a22238911f474 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 17:54:07 -0700 Subject: [PATCH 15/49] don't capture strong pointer to stat tracker --- libraries/networking/src/AssetResourceRequest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index fc83fb6cae..c0150fd3ed 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -76,7 +76,9 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { _assetMappingRequest = assetClient->createGetMappingRequest(path); // make sure we'll hear about the result of the get mapping request - connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path, statTracker](GetMappingRequest* request){ + connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path](GetMappingRequest* request){ + auto statTracker = DependencyManager::get(); + Q_ASSERT(_state == InProgress); Q_ASSERT(request == _assetMappingRequest); From 50285005beead11349656f0ca380ad98b144319d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 18:35:57 -0700 Subject: [PATCH 16/49] add machine fingerprint to the launch event --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b05efbadb..2fe0af8556 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -951,6 +952,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo Setting::Handle firstRun { Settings::firstRun, true }; properties["first_run"] = firstRun.get(); + // add the user's machine ID to the launch event + properties["machine_fingerprint"] = FingerprintUtils::getMachineFingerprint().toString(); + UserActivityLogger::getInstance().logAction("launch", properties); // Tell our entity edit sender about our known jurisdictions From f897f3f0902c4cef7f04357a26db448b26677f7f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 19:08:25 -0700 Subject: [PATCH 17/49] send machine fingerprint as uuid without curly braces --- 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 2fe0af8556..abccc5197d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -953,7 +953,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["first_run"] = firstRun.get(); // add the user's machine ID to the launch event - properties["machine_fingerprint"] = FingerprintUtils::getMachineFingerprint().toString(); + properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); UserActivityLogger::getInstance().logAction("launch", properties); From d7b3ee9bcb06fbf3df764918e1629e9bbb10327b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 24 May 2017 19:15:10 -0700 Subject: [PATCH 18/49] check for cached ATP assets in right place --- libraries/networking/src/AssetRequest.cpp | 9 +++++++-- libraries/networking/src/AssetRequest.h | 3 +++ libraries/networking/src/AssetResourceRequest.cpp | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 920c7ae036..00fa3d9f2f 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -15,11 +15,13 @@ #include +#include +#include + #include "AssetClient.h" #include "NetworkLogging.h" #include "NodeList.h" #include "ResourceCache.h" -#include static int requestID = 0; @@ -62,9 +64,12 @@ void AssetRequest::start() { _data = loadFromCache(getUrl()); if (!_data.isNull()) { _error = NoError; - + + _loadedFromCache = true; + _state = Finished; emit finished(this); + return; } diff --git a/libraries/networking/src/AssetRequest.h b/libraries/networking/src/AssetRequest.h index b808ae0ca6..df5cf80ecd 100644 --- a/libraries/networking/src/AssetRequest.h +++ b/libraries/networking/src/AssetRequest.h @@ -52,6 +52,8 @@ public: QUrl getUrl() const { return ::getATPUrl(_hash); } QString getHash() const { return _hash; } + bool loadedFromCache() const { return _loadedFromCache; } + signals: void finished(AssetRequest* thisRequest); void progress(qint64 totalReceived, qint64 total); @@ -66,6 +68,7 @@ private: int _numPendingRequests { 0 }; MessageID _assetRequestID { INVALID_MESSAGE_ID }; const ByteRange _byteRange; + bool _loadedFromCache { false }; }; #endif diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index c0150fd3ed..f4a3b20fd5 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -156,7 +156,11 @@ void AssetResourceRequest::requestHash(const AssetHash& hash) { } auto statTracker = DependencyManager::get(); - + + if (_assetRequest->loadedFromCache()) { + _loadedFromCache = true; + } + _state = Finished; emit finished(); From 1f24e38585cca9d1d7919e803b4806569af34570 Mon Sep 17 00:00:00 2001 From: volansystech Date: Wed, 24 May 2017 21:00:40 +0530 Subject: [PATCH 19/49] Initial Commit: Switching from Desktop mode to HMD [Oculus Rift] mode automatically when the user wear Oculus Rift. --- interface/src/Application.cpp | 54 ++++++++++++++----- interface/src/Application.h | 10 ++-- .../display-plugins/OpenGLDisplayPlugin.cpp | 15 +++++- .../src/display-plugins/OpenGLDisplayPlugin.h | 6 +++ libraries/plugins/src/plugins/Plugin.h | 13 +++++ .../oculus/src/OculusBaseDisplayPlugin.cpp | 11 ++++ plugins/oculus/src/OculusBaseDisplayPlugin.h | 2 + 7 files changed, 92 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ced5e51565..99c2b2febf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1338,11 +1338,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); - if (isOculusRiftPluginAvailable()){ - qCDebug(interfaceapp) << "Oculus Rift Plugin is available"; - QTimer *switchModeTimer = new QTimer(this); - connect(switchModeTimer, SIGNAL(timeout()), this, SLOT(switchmode())); - switchModeTimer->start(500); + if (isOculusRiftPluginAvailable()) { + // If Oculus Rift Plugin is Available,And Current Display Plugin is not Oculus Rift + // then startOculusRiftStandBySession to listen Oculus HMD Mounted status. + if (getActiveDisplayPlugin()->getName() != "Oculus Rift" && + !oculusRiftPlugin->isFakeSessionActive()) { + startOculusRiftStandBySession(); + } + // Poll periodically to check whether the user has worn Oculus HMD or not. And switch mode + // accordingly. If the user wear HMD, switch to VR mode, if remove switch to Desktop mode. + QTimer *switchDisplayModeTimer = new QTimer(this); + connect(switchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayModeForOculus())); + switchDisplayModeTimer->start(500); } auto glInfo = getGLContextData(); @@ -1574,7 +1581,9 @@ void Application::aboutToQuit() { } getActiveDisplayPlugin()->deactivate(); - + if (oculusRiftPlugin && oculusRiftPlugin->isFakeSessionActive()){ + oculusRiftPlugin->endStandBySession(); + } // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); @@ -6845,7 +6854,7 @@ bool Application::isOculusRiftPluginAvailable(){ auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); // Default to the first item on the list, in case none of the menu items match DisplayPluginPointer defaultplugin = displayPlugins.at(0); - if (defaultplugin->isHmd() && defaultplugin->getName() == "Oculus Rift"){ + if (defaultplugin->isHmd() && defaultplugin->getName() == "Oculus Rift") { oculusRiftPlugin = defaultplugin; return true; // No need to iterate again,so return } @@ -6854,7 +6863,7 @@ bool Application::isOculusRiftPluginAvailable(){ QString pluginname = displayPlugin->getName(); if (displayPlugin->isHmd() && pluginname == "Oculus Rift") { oculusRiftPlugin = displayPlugin; - _isDisplayVisible = displayPlugin->isDisplayVisible(); + _oculusHMDMountedStatus = displayPlugin->isDisplayVisible(); isOculusRiftPluginAvailable = true; break; } @@ -6862,15 +6871,32 @@ bool Application::isOculusRiftPluginAvailable(){ return isOculusRiftPluginAvailable; } -void Application::switchmode(){ - bool isDisplayVisible = oculusRiftPlugin->isDisplayVisible(); - if (isDisplayVisible != _isDisplayVisible){ - if (isDisplayVisible == false && _isDisplayVisible == true){ - qCDebug(interfaceapp) << "switching from HMD to desktop mode"; +void Application::switchDisplayModeForOculus(){ + bool currenthmdMountedStatus = oculusRiftPlugin->isDisplayVisible(); + if (currenthmdMountedStatus != _oculusHMDMountedStatus){ + // Switch to respective mode as soon as currenthmdMountedStatus changes + if (currenthmdMountedStatus == false && _oculusHMDMountedStatus == true) { + qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; setActiveDisplayPlugin("Desktop"); + startOculusRiftStandBySession(); + } + if (currenthmdMountedStatus == true && _oculusHMDMountedStatus == false) { + qCDebug(interfaceapp) << "Switching from Desktop to HMD mode"; + endOculusRiftStandBySession(); + setActiveDisplayPlugin("Oculus Rift"); } } - _isDisplayVisible = isDisplayVisible; // assign current status + _oculusHMDMountedStatus = currenthmdMountedStatus; +} + +bool Application::startOculusRiftStandBySession(){ + bool isStandBySessionStarted = oculusRiftPlugin->startStandBySession(); + qCDebug(interfaceapp) << "startOculusRiftStandBySession: " << isStandBySessionStarted; + return isStandBySessionStarted; +} + +void Application::endOculusRiftStandBySession(){ + oculusRiftPlugin->endStandBySession(); } mat4 Application::getEyeProjection(int eye) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index c181e74c74..a6ac244dc8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -443,7 +443,7 @@ private slots: void addAssetToWorldErrorTimeout(); void handleSandboxStatus(QNetworkReply* reply); - void switchmode(); + void switchDisplayModeForOculus(); private: static void initDisplay(); void init(); @@ -684,9 +684,13 @@ private: AudioInjector* _snapshotSoundInjector { nullptr }; SharedSoundPointer _snapshotSound; - bool isOculusRiftPluginAvailable(); + DisplayPluginPointer oculusRiftPlugin; - bool _isDisplayVisible; + + bool isOculusRiftPluginAvailable(); + bool _oculusHMDMountedStatus; // Keep track of HMD Mounted Flag + bool startOculusRiftStandBySession(); + void endOculusRiftStandBySession(); }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 306db98b35..639acc7739 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -315,8 +315,7 @@ bool OpenGLDisplayPlugin::activate() { if (isHmd() && (getHmdScreen() >= 0)) { _container->showDisplayPluginsTools(); } - - return Parent::activate(); + return Parent::activate(); } void OpenGLDisplayPlugin::deactivate() { @@ -339,6 +338,18 @@ void OpenGLDisplayPlugin::deactivate() { Parent::deactivate(); } +bool OpenGLDisplayPlugin::startStandBySession() { + if (!activateStandBySession()) { + return false; + } + return Parent::startStandBySession(); +} + +void OpenGLDisplayPlugin::endStandBySession() { + deactivateStandBySession(); + return Parent::endStandBySession(); +} + void OpenGLDisplayPlugin::customizeContext() { auto presentThread = DependencyManager::get(); Q_ASSERT(thread() == presentThread->thread()); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index e1eea5de6c..ecde3b3c93 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -42,6 +42,8 @@ public: // between the main thread and the presentation thread bool activate() override final; void deactivate() override final; + bool startStandBySession() override final; + void endStandBySession() override final; bool eventFilter(QObject* receiver, QEvent* event) override; bool isDisplayVisible() const override { return true; } @@ -99,6 +101,10 @@ protected: // Returns true on successful activation virtual bool internalActivate() { return true; } virtual void internalDeactivate() {} + + // Returns true on successful activation of standby session + virtual bool activateStandBySession() { return true; } + virtual void deactivateStandBySession() {} // Plugin specific functionality to send the composed scene to the output window or device virtual void internalPresent(); diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index 15588fafa4..74f04fff18 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -53,6 +53,18 @@ public: virtual bool isActive() { return _active; } + virtual bool startStandBySession(){ + _standbysessionactive = true; + return _standbysessionactive; + } + + virtual void endStandBySession(){ + _standbysessionactive = false; + } + + virtual bool isFakeSessionActive() { + return _standbysessionactive; + } /** * Called by the application during it's idle phase. If the plugin needs to do @@ -73,6 +85,7 @@ signals: protected: bool _active { false }; + bool _standbysessionactive { false }; PluginContainer* _container { nullptr }; static const char* UNKNOWN_PLUGIN_ID; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 26906ef2fb..28e30e0d21 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -127,6 +127,17 @@ void OculusBaseDisplayPlugin::internalDeactivate() { _session = nullptr; } +bool OculusBaseDisplayPlugin::activateStandBySession() { + _session = acquireOculusSession(); + if (!_session) { + return false; + } + return true; +} +void OculusBaseDisplayPlugin::deactivateStandBySession() { + releaseOculusSession(); + _session = nullptr; +} void OculusBaseDisplayPlugin::updatePresentPose() { //mat4 sensorResetMat; //_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index e5dc75095d..79085f817b 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -33,6 +33,8 @@ protected: void uncustomizeContext() override; bool internalActivate() override; void internalDeactivate() override; + bool activateStandBySession() override; + void deactivateStandBySession() override; void updatePresentPose() override; protected: From a2851b5bcbe9db8147348e5d54543a666e2b690b Mon Sep 17 00:00:00 2001 From: volansystech Date: Thu, 25 May 2017 18:32:46 +0530 Subject: [PATCH 20/49] Put proper comments and indentation. --- interface/src/Application.cpp | 22 +++++++++---------- interface/src/Application.h | 5 ++--- .../display-plugins/OpenGLDisplayPlugin.cpp | 2 +- libraries/plugins/src/plugins/Plugin.h | 16 +++++++------- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fda9b7b8f9..a40f31a8bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1339,14 +1339,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["using_hmd"] = isHMDMode(); if (isOculusRiftPluginAvailable()) { - // If Oculus Rift Plugin is Available,And Current Display Plugin is not Oculus Rift + // If Oculus Rift Plugin is available and current display plugin is not Oculus Rift // then startOculusRiftStandBySession to listen Oculus HMD Mounted status. if (getActiveDisplayPlugin()->getName() != "Oculus Rift" && - !oculusRiftPlugin->isFakeSessionActive()) { + !oculusRiftPlugin->isStandBySessionActive()) { startOculusRiftStandBySession(); } - // Poll periodically to check whether the user has worn Oculus HMD or not. And switch mode - // accordingly. If the user wear HMD, switch to VR mode, if remove switch to Desktop mode. + // Poll periodically to check whether the user has worn Oculus HMD or not. And switch Display mode accordingly. + // If the user wear Oculus HMD then switch to VR mode. If the user removes Oculus HMD then switch to Desktop mode. QTimer *switchDisplayModeTimer = new QTimer(this); connect(switchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayModeForOculus())); switchDisplayModeTimer->start(500); @@ -1581,7 +1581,7 @@ void Application::aboutToQuit() { } getActiveDisplayPlugin()->deactivate(); - if (oculusRiftPlugin && oculusRiftPlugin->isFakeSessionActive()){ + if (oculusRiftPlugin && oculusRiftPlugin->isStandBySessionActive()) { oculusRiftPlugin->endStandBySession(); } // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. @@ -6846,14 +6846,14 @@ void Application::updateDisplayMode() { Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } -bool Application::isOculusRiftPluginAvailable(){ +bool Application::isOculusRiftPluginAvailable() { bool isOculusRiftPluginAvailable = false; auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); // Default to the first item on the list, in case none of the menu items match DisplayPluginPointer defaultplugin = displayPlugins.at(0); if (defaultplugin->isHmd() && defaultplugin->getName() == "Oculus Rift") { oculusRiftPlugin = defaultplugin; - return true; // No need to iterate again,so return + return true; } // Iterate to check If Oculus Rift Plugin is available foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { @@ -6868,9 +6868,9 @@ bool Application::isOculusRiftPluginAvailable(){ return isOculusRiftPluginAvailable; } -void Application::switchDisplayModeForOculus(){ +void Application::switchDisplayModeForOculus() { bool currenthmdMountedStatus = oculusRiftPlugin->isDisplayVisible(); - if (currenthmdMountedStatus != _oculusHMDMountedStatus){ + if (currenthmdMountedStatus != _oculusHMDMountedStatus) { // Switch to respective mode as soon as currenthmdMountedStatus changes if (currenthmdMountedStatus == false && _oculusHMDMountedStatus == true) { qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; @@ -6886,13 +6886,13 @@ void Application::switchDisplayModeForOculus(){ _oculusHMDMountedStatus = currenthmdMountedStatus; } -bool Application::startOculusRiftStandBySession(){ +bool Application::startOculusRiftStandBySession() { bool isStandBySessionStarted = oculusRiftPlugin->startStandBySession(); qCDebug(interfaceapp) << "startOculusRiftStandBySession: " << isStandBySessionStarted; return isStandBySessionStarted; } -void Application::endOculusRiftStandBySession(){ +void Application::endOculusRiftStandBySession() { oculusRiftPlugin->endStandBySession(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 6b172cdb9e..112b650160 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -152,7 +152,7 @@ public: void paintGL(); void resizeGL(); - bool event(QEvent* event) override; + bool event(QEvent* event) override; bool eventFilter(QObject* object, QEvent* event) override; glm::uvec2 getCanvasSize() const; @@ -685,9 +685,8 @@ private: DisplayPluginPointer oculusRiftPlugin; - bool isOculusRiftPluginAvailable(); - bool _oculusHMDMountedStatus; // Keep track of HMD Mounted Flag + bool _oculusHMDMountedStatus; // Keep track of Oculus Rift HMDMounted Flag bool startOculusRiftStandBySession(); void endOculusRiftStandBySession(); }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 96d3d8114c..cebe844b84 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -315,7 +315,7 @@ bool OpenGLDisplayPlugin::activate() { if (isHmd() && (getHmdScreen() >= 0)) { _container->showDisplayPluginsTools(); } - return Parent::activate(); + return Parent::activate(); } void OpenGLDisplayPlugin::deactivate() { diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index 74f04fff18..045a9eee15 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -53,17 +53,17 @@ public: virtual bool isActive() { return _active; } - virtual bool startStandBySession(){ - _standbysessionactive = true; - return _standbysessionactive; + virtual bool startStandBySession() { + _standbysessionstatus = true; + return _standbysessionstatus; } - virtual void endStandBySession(){ - _standbysessionactive = false; + virtual void endStandBySession() { + _standbysessionstatus = false; } - virtual bool isFakeSessionActive() { - return _standbysessionactive; + virtual bool isStandBySessionActive() { + return _standbysessionstatus; } /** @@ -85,7 +85,7 @@ signals: protected: bool _active { false }; - bool _standbysessionactive { false }; + bool _standbysessionstatus { false }; PluginContainer* _container { nullptr }; static const char* UNKNOWN_PLUGIN_ID; From 64191ee20ac4eac47943232c961ff50fb8eabe64 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 23 May 2017 10:11:16 -0700 Subject: [PATCH 21/49] Make the changes - big thanks to Andrew! --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 9 ++++++--- libraries/entities/src/EntityItemProperties.cpp | 7 ++++++- libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityScriptingInterface.cpp | 10 ++++++---- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 09308baabb..d62181c651 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1091,15 +1091,18 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // trigger scripted collision sounds and events for locally owned objects EntityItemPointer entityA = entityTree->findEntityByEntityItemID(idA); - if ((bool)entityA && myNodeID == entityA->getSimulatorID()) { + EntityItemPointer entityB = entityTree->findEntityByEntityItemID(idB); + QUuid entityASimulatorID = entityA->getSimulatorID(); + QUuid entityBSimulatorID = entityB->getSimulatorID(); + if ((bool)entityA && (myNodeID == entityASimulatorID || ((bool)entityB && myNodeID == entityBSimulatorID && entityASimulatorID.isNull()))) { playEntityCollisionSound(entityA, collision); emit collisionWithEntity(idA, idB, collision); if (_entitiesScriptEngine) { _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); } } - EntityItemPointer entityB = entityTree->findEntityByEntityItemID(idB); - if ((bool)entityB && myNodeID == entityB->getSimulatorID()) { + + if ((bool)entityB && (myNodeID == entityBSimulatorID || ((bool)entityA && myNodeID == entityASimulatorID && entityBSimulatorID.isNull()))) { playEntityCollisionSound(entityB, collision); // since we're swapping A and B we need to send the inverted collision Collision invertedCollision(collision); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1ed020e592..4595ebf70d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1824,10 +1824,15 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged; } +bool EntityItemProperties::hasDynamicPhysicsChanges() const { + return _dynamicChanged || _velocityChanged || _angularVelocityChanged || _accelerationChanged; +} + bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged; + _compoundShapeURLChanged || _collisionlessChanged || _collisionMaskChanged || + _rotationChanged || _positionChanged; } void EntityItemProperties::clearSimulationOwner() { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 590298e102..697c634c67 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -274,6 +274,7 @@ public: void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; + bool hasDynamicPhysicsChanges() const; bool hasMiscPhysicsChanges() const; void clearSimulationOwner(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index b184d648da..367343cb60 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -414,15 +414,17 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& entityFound = true; // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); - bool hasTerseUpdateChanges = properties.hasTerseUpdateChanges(); - bool hasPhysicsChanges = properties.hasMiscPhysicsChanges() || hasTerseUpdateChanges; - if (_bidOnSimulationOwnership && hasPhysicsChanges) { + bool hasMiscPhysicsChanges = properties.hasMiscPhysicsChanges(); + bool hasDynamicsChanges = properties.hasDynamicPhysicsChanges(); + // _bidOnSimulationOwnership is set per-instance of the scripting interface. + // It essentially corresponds to "Am I an AC or an Interface client?" - ACs will never bid. + if ((_bidOnSimulationOwnership && ((hasMiscPhysicsChanges && entity->isMoving()) || hasDynamicsChanges))) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); if (entity->getSimulatorID() == myNodeID) { // we think we already own the simulation, so make sure to send ALL TerseUpdate properties - if (hasTerseUpdateChanges) { + if (properties.hasTerseUpdateChanges()) { entity->getAllTerseUpdateProperties(properties); } // TODO: if we knew that ONLY TerseUpdate properties have changed in properties AND the object From 827daade1b140c7dbfc142c6116a2fc2d931359e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 23 May 2017 12:50:43 -0700 Subject: [PATCH 22/49] Make this PR a protocol change --- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index f88015a4e4..0dbbcd771f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -114,7 +114,8 @@ public: EntityServerScriptLog, AdjustAvatarSorting, OctreeFileReplacement, - LAST_PACKET_TYPE = OctreeFileReplacement + SimulationBiddingChanges, + LAST_PACKET_TYPE = SimulationBiddingChanges }; }; From 8dec066c2bba98b8d02b88afa057c0c22a97ccfa Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 23 May 2017 14:41:02 -0700 Subject: [PATCH 23/49] Revert 'dynamicChanged' to be a 'misc' physics property --- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4595ebf70d..fa4df72387 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1825,13 +1825,13 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { } bool EntityItemProperties::hasDynamicPhysicsChanges() const { - return _dynamicChanged || _velocityChanged || _angularVelocityChanged || _accelerationChanged; + return _velocityChanged || _angularVelocityChanged || _accelerationChanged; } bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _collisionlessChanged || _collisionMaskChanged || + _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged || _rotationChanged || _positionChanged; } From ebe6ce9c8d3640e7e357755fa11bde766a6b95cb Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 24 May 2017 10:16:51 -0700 Subject: [PATCH 24/49] Committing checkpoint changes, then testing --- .../src/EntityTreeRenderer.cpp | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index d62181c651..7b2333ade9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1092,24 +1092,29 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // trigger scripted collision sounds and events for locally owned objects EntityItemPointer entityA = entityTree->findEntityByEntityItemID(idA); EntityItemPointer entityB = entityTree->findEntityByEntityItemID(idB); - QUuid entityASimulatorID = entityA->getSimulatorID(); - QUuid entityBSimulatorID = entityB->getSimulatorID(); - if ((bool)entityA && (myNodeID == entityASimulatorID || ((bool)entityB && myNodeID == entityBSimulatorID && entityASimulatorID.isNull()))) { - playEntityCollisionSound(entityA, collision); - emit collisionWithEntity(idA, idB, collision); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); - } - } + if ((bool)entityA && (bool)entityB) { + QUuid entityASimulatorID = entityA->getSimulatorID(); + QUuid entityBSimulatorID = entityB->getSimulatorID(); + bool entityAIsStatic = !entityA->getDynamic() && !entityA->isMoving(); + bool entityBIsStatic = !entityB->getDynamic() && !entityB->isMoving(); - if ((bool)entityB && (myNodeID == entityBSimulatorID || ((bool)entityA && myNodeID == entityASimulatorID && entityBSimulatorID.isNull()))) { - playEntityCollisionSound(entityB, collision); - // since we're swapping A and B we need to send the inverted collision - Collision invertedCollision(collision); - invertedCollision.invert(); - emit collisionWithEntity(idB, idA, invertedCollision); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(idB, "collisionWithEntity", idA, invertedCollision); + if (myNodeID == entityASimulatorID || (myNodeID == entityBSimulatorID && entityAIsStatic)) { + playEntityCollisionSound(entityA, collision); + emit collisionWithEntity(idA, idB, collision); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); + } + } + + if (myNodeID == entityBSimulatorID || (myNodeID == entityASimulatorID && entityBIsStatic)) { + playEntityCollisionSound(entityB, collision); + // since we're swapping A and B we need to send the inverted collision + Collision invertedCollision(collision); + invertedCollision.invert(); + emit collisionWithEntity(idB, idA, invertedCollision); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(idB, "collisionWithEntity", idA, invertedCollision); + } } } } From 3ec73cc5e1ffe2b7a5cd8c2cbcb81d5159322cf3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 24 May 2017 11:17:03 -0700 Subject: [PATCH 25/49] Changes after discussion with Brad --- .../src/EntityTreeRenderer.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 7b2333ade9..fccc6f512f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1095,10 +1095,20 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons if ((bool)entityA && (bool)entityB) { QUuid entityASimulatorID = entityA->getSimulatorID(); QUuid entityBSimulatorID = entityB->getSimulatorID(); - bool entityAIsStatic = !entityA->getDynamic() && !entityA->isMoving(); - bool entityBIsStatic = !entityB->getDynamic() && !entityB->isMoving(); + bool entityAIsDynamic = entityA->getDynamic(); + bool entityBIsDynamic = entityB->getDynamic(); - if (myNodeID == entityASimulatorID || (myNodeID == entityBSimulatorID && entityAIsStatic)) { +#ifdef WANT_DEBUG + bool bothEntitiesStatic = !entityAIsDynamic && !entityBIsDynamic; + if (bothEntitiesStatic) { + qCDebug(entities) << "A collision has occurred between two static entities!"; + qCDebug(entities) << "Entity A ID:" << entityA->getID(); + qCDebug(entities) << "Entity B ID:" << entityB->getID(); + } + assert(!bothEntitiesStatic); +#endif + + if ((myNodeID == entityASimulatorID && entityAIsDynamic) || (myNodeID == entityBSimulatorID && !entityAIsDynamic)) { playEntityCollisionSound(entityA, collision); emit collisionWithEntity(idA, idB, collision); if (_entitiesScriptEngine) { @@ -1106,7 +1116,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons } } - if (myNodeID == entityBSimulatorID || (myNodeID == entityASimulatorID && entityBIsStatic)) { + if ((myNodeID == entityBSimulatorID && entityBIsDynamic) || (myNodeID == entityASimulatorID && !entityBIsDynamic)) { playEntityCollisionSound(entityB, collision); // since we're swapping A and B we need to send the inverted collision Collision invertedCollision(collision); From 21d396bbb507b152c6a89152328b1f68da188f29 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 24 May 2017 14:15:59 -0700 Subject: [PATCH 26/49] Pull out ownership bidding changes --- libraries/entities/src/EntityItemProperties.cpp | 7 +------ libraries/entities/src/EntityItemProperties.h | 1 - libraries/entities/src/EntityScriptingInterface.cpp | 10 ++++------ libraries/networking/src/udt/PacketHeaders.h | 4 ++-- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index fa4df72387..1ed020e592 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1824,15 +1824,10 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged; } -bool EntityItemProperties::hasDynamicPhysicsChanges() const { - return _velocityChanged || _angularVelocityChanged || _accelerationChanged; -} - bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged || - _rotationChanged || _positionChanged; + _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged; } void EntityItemProperties::clearSimulationOwner() { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 697c634c67..590298e102 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -274,7 +274,6 @@ public: void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; - bool hasDynamicPhysicsChanges() const; bool hasMiscPhysicsChanges() const; void clearSimulationOwner(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 367343cb60..b184d648da 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -414,17 +414,15 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& entityFound = true; // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); - bool hasMiscPhysicsChanges = properties.hasMiscPhysicsChanges(); - bool hasDynamicsChanges = properties.hasDynamicPhysicsChanges(); - // _bidOnSimulationOwnership is set per-instance of the scripting interface. - // It essentially corresponds to "Am I an AC or an Interface client?" - ACs will never bid. - if ((_bidOnSimulationOwnership && ((hasMiscPhysicsChanges && entity->isMoving()) || hasDynamicsChanges))) { + bool hasTerseUpdateChanges = properties.hasTerseUpdateChanges(); + bool hasPhysicsChanges = properties.hasMiscPhysicsChanges() || hasTerseUpdateChanges; + if (_bidOnSimulationOwnership && hasPhysicsChanges) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); if (entity->getSimulatorID() == myNodeID) { // we think we already own the simulation, so make sure to send ALL TerseUpdate properties - if (properties.hasTerseUpdateChanges()) { + if (hasTerseUpdateChanges) { entity->getAllTerseUpdateProperties(properties); } // TODO: if we knew that ONLY TerseUpdate properties have changed in properties AND the object diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 0dbbcd771f..2cc3a2c42e 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -114,8 +114,8 @@ public: EntityServerScriptLog, AdjustAvatarSorting, OctreeFileReplacement, - SimulationBiddingChanges, - LAST_PACKET_TYPE = SimulationBiddingChanges + CollisionEventChanges, + LAST_PACKET_TYPE = CollisionEventChanges }; }; From 252298938b89a98235efe0d58306435d67c5b50d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 25 May 2017 09:28:11 -0700 Subject: [PATCH 27/49] Update conditional to handle 'other unowned' case --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index fccc6f512f..e029ca6ada 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1108,7 +1108,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons assert(!bothEntitiesStatic); #endif - if ((myNodeID == entityASimulatorID && entityAIsDynamic) || (myNodeID == entityBSimulatorID && !entityAIsDynamic)) { + if ((myNodeID == entityASimulatorID && entityAIsDynamic) || (myNodeID == entityBSimulatorID && (!entityAIsDynamic || entityASimulatorID.isNull()))) { playEntityCollisionSound(entityA, collision); emit collisionWithEntity(idA, idB, collision); if (_entitiesScriptEngine) { @@ -1116,7 +1116,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons } } - if ((myNodeID == entityBSimulatorID && entityBIsDynamic) || (myNodeID == entityASimulatorID && !entityBIsDynamic)) { + if ((myNodeID == entityBSimulatorID && entityBIsDynamic) || (myNodeID == entityASimulatorID && (!entityBIsDynamic || entityBSimulatorID.isNull()))) { playEntityCollisionSound(entityB, collision); // since we're swapping A and B we need to send the inverted collision Collision invertedCollision(collision); From 0a7a42bdc3855b1b08e92930f182815276130f86 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 26 May 2017 12:04:35 -0700 Subject: [PATCH 28/49] fix force of BC3 instead of BC1a compression --- libraries/image/src/image/Image.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index dcc65e8995..f274dc54f8 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -493,10 +493,6 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s if (validAlpha) { processTextureAlpha(image, validAlpha, alphaAsMask); - - // NOTE: This disables BC1a compression because it was producing odd artifacts on text textures - // for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts). - alphaAsMask = false; } gpu::TexturePointer theTexture = nullptr; @@ -506,7 +502,9 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s gpu::Element formatGPU; if (isColorTexturesCompressionEnabled()) { if (validAlpha) { - formatGPU = alphaAsMask ? gpu::Element::COLOR_COMPRESSED_SRGBA_MASK : gpu::Element::COLOR_COMPRESSED_SRGBA; + // NOTE: This disables BC1a compression because it was producing odd artifacts on text textures + // for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts). + formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; } else { formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB; } From bf057219acdeb201a1f78be085aa017eae187bd9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 26 May 2017 14:37:24 -0700 Subject: [PATCH 29/49] fix reference to pending transfer count for progress/stats --- scripts/developer/utilities/render/stats.qml | 13 ++++++------- scripts/system/progress.js | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/developer/utilities/render/stats.qml b/scripts/developer/utilities/render/stats.qml index 7acf678570..54e0dc4ce8 100644 --- a/scripts/developer/utilities/render/stats.qml +++ b/scripts/developer/utilities/render/stats.qml @@ -20,9 +20,9 @@ Item { id: stats spacing: 8 anchors.fill:parent - + property var config: Render.getConfig("Stats") - + function evalEvenHeight() { // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ? return (height - spacing * (children.length - 1)) / children.length @@ -81,7 +81,7 @@ Item { color: "#1AC567" }, { - prop: "textureGPUTransferCount", + prop: "texturePendingGPUTransferCount", label: "Transfer", color: "#9495FF" } @@ -158,7 +158,7 @@ Item { } ] } - + PlotPerf { title: "State Changes" height: parent.evalEvenHeight() @@ -180,7 +180,7 @@ Item { color: "#1AC567" } ] - } + } property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred") property var drawTransparentConfig: Render.getConfig("DrawTransparentDeferred") @@ -211,7 +211,7 @@ Item { color: "#FED959" } ] - } + } PlotPerf { title: "Timing" @@ -250,4 +250,3 @@ Item { } } - diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 81da38c8c2..f4741c5b6a 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -261,7 +261,7 @@ } } - gpuTextures = Render.getConfig("Stats").textureGPUTransferCount; + gpuTextures = Render.getConfig("Stats").texturePendingGPUTransferCount; // Update state if (!visible) { // Not visible because no recent downloads @@ -290,7 +290,7 @@ }, FADE_OUT_WAIT); } } else { - if (displayProgress < 100 || gpuTextures > 0) { // Was finished and waiting to fade out but have resumed so + if (displayProgress < 100 || gpuTextures > 0) { // Was finished and waiting to fade out but have resumed so // don't fade out Script.clearInterval(fadeWaitTimer); fadeWaitTimer = null; From 0920dbc1a8910c986b2c83b2422aa7fa63e192d9 Mon Sep 17 00:00:00 2001 From: volansystech Date: Mon, 29 May 2017 15:53:33 +0530 Subject: [PATCH 30/49] Resolve the comments of @ZappoMan. --- interface/src/Application.cpp | 111 +++++++++--------- interface/src/Application.h | 13 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 12 +- .../src/display-plugins/OpenGLDisplayPlugin.h | 10 +- libraries/plugins/src/plugins/Plugin.h | 22 ++-- .../oculus/src/OculusBaseDisplayPlugin.cpp | 14 +-- plugins/oculus/src/OculusBaseDisplayPlugin.h | 4 +- 7 files changed, 92 insertions(+), 94 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a40f31a8bb..57a627fe53 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -244,6 +244,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; +static const int INTERVAL_TO_CHECK_HMD_MOUNTED_STATUS = 500; // milliseconds +static const QString OCULUS_RIFT_DISPLAY_PLUGIN_NAME = "Oculus Rift"; const QHash Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, @@ -1338,19 +1340,20 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); - if (isOculusRiftPluginAvailable()) { - // If Oculus Rift Plugin is available and current display plugin is not Oculus Rift - // then startOculusRiftStandBySession to listen Oculus HMD Mounted status. - if (getActiveDisplayPlugin()->getName() != "Oculus Rift" && - !oculusRiftPlugin->isStandBySessionActive()) { - startOculusRiftStandBySession(); - } - // Poll periodically to check whether the user has worn Oculus HMD or not. And switch Display mode accordingly. - // If the user wear Oculus HMD then switch to VR mode. If the user removes Oculus HMD then switch to Desktop mode. - QTimer *switchDisplayModeTimer = new QTimer(this); - connect(switchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayModeForOculus())); - switchDisplayModeTimer->start(500); - } + if (isHMDPluginAvailable()) { + // Currently, autoswitch display mode support is only for Oculus Rift. + // If HMD Plugin is available and current display plugin is not HMD plugin + // then startHMDStandBySession to listen HMD Mounted status. + if (getActiveDisplayPlugin()->getName() != _hmdPluginName && + !_hmdPlugin->isStandBySessionActive()) { + startHMDStandBySession(); + } + // Poll periodically to check whether the user has worn HMD or not. And switch Display mode accordingly. + // If the user wear HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. + QTimer *switchDisplayModeTimer = new QTimer(this); + connect(switchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode())); + switchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_MOUNTED_STATUS); + } auto glInfo = getGLContextData(); properties["gl_info"] = glInfo; @@ -1581,8 +1584,8 @@ void Application::aboutToQuit() { } getActiveDisplayPlugin()->deactivate(); - if (oculusRiftPlugin && oculusRiftPlugin->isStandBySessionActive()) { - oculusRiftPlugin->endStandBySession(); + if (_hmdPlugin && _hmdPlugin->isStandBySessionActive()) { + _hmdPlugin->endStandBySession(); } // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); @@ -6846,54 +6849,48 @@ void Application::updateDisplayMode() { Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } -bool Application::isOculusRiftPluginAvailable() { - bool isOculusRiftPluginAvailable = false; - auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); - // Default to the first item on the list, in case none of the menu items match - DisplayPluginPointer defaultplugin = displayPlugins.at(0); - if (defaultplugin->isHmd() && defaultplugin->getName() == "Oculus Rift") { - oculusRiftPlugin = defaultplugin; - return true; - } - // Iterate to check If Oculus Rift Plugin is available - foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { - QString pluginname = displayPlugin->getName(); - if (displayPlugin->isHmd() && pluginname == "Oculus Rift") { - oculusRiftPlugin = displayPlugin; - _oculusHMDMountedStatus = displayPlugin->isDisplayVisible(); - isOculusRiftPluginAvailable = true; - break; - } - } - return isOculusRiftPluginAvailable; +bool Application::isHMDPluginAvailable() { + bool isHMDEnabledPluginAvailable = false; + auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); + // Currently, autoswitch display mode support is only for Oculus Rift. + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { + if (displayPlugin->isHmd() && displayPlugin->getName() == OCULUS_RIFT_DISPLAY_PLUGIN_NAME) { + _hmdPlugin = displayPlugin; + _hmdPluginName = displayPlugin->getName(); + _hmdMountedStatus = displayPlugin->isDisplayVisible(); + isHMDEnabledPluginAvailable = true; + break; + } + } + return isHMDEnabledPluginAvailable; } -void Application::switchDisplayModeForOculus() { - bool currenthmdMountedStatus = oculusRiftPlugin->isDisplayVisible(); - if (currenthmdMountedStatus != _oculusHMDMountedStatus) { - // Switch to respective mode as soon as currenthmdMountedStatus changes - if (currenthmdMountedStatus == false && _oculusHMDMountedStatus == true) { - qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; - setActiveDisplayPlugin("Desktop"); - startOculusRiftStandBySession(); - } - if (currenthmdMountedStatus == true && _oculusHMDMountedStatus == false) { - qCDebug(interfaceapp) << "Switching from Desktop to HMD mode"; - endOculusRiftStandBySession(); - setActiveDisplayPlugin("Oculus Rift"); - } - } - _oculusHMDMountedStatus = currenthmdMountedStatus; +void Application::switchDisplayMode() { + bool currentHMDMountedStatus = _hmdPlugin->isDisplayVisible(); + if (currentHMDMountedStatus != _hmdMountedStatus) { + // Switch to respective mode as soon as currenthmdMountedStatus changes + if (currentHMDMountedStatus == false && _hmdMountedStatus == true) { + qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; + setActiveDisplayPlugin("Desktop"); + startHMDStandBySession(); + } + if (currentHMDMountedStatus == true && _hmdMountedStatus == false) { + qCDebug(interfaceapp) << "Switching from Desktop to HMD mode"; + endHMDStandBySession(); + setActiveDisplayPlugin(_hmdPluginName); + } + } + _hmdMountedStatus = currentHMDMountedStatus; } -bool Application::startOculusRiftStandBySession() { - bool isStandBySessionStarted = oculusRiftPlugin->startStandBySession(); - qCDebug(interfaceapp) << "startOculusRiftStandBySession: " << isStandBySessionStarted; - return isStandBySessionStarted; +bool Application::startHMDStandBySession() { + bool isStandBySessionStarted = _hmdPlugin->startStandBySession(); + qCDebug(interfaceapp) << "startHMDStandBySession: " << isStandBySessionStarted; + return isStandBySessionStarted; } -void Application::endOculusRiftStandBySession() { - oculusRiftPlugin->endStandBySession(); +void Application::endHMDStandBySession() { + _hmdPlugin->endStandBySession(); } mat4 Application::getEyeProjection(int eye) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 112b650160..699cb9f879 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -442,7 +442,7 @@ private slots: void addAssetToWorldErrorTimeout(); void handleSandboxStatus(QNetworkReply* reply); - void switchDisplayModeForOculus(); + void switchDisplayMode(); private: static void initDisplay(); void init(); @@ -684,11 +684,12 @@ private: SharedSoundPointer _snapshotSound; - DisplayPluginPointer oculusRiftPlugin; - bool isOculusRiftPluginAvailable(); - bool _oculusHMDMountedStatus; // Keep track of Oculus Rift HMDMounted Flag - bool startOculusRiftStandBySession(); - void endOculusRiftStandBySession(); + DisplayPluginPointer _hmdPlugin; // HMD Enabled Plugin + QString _hmdPluginName; + bool isHMDPluginAvailable(); + bool _hmdMountedStatus; // Check HMD Mounted status + bool startHMDStandBySession(); + void endHMDStandBySession(); }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index cebe844b84..3bdf9a672c 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -339,15 +339,15 @@ void OpenGLDisplayPlugin::deactivate() { } bool OpenGLDisplayPlugin::startStandBySession() { - if (!activateStandBySession()) { - return false; - } - return Parent::startStandBySession(); + if (!activateStandBySession()) { + return false; + } + return Parent::startStandBySession(); } void OpenGLDisplayPlugin::endStandBySession() { - deactivateStandBySession(); - return Parent::endStandBySession(); + deactivateStandBySession(); + return Parent::endStandBySession(); } void OpenGLDisplayPlugin::customizeContext() { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index ecde3b3c93..9681158c55 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -42,8 +42,8 @@ public: // between the main thread and the presentation thread bool activate() override final; void deactivate() override final; - bool startStandBySession() override final; - void endStandBySession() override final; + bool startStandBySession() override final; + void endStandBySession() override final; bool eventFilter(QObject* receiver, QEvent* event) override; bool isDisplayVisible() const override { return true; } @@ -102,9 +102,9 @@ protected: virtual bool internalActivate() { return true; } virtual void internalDeactivate() {} - // Returns true on successful activation of standby session - virtual bool activateStandBySession() { return true; } - virtual void deactivateStandBySession() {} + // Returns true on successful activation of standby session + virtual bool activateStandBySession() { return true; } + virtual void deactivateStandBySession() {} // Plugin specific functionality to send the composed scene to the output window or device virtual void internalPresent(); diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index 045a9eee15..11ea79186a 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -53,18 +53,18 @@ public: virtual bool isActive() { return _active; } - virtual bool startStandBySession() { - _standbysessionstatus = true; - return _standbysessionstatus; - } + virtual bool startStandBySession() { + _standbysessionstatus = true; + return _standbysessionstatus; + } - virtual void endStandBySession() { - _standbysessionstatus = false; - } + virtual void endStandBySession() { + _standbysessionstatus = false; + } - virtual bool isStandBySessionActive() { - return _standbysessionstatus; - } + virtual bool isStandBySessionActive() { + return _standbysessionstatus; + } /** * Called by the application during it's idle phase. If the plugin needs to do @@ -85,7 +85,7 @@ signals: protected: bool _active { false }; - bool _standbysessionstatus { false }; + bool _standbysessionstatus { false }; PluginContainer* _container { nullptr }; static const char* UNKNOWN_PLUGIN_ID; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 28e30e0d21..df98abf408 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -128,15 +128,15 @@ void OculusBaseDisplayPlugin::internalDeactivate() { } bool OculusBaseDisplayPlugin::activateStandBySession() { - _session = acquireOculusSession(); - if (!_session) { - return false; - } - return true; + _session = acquireOculusSession(); + if (!_session) { + return false; + } + return true; } void OculusBaseDisplayPlugin::deactivateStandBySession() { - releaseOculusSession(); - _session = nullptr; + releaseOculusSession(); + _session = nullptr; } void OculusBaseDisplayPlugin::updatePresentPose() { //mat4 sensorResetMat; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 79085f817b..1f54742c2d 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -33,8 +33,8 @@ protected: void uncustomizeContext() override; bool internalActivate() override; void internalDeactivate() override; - bool activateStandBySession() override; - void deactivateStandBySession() override; + bool activateStandBySession() override; + void deactivateStandBySession() override; void updatePresentPose() override; protected: From e90b1b5a67c8fd33d539c7d86b677ba24d17f61c Mon Sep 17 00:00:00 2001 From: volansystech Date: Mon, 29 May 2017 18:21:59 +0530 Subject: [PATCH 31/49] Resolve the comments of @ZappoMan. --- interface/src/Application.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d219d7bcb6..b5733fa6f5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -246,6 +246,7 @@ Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTRE static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; static const int INTERVAL_TO_CHECK_HMD_MOUNTED_STATUS = 500; // milliseconds static const QString OCULUS_RIFT_DISPLAY_PLUGIN_NAME = "Oculus Rift"; +static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; const QHash Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, @@ -1348,8 +1349,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo !_hmdPlugin->isStandBySessionActive()) { startHMDStandBySession(); } - // Poll periodically to check whether the user has worn HMD or not. And switch Display mode accordingly. - // If the user wear HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. + // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly. + // If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. QTimer *switchDisplayModeTimer = new QTimer(this); connect(switchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode())); switchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_MOUNTED_STATUS); @@ -6773,7 +6774,7 @@ void Application::switchDisplayMode() { // Switch to respective mode as soon as currenthmdMountedStatus changes if (currentHMDMountedStatus == false && _hmdMountedStatus == true) { qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; - setActiveDisplayPlugin("Desktop"); + setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME); startHMDStandBySession(); } if (currentHMDMountedStatus == true && _hmdMountedStatus == false) { From 58142817a12d132077515669953fd3c4087487df Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Wed, 31 May 2017 19:13:55 +0530 Subject: [PATCH 32/49] Resolve the review comments of @ZappoMan. --- interface/src/Application.cpp | 86 ++++++++++++++++++----------------- interface/src/Application.h | 14 ++---- 2 files changed, 49 insertions(+), 51 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b5733fa6f5..ac39f51d7e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -244,8 +244,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; -static const int INTERVAL_TO_CHECK_HMD_MOUNTED_STATUS = 500; // milliseconds -static const QString OCULUS_RIFT_DISPLAY_PLUGIN_NAME = "Oculus Rift"; +static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds +static const QString DISPLAY_PLUGIN_NAME_OCULUS_RIFT = "Oculus Rift"; static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; const QHash Application::_acceptedExtensions { @@ -1341,19 +1341,38 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); - if (isHMDPluginAvailable()) { - // Currently, autoswitch display mode support is only for Oculus Rift. - // If HMD Plugin is available and current display plugin is not HMD plugin - // then startHMDStandBySession to listen HMD Mounted status. - if (getActiveDisplayPlugin()->getName() != _hmdPluginName && - !_hmdPlugin->isStandBySessionActive()) { + _autoSwitchDisplayModeSupportedHMDPlugin = nullptr; + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { + if (displayPlugin->isHmd() && + displayPlugin->getName() == DISPLAY_PLUGIN_NAME_OCULUS_RIFT) { + + // Currently auto switch display mode support is only for Oculus Rift + // To support other plugins, add a condition + // (|| displayPlugin->getName() == "Other HMD Display Plugin Name") + + _autoSwitchDisplayModeSupportedHMDPlugin = displayPlugin; + _autoSwitchDisplayModeSupportedHMDPluginName = + _autoSwitchDisplayModeSupportedHMDPlugin->getName(); + _previousHMDWornStatus = + _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible(); + qCDebug(interfaceapp) << "_autoSwitchModeSupportedPluginName::" + << _autoSwitchDisplayModeSupportedHMDPluginName; + break; + } + } + + if (_autoSwitchDisplayModeSupportedHMDPlugin != nullptr) { + // If HMD Plugin is available and current display plugin is not HMD plugin + // then startHMDStandBySession to poll HMD Worn status. + if (getActiveDisplayPlugin()->getName() != _autoSwitchDisplayModeSupportedHMDPluginName && + !_autoSwitchDisplayModeSupportedHMDPlugin->isStandBySessionActive()) { startHMDStandBySession(); } // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly. // If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. - QTimer *switchDisplayModeTimer = new QTimer(this); - connect(switchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode())); - switchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_MOUNTED_STATUS); + QTimer* autoSwitchDisplayModeTimer = new QTimer(this); + connect(autoSwitchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode())); + autoSwitchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_WORN_STATUS); } auto glInfo = getGLContextData(); @@ -1585,9 +1604,10 @@ void Application::aboutToQuit() { } getActiveDisplayPlugin()->deactivate(); - if (_hmdPlugin && _hmdPlugin->isStandBySessionActive()) { - _hmdPlugin->endStandBySession(); - } + if (_autoSwitchDisplayModeSupportedHMDPlugin != nullptr + && _autoSwitchDisplayModeSupportedHMDPlugin->isStandBySessionActive()) { + _autoSwitchDisplayModeSupportedHMDPlugin->endStandBySession(); + } // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); @@ -6752,48 +6772,30 @@ void Application::updateDisplayMode() { Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } -bool Application::isHMDPluginAvailable() { - bool isHMDEnabledPluginAvailable = false; - auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); - // Currently, autoswitch display mode support is only for Oculus Rift. - foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { - if (displayPlugin->isHmd() && displayPlugin->getName() == OCULUS_RIFT_DISPLAY_PLUGIN_NAME) { - _hmdPlugin = displayPlugin; - _hmdPluginName = displayPlugin->getName(); - _hmdMountedStatus = displayPlugin->isDisplayVisible(); - isHMDEnabledPluginAvailable = true; - break; - } - } - return isHMDEnabledPluginAvailable; -} - void Application::switchDisplayMode() { - bool currentHMDMountedStatus = _hmdPlugin->isDisplayVisible(); - if (currentHMDMountedStatus != _hmdMountedStatus) { - // Switch to respective mode as soon as currenthmdMountedStatus changes - if (currentHMDMountedStatus == false && _hmdMountedStatus == true) { + bool currentHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible(); + if (currentHMDWornStatus != _previousHMDWornStatus) { + // Switch to respective mode as soon as currentHMDWornStatus changes + if (currentHMDWornStatus == false && _previousHMDWornStatus == true) { qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME); startHMDStandBySession(); } - if (currentHMDMountedStatus == true && _hmdMountedStatus == false) { + if (currentHMDWornStatus == true && _previousHMDWornStatus == false) { qCDebug(interfaceapp) << "Switching from Desktop to HMD mode"; endHMDStandBySession(); - setActiveDisplayPlugin(_hmdPluginName); + setActiveDisplayPlugin(_autoSwitchDisplayModeSupportedHMDPluginName); } } - _hmdMountedStatus = currentHMDMountedStatus; + _previousHMDWornStatus = currentHMDWornStatus; } -bool Application::startHMDStandBySession() { - bool isStandBySessionStarted = _hmdPlugin->startStandBySession(); - qCDebug(interfaceapp) << "startHMDStandBySession: " << isStandBySessionStarted; - return isStandBySessionStarted; +void Application::startHMDStandBySession() { + _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession(); } void Application::endHMDStandBySession() { - _hmdPlugin->endStandBySession(); + _autoSwitchDisplayModeSupportedHMDPlugin->endStandBySession(); } mat4 Application::getEyeProjection(int eye) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index f19c2c9adf..e1fb37ef3a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -681,14 +681,10 @@ private: AudioInjector* _snapshotSoundInjector { nullptr }; SharedSoundPointer _snapshotSound; - - DisplayPluginPointer _hmdPlugin; // HMD Enabled Plugin - QString _hmdPluginName; - bool isHMDPluginAvailable(); - bool _hmdMountedStatus; // Check HMD Mounted status - bool startHMDStandBySession(); - void endHMDStandBySession(); + DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin = nullptr; + QString _autoSwitchDisplayModeSupportedHMDPluginName; + bool _previousHMDWornStatus; + void startHMDStandBySession(); + void endHMDStandBySession(); }; - - #endif // hifi_Application_h From c7c07b28e94bc9d0b6aa0ac767e39aacb84c0b8c Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Thu, 1 Jun 2017 12:14:54 +0530 Subject: [PATCH 33/49] Resolve the reviewed comments of @ZappoMan --- interface/src/Application.cpp | 8 +------- libraries/plugins/src/plugins/DisplayPlugin.h | 1 + plugins/oculus/src/OculusBaseDisplayPlugin.h | 1 + 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ac39f51d7e..b8bfff8c5f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -245,7 +245,6 @@ Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTRE static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds -static const QString DISPLAY_PLUGIN_NAME_OCULUS_RIFT = "Oculus Rift"; static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; const QHash Application::_acceptedExtensions { @@ -1344,12 +1343,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _autoSwitchDisplayModeSupportedHMDPlugin = nullptr; foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { if (displayPlugin->isHmd() && - displayPlugin->getName() == DISPLAY_PLUGIN_NAME_OCULUS_RIFT) { - - // Currently auto switch display mode support is only for Oculus Rift - // To support other plugins, add a condition - // (|| displayPlugin->getName() == "Other HMD Display Plugin Name") - + displayPlugin->getSupportsAutoSwitch()) { _autoSwitchDisplayModeSupportedHMDPlugin = displayPlugin; _autoSwitchDisplayModeSupportedHMDPluginName = _autoSwitchDisplayModeSupportedHMDPlugin->getName(); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 754c919fd4..297bdb2cca 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -200,6 +200,7 @@ public: virtual float newFramePresentRate() const { return -1.0f; } // Rate at which rendered frames are being skipped virtual float droppedFrameRate() const { return -1.0f; } + virtual bool getSupportsAutoSwitch() { return false; } // Hardware specific stats virtual QJsonObject getHardwareStats() const { return QJsonObject(); } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 1f54742c2d..bfdcc5db1e 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -26,6 +26,7 @@ public: void resetSensors() override final; bool beginFrameRender(uint32_t frameIndex) override; float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; } + bool getSupportsAutoSwitch() override final { return true; } protected: From 6228ff19bf2c9315b6edc01747a985301421e436 Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Fri, 2 Jun 2017 14:37:17 +0530 Subject: [PATCH 34/49] Resolve the reviewed comments of @ZappoMan --- interface/src/Application.cpp | 26 +++++++++---------- interface/src/Application.h | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 3 ++- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8384204fb9..a3787847db 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1349,16 +1349,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _autoSwitchDisplayModeSupportedHMDPlugin->getName(); _previousHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible(); - qCDebug(interfaceapp) << "_autoSwitchModeSupportedPluginName::" - << _autoSwitchDisplayModeSupportedHMDPluginName; break; } } - if (_autoSwitchDisplayModeSupportedHMDPlugin != nullptr) { - // If HMD Plugin is available and current display plugin is not HMD plugin - // then startHMDStandBySession to poll HMD Worn status. - if (getActiveDisplayPlugin()->getName() != _autoSwitchDisplayModeSupportedHMDPluginName && + if (_autoSwitchDisplayModeSupportedHMDPlugin) { + if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin && !_autoSwitchDisplayModeSupportedHMDPlugin->isStandBySessionActive()) { startHMDStandBySession(); } @@ -1600,7 +1596,7 @@ void Application::aboutToQuit() { } getActiveDisplayPlugin()->deactivate(); - if (_autoSwitchDisplayModeSupportedHMDPlugin != nullptr + if (_autoSwitchDisplayModeSupportedHMDPlugin && _autoSwitchDisplayModeSupportedHMDPlugin->isStandBySessionActive()) { _autoSwitchDisplayModeSupportedHMDPlugin->endStandBySession(); } @@ -6769,18 +6765,20 @@ void Application::updateDisplayMode() { } void Application::switchDisplayMode() { + if (!_autoSwitchDisplayModeSupportedHMDPlugin) { + return; + } bool currentHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible(); if (currentHMDWornStatus != _previousHMDWornStatus) { - // Switch to respective mode as soon as currentHMDWornStatus changes - if (currentHMDWornStatus == false && _previousHMDWornStatus == true) { - qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; - setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME); - startHMDStandBySession(); - } - if (currentHMDWornStatus == true && _previousHMDWornStatus == false) { + // Switch to respective mode as soon as currentHMDWornStatus changes + if (currentHMDWornStatus) { qCDebug(interfaceapp) << "Switching from Desktop to HMD mode"; endHMDStandBySession(); setActiveDisplayPlugin(_autoSwitchDisplayModeSupportedHMDPluginName); + } else { + qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; + setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME); + startHMDStandBySession(); } } _previousHMDWornStatus = currentHMDWornStatus; diff --git a/interface/src/Application.h b/interface/src/Application.h index e1fb37ef3a..4cd47ada58 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -681,7 +681,7 @@ private: AudioInjector* _snapshotSoundInjector { nullptr }; SharedSoundPointer _snapshotSound; - DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin = nullptr; + DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin; QString _autoSwitchDisplayModeSupportedHMDPluginName; bool _previousHMDWornStatus; void startHMDStandBySession(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 3bdf9a672c..fbdc1ad71e 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -315,6 +315,7 @@ bool OpenGLDisplayPlugin::activate() { if (isHmd() && (getHmdScreen() >= 0)) { _container->showDisplayPluginsTools(); } + return Parent::activate(); } @@ -347,7 +348,7 @@ bool OpenGLDisplayPlugin::startStandBySession() { void OpenGLDisplayPlugin::endStandBySession() { deactivateStandBySession(); - return Parent::endStandBySession(); + Parent::endStandBySession(); } void OpenGLDisplayPlugin::customizeContext() { From f5d732f3329132b5b604242261ec785c08be7f6b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 31 May 2017 19:00:41 -0700 Subject: [PATCH 35/49] initial version of the ClosureEventSender using std::thread --- interface/src/Application.cpp | 6 ++ interface/src/Application.h | 3 + interface/src/main.cpp | 7 ++ .../src/networking/ClosureEventSender.cpp | 71 +++++++++++++++++++ interface/src/networking/ClosureEventSender.h | 35 +++++++++ libraries/networking/src/AccountManager.cpp | 1 - libraries/networking/src/AccountManager.h | 1 + .../networking/src/UserActivityLogger.cpp | 2 - libraries/networking/src/UserActivityLogger.h | 2 + 9 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 interface/src/networking/ClosureEventSender.cpp create mode 100644 interface/src/networking/ClosureEventSender.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 46c4c0bd4e..297ee943fa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -144,6 +144,7 @@ #include "InterfaceLogging.h" #include "LODManager.h" #include "ModelPackager.h" +#include "networking/ClosureEventSender.h" #include "networking/HFWebEngineProfile.h" #include "networking/HFTabletWebEngineProfile.h" #include "networking/FileTypeProfile.h" @@ -534,6 +535,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -1568,6 +1570,10 @@ void Application::aboutToQuit() { getActiveDisplayPlugin()->deactivate(); + // use the ClosureEventSender via an std::thread (to not use QThread while the application is going down) + // to send an event that says the user asked for the app to close + _userQuitThread = std::thread { &ClosureEventSender::sendQuitStart, DependencyManager::get() }; + // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9cf03f1cef..23673399f6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -13,6 +13,7 @@ #define hifi_Application_h #include +#include #include #include @@ -680,6 +681,8 @@ private: FileScriptingInterface* _fileDownload; AudioInjector* _snapshotSoundInjector { nullptr }; SharedSoundPointer _snapshotSound; + + std::thread _userQuitThread; }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 49517eb38e..68525dfd1e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -30,6 +30,7 @@ #include "InterfaceLogging.h" #include "UserActivityLogger.h" #include "MainWindow.h" +#include "networking/ClosureEventSender.h" #ifdef HAS_BUGSPLAT #include @@ -267,6 +268,12 @@ int main(int argc, const char* argv[]) { Application::shutdownPlugins(); + if (UserActivityLogger::getInstance().isEnabled()) { + // send a quit finished event here to indicate that this session closed cleanly + std::thread quitCompleteThread { &::ClosureEventSender::sendQuitFinish, DependencyManager::get() }; + quitCompleteThread.join(); + } + qCDebug(interfaceapp, "Normal exit."); #if !defined(DEBUG) && !defined(Q_OS_LINUX) // HACK: exit immediately (don't handle shutdown callbacks) for Release build diff --git a/interface/src/networking/ClosureEventSender.cpp b/interface/src/networking/ClosureEventSender.cpp new file mode 100644 index 0000000000..f514fa17b6 --- /dev/null +++ b/interface/src/networking/ClosureEventSender.cpp @@ -0,0 +1,71 @@ +// +// ClosureEventSender.cpp +// interface/src/networking +// +// Created by Stephen Birarda on 5/31/17. +// Copyright 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ClosureEventSender.h" + +QNetworkRequest createNetworkRequest() { + + QNetworkRequest request; + + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL; + requestURL.setPath(USER_ACTIVITY_URL); + + request.setUrl(requestURL); + + auto accountManager = DependencyManager::get(); + + if (accountManager->hasValidAccessToken()) { + request.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, + accountManager->getAccountInfo().getAccessToken().authorizationHeaderValue()); + } + + request.setRawHeader(METAVERSE_SESSION_ID_HEADER, + uuidStringWithoutCurlyBraces(accountManager->getSessionID()).toLocal8Bit()); + + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + return request; +} + +QByteArray postDataForAction(QString action) { + return QString("{\"action\": \"" + action + "\"}").toUtf8(); +} + +QNetworkReply* replyForAction(QString action) { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + return networkAccessManager.post(createNetworkRequest(), postDataForAction(action)); +} + +void ClosureEventSender::sendQuitStart() { + + QNetworkReply* reply = replyForAction("quit_start"); + + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); +} + +void ClosureEventSender::sendQuitFinish() { + QNetworkReply* reply = replyForAction("quit_finish"); + + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); +} diff --git a/interface/src/networking/ClosureEventSender.h b/interface/src/networking/ClosureEventSender.h new file mode 100644 index 0000000000..dc726fc386 --- /dev/null +++ b/interface/src/networking/ClosureEventSender.h @@ -0,0 +1,35 @@ +// +// ClosureEventSender.h +// interface/src/networking +// +// Created by Stephen Birarda on 5/31/17. +// Copyright 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_ClosureEventSender_h +#define hifi_ClosureEventSender_h + +#include +#include + +#include + +class ClosureEventSender : public Dependency { + SINGLETON_DEPENDENCY + +public: + void setSessionID(QUuid sessionID) { _sessionID = sessionID; } + + void sendQuitStart(); + void sendQuitFinish(); + void sendCrashEvent(); + +private: + QUuid _sessionID; + QString _accessToken; +}; + +#endif // hifi_ClosureEventSender_h diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 6266ad0f89..2457d0ac42 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -45,7 +45,6 @@ Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) Q_DECLARE_METATYPE(JSONCallbackParameters) const QString ACCOUNTS_GROUP = "accounts"; -static const auto METAVERSE_SESSION_ID_HEADER = QString("HFM-SessionID").toLocal8Bit(); JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod, QObject* errorCallbackReceiver, const QString& errorCallbackMethod, diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index dd2216957f..bd452646f6 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -52,6 +52,7 @@ namespace AccountManagerAuth { Q_DECLARE_METATYPE(AccountManagerAuth::Type); const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization"; +const auto METAVERSE_SESSION_ID_HEADER = QString("HFM-SessionID").toLocal8Bit(); using UserAgentGetter = std::function; diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index e2dd110cfd..28117c0933 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -20,8 +20,6 @@ #include #include "AddressManager.h" -static const QString USER_ACTIVITY_URL = "/api/v1/user_activities"; - UserActivityLogger& UserActivityLogger::getInstance() { static UserActivityLogger sharedInstance; return sharedInstance; diff --git a/libraries/networking/src/UserActivityLogger.h b/libraries/networking/src/UserActivityLogger.h index b41960a8ad..9fad498b86 100644 --- a/libraries/networking/src/UserActivityLogger.h +++ b/libraries/networking/src/UserActivityLogger.h @@ -22,6 +22,8 @@ #include #include "AddressManager.h" +const QString USER_ACTIVITY_URL = "/api/v1/user_activities"; + class UserActivityLogger : public QObject { Q_OBJECT From 40dfcb1e6e5e8d18f8285d2e52ad14ea3f8cbfc2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 10:43:47 -0700 Subject: [PATCH 36/49] send quit event during shutdown on thread, with timeout --- interface/src/Application.cpp | 21 +++++++-- interface/src/Application.h | 3 -- interface/src/main.cpp | 8 ---- .../src/networking/ClosureEventSender.cpp | 43 +++++++++++++------ interface/src/networking/ClosureEventSender.h | 22 +++++++--- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 297ee943fa..a637f9414b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -11,6 +11,8 @@ #include "Application.h" +#include + #include #include #include @@ -1570,9 +1572,13 @@ void Application::aboutToQuit() { getActiveDisplayPlugin()->deactivate(); - // use the ClosureEventSender via an std::thread (to not use QThread while the application is going down) - // to send an event that says the user asked for the app to close - _userQuitThread = std::thread { &ClosureEventSender::sendQuitStart, DependencyManager::get() }; + // use the ClosureEventSender via a QThread to send an event that says the user asked for the app to close + auto closureEventSender = DependencyManager::get(); + QThread* closureEventThread = new QThread(this); + closureEventSender->moveToThread(closureEventThread); + // sendQuitEventAsync will bail immediately if the UserActivityLogger is not enabled + connect(closureEventThread, &QThread::started, closureEventSender.data(), &ClosureEventSender::sendQuitEventAsync); + closureEventThread->start(); // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); @@ -1738,6 +1744,15 @@ Application::~Application() { _window->deleteLater(); + // make sure that the quit event has finished sending before we take the application down + auto closureEventSender = DependencyManager::get(); + while (!closureEventSender->hasFinishedQuitEvent() && !closureEventSender->hasTimedOutQuitEvent()) { + // yield so we're not spinning + std::this_thread::yield(); + } + // quit the thread used by the closure event sender + closureEventSender->thread()->quit(); + // Can't log to file passed this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 23673399f6..9cf03f1cef 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -13,7 +13,6 @@ #define hifi_Application_h #include -#include #include #include @@ -681,8 +680,6 @@ private: FileScriptingInterface* _fileDownload; AudioInjector* _snapshotSoundInjector { nullptr }; SharedSoundPointer _snapshotSound; - - std::thread _userQuitThread; }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 68525dfd1e..63738d2d91 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -24,13 +24,11 @@ #include #include - #include "AddressManager.h" #include "Application.h" #include "InterfaceLogging.h" #include "UserActivityLogger.h" #include "MainWindow.h" -#include "networking/ClosureEventSender.h" #ifdef HAS_BUGSPLAT #include @@ -268,12 +266,6 @@ int main(int argc, const char* argv[]) { Application::shutdownPlugins(); - if (UserActivityLogger::getInstance().isEnabled()) { - // send a quit finished event here to indicate that this session closed cleanly - std::thread quitCompleteThread { &::ClosureEventSender::sendQuitFinish, DependencyManager::get() }; - quitCompleteThread.join(); - } - qCDebug(interfaceapp, "Normal exit."); #if !defined(DEBUG) && !defined(Q_OS_LINUX) // HACK: exit immediately (don't handle shutdown callbacks) for Release build diff --git a/interface/src/networking/ClosureEventSender.cpp b/interface/src/networking/ClosureEventSender.cpp index f514fa17b6..238629b809 100644 --- a/interface/src/networking/ClosureEventSender.cpp +++ b/interface/src/networking/ClosureEventSender.cpp @@ -9,14 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include -#include #include #include #include #include +#include #include #include @@ -43,11 +44,13 @@ QNetworkRequest createNetworkRequest() { request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + request.setPriority(QNetworkRequest::HighPriority); + return request; } QByteArray postDataForAction(QString action) { - return QString("{\"action\": \"" + action + "\"}").toUtf8(); + return QString("{\"action_name\": \"" + action + "\"}").toUtf8(); } QNetworkReply* replyForAction(QString action) { @@ -55,17 +58,33 @@ QNetworkReply* replyForAction(QString action) { return networkAccessManager.post(createNetworkRequest(), postDataForAction(action)); } -void ClosureEventSender::sendQuitStart() { - - QNetworkReply* reply = replyForAction("quit_start"); - - QEventLoop loop; - QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); +void ClosureEventSender::sendQuitEventAsync() { + if (UserActivityLogger::getInstance().isEnabled()) { + QNetworkReply* reply = replyForAction("quit"); + connect(reply, &QNetworkReply::finished, this, &ClosureEventSender::handleQuitEventFinished); + _quitEventStartTimestamp = QDateTime::currentMSecsSinceEpoch(); + } else { + _hasFinishedQuitEvent = true; + } } -void ClosureEventSender::sendQuitFinish() { - QNetworkReply* reply = replyForAction("quit_finish"); +void ClosureEventSender::handleQuitEventFinished() { + _hasFinishedQuitEvent = true; - QEventLoop loop; - QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + auto reply = qobject_cast(sender()); + if (reply->error() == QNetworkReply::NoError) { + qCDebug(networking) << "Quit event sent successfully"; + } else { + qCDebug(networking) << "Failed to send quit event -" << reply->errorString(); + } + + reply->deleteLater(); } + +bool ClosureEventSender::hasTimedOutQuitEvent() { + const int CLOSURE_EVENT_TIMEOUT_MS = 5000; + return _quitEventStartTimestamp != 0 + && QDateTime::currentMSecsSinceEpoch() - _quitEventStartTimestamp > CLOSURE_EVENT_TIMEOUT_MS; +} + + diff --git a/interface/src/networking/ClosureEventSender.h b/interface/src/networking/ClosureEventSender.h index dc726fc386..be2daca12b 100644 --- a/interface/src/networking/ClosureEventSender.h +++ b/interface/src/networking/ClosureEventSender.h @@ -12,24 +12,32 @@ #ifndef hifi_ClosureEventSender_h #define hifi_ClosureEventSender_h +#include + #include #include #include -class ClosureEventSender : public Dependency { +class ClosureEventSender : public QObject, public Dependency { + Q_OBJECT SINGLETON_DEPENDENCY public: - void setSessionID(QUuid sessionID) { _sessionID = sessionID; } + void sendCrashEventSync(); - void sendQuitStart(); - void sendQuitFinish(); - void sendCrashEvent(); + bool hasTimedOutQuitEvent(); + bool hasFinishedQuitEvent() { return _hasFinishedQuitEvent; } + +public slots: + void sendQuitEventAsync(); + +private slots: + void handleQuitEventFinished(); private: - QUuid _sessionID; - QString _accessToken; + std::atomic _hasFinishedQuitEvent { false }; + std::atomic _quitEventStartTimestamp; }; #endif // hifi_ClosureEventSender_h From ecc697dbe1a467b6448a3b3af77eca645d0de35c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 13:40:50 -0700 Subject: [PATCH 37/49] remove crash event definition for now --- interface/src/networking/ClosureEventSender.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/networking/ClosureEventSender.h b/interface/src/networking/ClosureEventSender.h index be2daca12b..ea07e55c84 100644 --- a/interface/src/networking/ClosureEventSender.h +++ b/interface/src/networking/ClosureEventSender.h @@ -24,8 +24,6 @@ class ClosureEventSender : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - void sendCrashEventSync(); - bool hasTimedOutQuitEvent(); bool hasFinishedQuitEvent() { return _hasFinishedQuitEvent; } From e3d8229abe032dc997522d4b5e7a0784d577acc4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 17:52:01 -0700 Subject: [PATCH 38/49] rename ClosureEventSender to CloseEventSender --- interface/src/Application.cpp | 18 +++++++++--------- ...ureEventSender.cpp => CloseEventSender.cpp} | 12 ++++++------ ...ClosureEventSender.h => CloseEventSender.h} | 10 +++++----- 3 files changed, 20 insertions(+), 20 deletions(-) rename interface/src/networking/{ClosureEventSender.cpp => CloseEventSender.cpp} (88%) rename interface/src/networking/{ClosureEventSender.h => CloseEventSender.h} (79%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a637f9414b..41b0bcaf04 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -146,7 +146,7 @@ #include "InterfaceLogging.h" #include "LODManager.h" #include "ModelPackager.h" -#include "networking/ClosureEventSender.h" +#include "networking/CloseEventSender.h" #include "networking/HFWebEngineProfile.h" #include "networking/HFTabletWebEngineProfile.h" #include "networking/FileTypeProfile.h" @@ -537,7 +537,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -1572,12 +1572,12 @@ void Application::aboutToQuit() { getActiveDisplayPlugin()->deactivate(); - // use the ClosureEventSender via a QThread to send an event that says the user asked for the app to close - auto closureEventSender = DependencyManager::get(); + // use the CloseEventSender via a QThread to send an event that says the user asked for the app to close + auto closeEventSender = DependencyManager::get(); QThread* closureEventThread = new QThread(this); - closureEventSender->moveToThread(closureEventThread); + closeEventSender->moveToThread(closureEventThread); // sendQuitEventAsync will bail immediately if the UserActivityLogger is not enabled - connect(closureEventThread, &QThread::started, closureEventSender.data(), &ClosureEventSender::sendQuitEventAsync); + connect(closureEventThread, &QThread::started, closeEventSender.data(), &CloseEventSender::sendQuitEventAsync); closureEventThread->start(); // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. @@ -1745,13 +1745,13 @@ Application::~Application() { _window->deleteLater(); // make sure that the quit event has finished sending before we take the application down - auto closureEventSender = DependencyManager::get(); - while (!closureEventSender->hasFinishedQuitEvent() && !closureEventSender->hasTimedOutQuitEvent()) { + auto closeEventSender = DependencyManager::get(); + while (!closeEventSender->hasFinishedQuitEvent() && !closeEventSender->hasTimedOutQuitEvent()) { // yield so we're not spinning std::this_thread::yield(); } // quit the thread used by the closure event sender - closureEventSender->thread()->quit(); + closeEventSender->thread()->quit(); // Can't log to file passed this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); diff --git a/interface/src/networking/ClosureEventSender.cpp b/interface/src/networking/CloseEventSender.cpp similarity index 88% rename from interface/src/networking/ClosureEventSender.cpp rename to interface/src/networking/CloseEventSender.cpp index 238629b809..8c3d6ae888 100644 --- a/interface/src/networking/ClosureEventSender.cpp +++ b/interface/src/networking/CloseEventSender.cpp @@ -1,5 +1,5 @@ // -// ClosureEventSender.cpp +// CloseEventSender.cpp // interface/src/networking // // Created by Stephen Birarda on 5/31/17. @@ -21,7 +21,7 @@ #include #include -#include "ClosureEventSender.h" +#include "CloseEventSender.h" QNetworkRequest createNetworkRequest() { @@ -58,17 +58,17 @@ QNetworkReply* replyForAction(QString action) { return networkAccessManager.post(createNetworkRequest(), postDataForAction(action)); } -void ClosureEventSender::sendQuitEventAsync() { +void CloseEventSender::sendQuitEventAsync() { if (UserActivityLogger::getInstance().isEnabled()) { QNetworkReply* reply = replyForAction("quit"); - connect(reply, &QNetworkReply::finished, this, &ClosureEventSender::handleQuitEventFinished); + connect(reply, &QNetworkReply::finished, this, &CloseEventSender::handleQuitEventFinished); _quitEventStartTimestamp = QDateTime::currentMSecsSinceEpoch(); } else { _hasFinishedQuitEvent = true; } } -void ClosureEventSender::handleQuitEventFinished() { +void CloseEventSender::handleQuitEventFinished() { _hasFinishedQuitEvent = true; auto reply = qobject_cast(sender()); @@ -81,7 +81,7 @@ void ClosureEventSender::handleQuitEventFinished() { reply->deleteLater(); } -bool ClosureEventSender::hasTimedOutQuitEvent() { +bool CloseEventSender::hasTimedOutQuitEvent() { const int CLOSURE_EVENT_TIMEOUT_MS = 5000; return _quitEventStartTimestamp != 0 && QDateTime::currentMSecsSinceEpoch() - _quitEventStartTimestamp > CLOSURE_EVENT_TIMEOUT_MS; diff --git a/interface/src/networking/ClosureEventSender.h b/interface/src/networking/CloseEventSender.h similarity index 79% rename from interface/src/networking/ClosureEventSender.h rename to interface/src/networking/CloseEventSender.h index ea07e55c84..05e6f81ad4 100644 --- a/interface/src/networking/ClosureEventSender.h +++ b/interface/src/networking/CloseEventSender.h @@ -1,5 +1,5 @@ // -// ClosureEventSender.h +// CloseEventSender.h // interface/src/networking // // Created by Stephen Birarda on 5/31/17. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_ClosureEventSender_h -#define hifi_ClosureEventSender_h +#ifndef hifi_CloseEventSender_h +#define hifi_CloseEventSender_h #include @@ -19,7 +19,7 @@ #include -class ClosureEventSender : public QObject, public Dependency { +class CloseEventSender : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -38,4 +38,4 @@ private: std::atomic _quitEventStartTimestamp; }; -#endif // hifi_ClosureEventSender_h +#endif // hifi_CloseEventSender_h From d89febac7197d7e840150bc62ef3118167981572 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 1 Jun 2017 17:57:23 -0700 Subject: [PATCH 39/49] use a sleep instead of a yield waiting for close event --- interface/src/Application.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 41b0bcaf04..27c158322d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -11,6 +11,7 @@ #include "Application.h" +#include #include #include @@ -1747,8 +1748,8 @@ Application::~Application() { // make sure that the quit event has finished sending before we take the application down auto closeEventSender = DependencyManager::get(); while (!closeEventSender->hasFinishedQuitEvent() && !closeEventSender->hasTimedOutQuitEvent()) { - // yield so we're not spinning - std::this_thread::yield(); + // sleep a little so we're not spinning at 100% + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } // quit the thread used by the closure event sender closeEventSender->thread()->quit(); From f9e1f028882492fc5a5e9ccc17416660e69cdfb4 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 2 Jun 2017 14:59:27 -0700 Subject: [PATCH 40/49] protect _text member of Text3DOverlay with mutex --- interface/src/ui/overlays/Text3DOverlay.cpp | 19 +++++++++++++++---- interface/src/ui/overlays/Text3DOverlay.h | 13 +++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 2e2d586abc..d7e4edb197 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -23,12 +23,13 @@ const float LINE_SCALE_RATIO = 1.2f; QString const Text3DOverlay::TYPE = "text3d"; -Text3DOverlay::Text3DOverlay() { +Text3DOverlay::Text3DOverlay() : _mutex() { _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); _geometryId = DependencyManager::get()->allocateID(); } Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : + _mutex(), Billboard3DOverlay(text3DOverlay), _text(text3DOverlay->_text), _backgroundColor(text3DOverlay->_backgroundColor), @@ -51,6 +52,16 @@ Text3DOverlay::~Text3DOverlay() { } } +const QString Text3DOverlay::getText() const { + QMutexLocker lock(&_mutex); + return _text; +} + +void Text3DOverlay::setText(const QString& text) { + QMutexLocker lock(&_mutex); + _text = text; +} + xColor Text3DOverlay::getBackgroundColor() { if (_colorPulse == 0.0f) { return _backgroundColor; @@ -125,7 +136,7 @@ void Text3DOverlay::render(RenderArgs* args) { // FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline // for a gpu performance increase. Currently, // Text renderer sets its own pipeline, - _textRenderer->draw(batch, 0, 0, _text, textColor, glm::vec2(-1.0f), getDrawInFront()); + _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront()); // so before we continue, we must reset the pipeline batch.setPipeline(args->_pipeline->pipeline); args->_pipeline->prepare(batch); @@ -188,7 +199,7 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) { QVariant Text3DOverlay::getProperty(const QString& property) { if (property == "text") { - return _text; + return getText(); } if (property == "textAlpha") { return _textAlpha; @@ -231,7 +242,7 @@ QSizeF Text3DOverlay::textSize(const QString& text) const { return QSizeF(extents.x, extents.y) * pointToWorldScale; } -bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, +bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, BoxFace &face, glm::vec3& surfaceNormal) { Transform transform = getTransform(); applyTransformTo(transform, true); diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 5ba4fe5939..e7b09c9040 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -12,14 +12,14 @@ #define hifi_Text3DOverlay_h #include - +#include #include "Billboard3DOverlay.h" class TextRenderer3D; class Text3DOverlay : public Billboard3DOverlay { Q_OBJECT - + public: static QString const TYPE; virtual QString getType() const override { return TYPE; } @@ -34,7 +34,7 @@ public: virtual const render::ShapeKey getShapeKey() override; // getters - const QString& getText() const { return _text; } + const QString getText() const; float getLineHeight() const { return _lineHeight; } float getLeftMargin() const { return _leftMargin; } float getTopMargin() const { return _topMargin; } @@ -45,7 +45,7 @@ public: float getBackgroundAlpha() { return getAlpha(); } // setters - void setText(const QString& text) { _text = text; } + void setText(const QString& text); void setTextAlpha(float alpha) { _textAlpha = alpha; } void setLineHeight(float value) { _lineHeight = value; } void setLeftMargin(float margin) { _leftMargin = margin; } @@ -58,15 +58,16 @@ public: QSizeF textSize(const QString& test) const; // Meters - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal) override; virtual Text3DOverlay* createClone() const override; private: TextRenderer3D* _textRenderer = nullptr; - + QString _text; + mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions xColor _backgroundColor = xColor { 0, 0, 0 }; float _textAlpha { 1.0f }; float _lineHeight { 1.0f }; From 9b34abeb40f200a708285e3f6d8ae76103510ca4 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 2 Jun 2017 15:43:29 -0700 Subject: [PATCH 41/49] oops initializer order... --- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index d7e4edb197..9df8d2beb9 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -29,9 +29,9 @@ Text3DOverlay::Text3DOverlay() : _mutex() { } Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : - _mutex(), Billboard3DOverlay(text3DOverlay), _text(text3DOverlay->_text), + _mutex(), _backgroundColor(text3DOverlay->_backgroundColor), _textAlpha(text3DOverlay->_textAlpha), _lineHeight(text3DOverlay->_lineHeight), From 12cbc206d2fc94f87e0df6916f27cf81df6b0a0e Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 2 Jun 2017 15:59:15 -0700 Subject: [PATCH 42/49] cr feedback --- interface/src/ui/overlays/Text3DOverlay.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 9df8d2beb9..ebc28ca86a 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -23,7 +23,7 @@ const float LINE_SCALE_RATIO = 1.2f; QString const Text3DOverlay::TYPE = "text3d"; -Text3DOverlay::Text3DOverlay() : _mutex() { +Text3DOverlay::Text3DOverlay() { _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); _geometryId = DependencyManager::get()->allocateID(); } @@ -31,7 +31,6 @@ Text3DOverlay::Text3DOverlay() : _mutex() { Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : Billboard3DOverlay(text3DOverlay), _text(text3DOverlay->_text), - _mutex(), _backgroundColor(text3DOverlay->_backgroundColor), _textAlpha(text3DOverlay->_textAlpha), _lineHeight(text3DOverlay->_lineHeight), From 52c60b35df8d68c945f86c3d5c281b499c6e9ae6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 2 Jun 2017 09:50:23 -0700 Subject: [PATCH 43/49] Add startup_sent_to user activity event --- interface/src/Application.cpp | 36 +++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 27c158322d..bf578fb28e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2404,15 +2404,16 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // Check HMD use (may be technically available without being in use) bool hasHMD = PluginUtils::isHMDAvailable(); - bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd(); + bool isUsingHMD = _displayPlugin->isHmd(); + bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD; Setting::Handle tutorialComplete{ "tutorialComplete", false }; Setting::Handle firstRun{ Settings::firstRun, true }; bool isTutorialComplete = tutorialComplete.get(); - bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete; + bool shouldGoToTutorial = isUsingHMDAndHandControllers && hasTutorialContent && !isTutorialComplete; - qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD; + qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers; qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent << ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial; @@ -2426,10 +2427,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { const QString TUTORIAL_PATH = "/tutorial_begin"; + static const QString SENT_TO_TUTORIAL = "tutorial"; + static const QString SENT_TO_PREVIOUS_LOCATION = "previous_location"; + static const QString SENT_TO_ENTRY = "entry"; + static const QString SENT_TO_SANDBOX = "sandbox"; + + QString sentTo; + if (shouldGoToTutorial) { if (sandboxIsRunning) { qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; DependencyManager::get()->goToLocalSandbox(TUTORIAL_PATH); + sentTo = SENT_TO_TUTORIAL; } else { qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry."; if (firstRun.get()) { @@ -2437,8 +2446,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { } if (addressLookupString.isEmpty()) { DependencyManager::get()->goToEntry(); + sentTo = SENT_TO_ENTRY; } else { DependencyManager::get()->loadSettings(addressLookupString); + sentTo = SENT_TO_PREVIOUS_LOCATION; } } } else { @@ -2451,23 +2462,40 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (isFirstRun) { - if (isUsingHMD) { + if (isUsingHMDAndHandControllers) { if (sandboxIsRunning) { qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; DependencyManager::get()->goToLocalSandbox(); + sentTo = SENT_TO_SANDBOX; } else { qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry."; DependencyManager::get()->goToEntry(); + sentTo = SENT_TO_ENTRY; } } else { DependencyManager::get()->goToEntry(); + sentTo = SENT_TO_ENTRY; } } else { qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString); DependencyManager::get()->loadSettings(addressLookupString); + sentTo = SENT_TO_PREVIOUS_LOCATION; } } + UserActivityLogger::getInstance().logAction("startup_sent_to", { + { "sent_to", sentTo }, + { "sandbox_is_running", sandboxIsRunning }, + { "has_hmd", hasHMD }, + { "has_hand_controllers", hasHandControllers }, + { "is_using_hmd", isUsingHMD }, + { "is_using_hmd_and_hand_controllers", isUsingHMDAndHandControllers }, + { "content_version", contentVersion }, + { "is_tutorial_complete", isTutorialComplete }, + { "has_tutorial_content", hasTutorialContent }, + { "should_go_to_tutorial", shouldGoToTutorial } + }); + _connectionMonitor.init(); // After all of the constructor is completed, then set firstRun to false. From 7da73d0ff11832b66ed8a5e81e0e650391da4ae1 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 2 Jun 2017 18:01:40 -0700 Subject: [PATCH 44/49] teleport.js should still function on avatars with no feet. --- scripts/system/controllers/teleport.js | 52 ++++++++------------------ 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index dcbcaeb621..d6248fc6e0 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -366,45 +366,25 @@ function Teleporter() { } // related to repositioning the avatar after you teleport +var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"]; +var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5; function getAvatarFootOffset() { - var data = getJointData(); - var upperLeg, lowerLeg, foot, toe, toeTop; - data.forEach(function(d) { - var jointName = d.joint; - if (jointName === "RightUpLeg") { - upperLeg = d.translation.y; - } else if (jointName === "RightLeg") { - lowerLeg = d.translation.y; - } else if (jointName === "RightFoot") { - foot = d.translation.y; - } else if (jointName === "RightToeBase") { - toe = d.translation.y; - } else if (jointName === "RightToe_End") { - toeTop = d.translation.y; + // find a valid foot jointIndex + var footJointIndex = -1; + var i, l = FOOT_JOINT_NAMES.length; + for (i = 0; i < l; i++) { + footJointIndex = MyAvatar.getJointIndex(FOOT_JOINT_NAMES[i]); + if (footJointIndex != -1) { + break; } - }); - - var offset = upperLeg + lowerLeg + foot + toe + toeTop; - offset = offset / 100; - return offset; -} - -function getJointData() { - var allJointData = []; - var jointNames = MyAvatar.jointNames; - jointNames.forEach(function(joint, index) { - var translation = MyAvatar.getJointTranslation(index); - var rotation = MyAvatar.getJointRotation(index); - allJointData.push({ - joint: joint, - index: index, - translation: translation, - rotation: rotation - }); - }); - - return allJointData; + } + if (footJointIndex != -1) { + // default vertical offset from foot to avatar root. + return -MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex).y; + } else { + return DEFAULT_ROOT_TO_FOOT_OFFSET; + } } var leftPad = new ThumbPad('left'); From 995fe11c05437f54e9a3eed78e809ac3dbb060c0 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Mon, 5 Jun 2017 14:03:20 -0700 Subject: [PATCH 45/49] Migrate to single QML engine --- interface/resources/qml/Browser.qml | 6 +- interface/resources/qml/TabletBrowser.qml | 6 +- .../qml/controls-uit/BaseWebView.qml | 3 - .../qml/controls/TabletWebScreen.qml | 6 +- .../resources/qml/controls/TabletWebView.qml | 6 +- .../resources/qml/controls/WebEntityView.qml | 6 +- interface/resources/qml/controls/WebView.qml | 6 +- interface/resources/qml/hifi/Desktop.qml | 6 - .../resources/qml/hifi/tablet/EditTabView.qml | 1 - .../resources/qml/hifi/tablet/TabletMenu.qml | 1 - .../resources/qml/hifi/tablet/TabletRoot.qml | 1 - interface/src/Application.cpp | 120 ++++++------- interface/src/ui/overlays/Web3DOverlay.cpp | 63 ++++--- .../src/RenderableWebEntityItem.cpp | 8 +- libraries/gl/CMakeLists.txt | 2 +- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 163 ++++++++++++------ libraries/gl/src/gl/OffscreenQmlSurface.h | 5 +- .../gl/src/gl/OffscreenQmlSurfaceCache.cpp | 1 - libraries/networking/CMakeLists.txt | 2 +- .../networking/src}/FileTypeProfile.cpp | 0 .../networking/src}/FileTypeProfile.h | 0 .../src}/FileTypeRequestInterceptor.cpp | 0 .../src}/FileTypeRequestInterceptor.h | 0 .../src}/HFTabletWebEngineProfile.cpp | 1 + .../src}/HFTabletWebEngineProfile.h | 0 .../HFTabletWebEngineRequestInterceptor.cpp | 2 +- .../HFTabletWebEngineRequestInterceptor.h | 0 .../networking/src}/HFWebEngineProfile.cpp | 1 + .../networking/src}/HFWebEngineProfile.h | 0 .../src}/HFWebEngineRequestInterceptor.cpp | 2 +- .../src}/HFWebEngineRequestInterceptor.h | 0 .../networking/src}/RequestFilters.cpp | 2 +- .../networking/src}/RequestFilters.h | 0 libraries/ui/src/OffscreenUi.cpp | 16 +- libraries/ui/src/VrMenu.cpp | 2 +- 35 files changed, 223 insertions(+), 215 deletions(-) rename {interface/src/networking => libraries/networking/src}/FileTypeProfile.cpp (100%) rename {interface/src/networking => libraries/networking/src}/FileTypeProfile.h (100%) rename {interface/src/networking => libraries/networking/src}/FileTypeRequestInterceptor.cpp (100%) rename {interface/src/networking => libraries/networking/src}/FileTypeRequestInterceptor.h (100%) rename {interface/src/networking => libraries/networking/src}/HFTabletWebEngineProfile.cpp (95%) rename {interface/src/networking => libraries/networking/src}/HFTabletWebEngineProfile.h (100%) rename {interface/src/networking => libraries/networking/src}/HFTabletWebEngineRequestInterceptor.cpp (98%) rename {interface/src/networking => libraries/networking/src}/HFTabletWebEngineRequestInterceptor.h (100%) rename {interface/src/networking => libraries/networking/src}/HFWebEngineProfile.cpp (94%) rename {interface/src/networking => libraries/networking/src}/HFWebEngineProfile.h (100%) rename {interface/src/networking => libraries/networking/src}/HFWebEngineRequestInterceptor.cpp (95%) rename {interface/src/networking => libraries/networking/src}/HFWebEngineRequestInterceptor.h (100%) rename {interface/src/networking => libraries/networking/src}/RequestFilters.cpp (98%) rename {interface/src/networking => libraries/networking/src}/RequestFilters.h (100%) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 47fb610469..4f7639dd0e 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -2,7 +2,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtWebChannel 1.0 import QtWebEngine 1.2 -import FileTypeProfile 1.0 import "controls-uit" import "styles" as HifiStyles @@ -209,6 +208,7 @@ ScrollingWindow { WebView { id: webview url: "https://highfidelity.com/" + profile: FileTypeProfile; property alias eventBridgeWrapper: eventBridgeWrapper @@ -218,10 +218,6 @@ ScrollingWindow { property var eventBridge; } - profile: FileTypeProfile { - id: webviewProfile - storageName: "qmlWebEngine" - } webChannel.registeredObjects: [eventBridgeWrapper] diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml index ee4d05a701..d89aa8626f 100644 --- a/interface/resources/qml/TabletBrowser.qml +++ b/interface/resources/qml/TabletBrowser.qml @@ -8,7 +8,6 @@ import "controls-uit" as HifiControls import "styles" as HifiStyles import "styles-uit" import "windows" -import HFTabletWebEngineProfile 1.0 Item { id: root @@ -47,10 +46,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: HFTabletWebEngineProfile { - id: webviewTabletProfile - storageName: "qmlTabletWebEngine" - } + profile: HFTabletWebEngineProfile; property string userScriptUrl: "" diff --git a/interface/resources/qml/controls-uit/BaseWebView.qml b/interface/resources/qml/controls-uit/BaseWebView.qml index 670aea71aa..3ca57f03bf 100644 --- a/interface/resources/qml/controls-uit/BaseWebView.qml +++ b/interface/resources/qml/controls-uit/BaseWebView.qml @@ -10,13 +10,10 @@ import QtQuick 2.5 import QtWebEngine 1.2 -import HFWebEngineProfile 1.0 WebEngineView { id: root - // profile: desktop.browserProfile - Component.onCompleted: { console.log("Connecting JS messaging to Hifi Logging") // Ensure the JS from the web-engine makes it to our logging diff --git a/interface/resources/qml/controls/TabletWebScreen.qml b/interface/resources/qml/controls/TabletWebScreen.qml index 93ded724a1..0b265f6fbb 100644 --- a/interface/resources/qml/controls/TabletWebScreen.qml +++ b/interface/resources/qml/controls/TabletWebScreen.qml @@ -2,7 +2,6 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls -import HFTabletWebEngineProfile 1.0 Item { property alias url: root.url @@ -39,10 +38,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: HFTabletWebEngineProfile { - id: webviewProfile - storageName: "qmlTabletWebEngine" - } + profile: HFTabletWebEngineProfile; property string userScriptUrl: "" diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 215ac68ac0..3b23cbc19e 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -2,7 +2,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.2 import QtWebChannel 1.0 -import HFTabletWebEngineProfile 1.0 import "../controls-uit" as HiFiControls import "../styles" as HifiStyles import "../styles-uit" @@ -150,10 +149,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight anchors.top: buttons.bottom - profile: HFTabletWebEngineProfile { - id: webviewTabletProfile - storageName: "qmlTabletWebEngine" - } + profile: HFTabletWebEngineProfile; property string userScriptUrl: "" diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index a3d5fe903b..3bd6aad053 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -10,13 +10,9 @@ import QtQuick 2.5 import "." -import FileTypeProfile 1.0 WebView { - viewProfile: FileTypeProfile { - id: webviewProfile - storageName: "qmlWebEngine" - } + viewProfile: FileTypeProfile; urlTag: "noDownload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 06766fa6ef..d08562eea3 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -2,7 +2,6 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls -import HFWebEngineProfile 1.0 Item { property alias url: root.url @@ -39,10 +38,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: HFWebEngineProfile { - id: webviewProfile - storageName: "qmlWebEngine" - } + profile: HFWebEngineProfile; property string userScriptUrl: "" diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 7857eda3c2..ea9ec2f6c9 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -2,7 +2,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.1; import Qt.labs.settings 1.0 -import HFWebEngineProfile 1.0 import "../desktop" as OriginalDesktop import ".." @@ -27,11 +26,6 @@ OriginalDesktop.Desktop { property alias toolWindow: toolWindow ToolWindow { id: toolWindow } - property var browserProfile: HFWebEngineProfile { - id: webviewProfile - storageName: "qmlWebEngine" - } - Action { text: "Open Browser" shortcut: "Ctrl+B" diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index 35f2b82f0f..d084f1c7b3 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -5,7 +5,6 @@ import QtWebChannel 1.0 import QtQuick.Controls.Styles 1.4 import "../../controls" import "../toolbars" -import HFWebEngineProfile 1.0 import QtGraphicalEffects 1.0 import "../../controls-uit" as HifiControls import "../../styles-uit" diff --git a/interface/resources/qml/hifi/tablet/TabletMenu.qml b/interface/resources/qml/hifi/tablet/TabletMenu.qml index af36f72c82..62b61d129b 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenu.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenu.qml @@ -4,7 +4,6 @@ import QtQuick.Controls 1.4 import QtQml 2.2 import QtWebChannel 1.0 import QtWebEngine 1.1 -import HFWebEngineProfile 1.0 import "." diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 97c8854c86..e7654d9ff1 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -1,7 +1,6 @@ import QtQuick 2.0 import Hifi 1.0 import QtQuick.Controls 1.4 -import HFTabletWebEngineProfile 1.0 import "../../dialogs" import "../../controls" diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 851c07c501..d6475c4b00 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -148,9 +148,6 @@ #include "LODManager.h" #include "ModelPackager.h" #include "networking/CloseEventSender.h" -#include "networking/HFWebEngineProfile.h" -#include "networking/HFTabletWebEngineProfile.h" -#include "networking/FileTypeProfile.h" #include "scripting/TestScriptingInterface.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AssetMappingsScriptingInterface.h" @@ -1852,14 +1849,10 @@ void Application::initializeUi() { UpdateDialog::registerType(); qmlRegisterType("Hifi", 1, 0, "Preference"); - qmlRegisterType("HFWebEngineProfile", 1, 0, "HFWebEngineProfile"); - qmlRegisterType("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile"); - qmlRegisterType("FileTypeProfile", 1, 0, "FileTypeProfile"); - auto offscreenUi = DependencyManager::get(); offscreenUi->create(_glWidget->qglContext()); - auto rootContext = offscreenUi->getRootContext(); + auto surfaceContext = offscreenUi->getSurfaceContext(); offscreenUi->setProxyWindow(_window->windowHandle()); offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); @@ -1871,7 +1864,7 @@ void Application::initializeUi() { // do better detection in the offscreen UI of what has focus offscreenUi->setNavigationFocused(false); - auto engine = rootContext->engine(); + auto engine = surfaceContext->engine(); connect(engine, &QQmlEngine::quit, [] { qApp->quit(); }); @@ -1880,79 +1873,78 @@ void Application::initializeUi() { // For some reason there is already an "Application" object in the QML context, // though I can't find it. Hence, "ApplicationInterface" - rootContext->setContextProperty("ApplicationInterface", this); - rootContext->setContextProperty("Audio", DependencyManager::get().data()); - rootContext->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); - rootContext->setContextProperty("AudioScope", DependencyManager::get().data()); + surfaceContext->setContextProperty("Audio", DependencyManager::get().data()); + surfaceContext->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); + surfaceContext->setContextProperty("AudioScope", DependencyManager::get().data()); - rootContext->setContextProperty("Controller", DependencyManager::get().data()); - rootContext->setContextProperty("Entities", DependencyManager::get().data()); + surfaceContext->setContextProperty("Controller", DependencyManager::get().data()); + surfaceContext->setContextProperty("Entities", DependencyManager::get().data()); _fileDownload = new FileScriptingInterface(engine); - rootContext->setContextProperty("File", _fileDownload); + surfaceContext->setContextProperty("File", _fileDownload); connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip); - rootContext->setContextProperty("MyAvatar", getMyAvatar().get()); - rootContext->setContextProperty("Messages", DependencyManager::get().data()); - rootContext->setContextProperty("Recording", DependencyManager::get().data()); - rootContext->setContextProperty("Preferences", DependencyManager::get().data()); - rootContext->setContextProperty("AddressManager", DependencyManager::get().data()); - rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface); - rootContext->setContextProperty("Rates", new RatesScriptingInterface(this)); - rootContext->setContextProperty("pathToFonts", "../../"); + surfaceContext->setContextProperty("MyAvatar", getMyAvatar().get()); + surfaceContext->setContextProperty("Messages", DependencyManager::get().data()); + surfaceContext->setContextProperty("Recording", DependencyManager::get().data()); + surfaceContext->setContextProperty("Preferences", DependencyManager::get().data()); + surfaceContext->setContextProperty("AddressManager", DependencyManager::get().data()); + surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface); + surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this)); - rootContext->setContextProperty("TREE_SCALE", TREE_SCALE); - rootContext->setContextProperty("Quat", new Quat()); - rootContext->setContextProperty("Vec3", new Vec3()); - rootContext->setContextProperty("Uuid", new ScriptUUID()); - rootContext->setContextProperty("Assets", DependencyManager::get().data()); + surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE); + // FIXME Quat and Vec3 won't work with QJSEngine used by QML + surfaceContext->setContextProperty("Quat", new Quat()); + surfaceContext->setContextProperty("Vec3", new Vec3()); + surfaceContext->setContextProperty("Uuid", new ScriptUUID()); + surfaceContext->setContextProperty("Assets", DependencyManager::get().data()); - rootContext->setContextProperty("AvatarList", DependencyManager::get().data()); - rootContext->setContextProperty("Users", DependencyManager::get().data()); + surfaceContext->setContextProperty("AvatarList", DependencyManager::get().data()); + surfaceContext->setContextProperty("Users", DependencyManager::get().data()); - rootContext->setContextProperty("UserActivityLogger", DependencyManager::get().data()); + surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get().data()); - rootContext->setContextProperty("Camera", &_myCamera); + surfaceContext->setContextProperty("Camera", &_myCamera); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) - rootContext->setContextProperty("SpeechRecognizer", DependencyManager::get().data()); + surfaceContext->setContextProperty("SpeechRecognizer", DependencyManager::get().data()); #endif - rootContext->setContextProperty("Overlays", &_overlays); - rootContext->setContextProperty("Window", DependencyManager::get().data()); - rootContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); - rootContext->setContextProperty("Stats", Stats::getInstance()); - rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); - rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); - rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); - rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get().data()); - rootContext->setContextProperty("LocationBookmarks", DependencyManager::get().data()); + surfaceContext->setContextProperty("Overlays", &_overlays); + surfaceContext->setContextProperty("Window", DependencyManager::get().data()); + surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); + surfaceContext->setContextProperty("Stats", Stats::getInstance()); + surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); + surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); + surfaceContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); + surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get().data()); + surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get().data()); // Caches - rootContext->setContextProperty("AnimationCache", DependencyManager::get().data()); - rootContext->setContextProperty("TextureCache", DependencyManager::get().data()); - rootContext->setContextProperty("ModelCache", DependencyManager::get().data()); - rootContext->setContextProperty("SoundCache", DependencyManager::get().data()); + surfaceContext->setContextProperty("AnimationCache", DependencyManager::get().data()); + surfaceContext->setContextProperty("TextureCache", DependencyManager::get().data()); + surfaceContext->setContextProperty("ModelCache", DependencyManager::get().data()); + surfaceContext->setContextProperty("SoundCache", DependencyManager::get().data()); - rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); - rootContext->setContextProperty("Tablet", DependencyManager::get().data()); - rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); - rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); - rootContext->setContextProperty("FaceTracker", DependencyManager::get().data()); - rootContext->setContextProperty("AvatarManager", DependencyManager::get().data()); - rootContext->setContextProperty("UndoStack", &_undoStackScriptingInterface); - rootContext->setContextProperty("LODManager", DependencyManager::get().data()); - rootContext->setContextProperty("Paths", DependencyManager::get().data()); - rootContext->setContextProperty("HMD", DependencyManager::get().data()); - rootContext->setContextProperty("Scene", DependencyManager::get().data()); - rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); - rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); - rootContext->setContextProperty("Snapshot", DependencyManager::get().data()); + surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); + surfaceContext->setContextProperty("Tablet", DependencyManager::get().data()); + surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); + surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); + surfaceContext->setContextProperty("FaceTracker", DependencyManager::get().data()); + surfaceContext->setContextProperty("AvatarManager", DependencyManager::get().data()); + surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface); + surfaceContext->setContextProperty("LODManager", DependencyManager::get().data()); + surfaceContext->setContextProperty("Paths", DependencyManager::get().data()); + surfaceContext->setContextProperty("HMD", DependencyManager::get().data()); + surfaceContext->setContextProperty("Scene", DependencyManager::get().data()); + surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); + surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); + surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); - rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); + surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); - rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); + surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { - rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); + surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 75c793bf77..e26a641206 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -135,7 +135,7 @@ Web3DOverlay::~Web3DOverlay() { void Web3DOverlay::update(float deltatime) { if (_webSurface) { // update globalPosition - _webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } } @@ -163,57 +163,56 @@ void Web3DOverlay::loadSourceURL() { _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _url); _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); - _webSurface->getRootContext()->setContextProperty("ApplicationInterface", qApp); } else { _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); _webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {}); _webSurface->resume(); - _webSurface->getRootContext()->setContextProperty("Users", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("UserActivityLogger", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("Preferences", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("Vec3", new Vec3()); - _webSurface->getRootContext()->setContextProperty("Quat", new Quat()); - _webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); - _webSurface->getRootContext()->setContextProperty("Entities", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("Snapshot", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3()); + _webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat()); + _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); + _webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get().data()); if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { auto tabletScriptingInterface = DependencyManager::get(); auto flags = tabletScriptingInterface->getFlags(); - _webSurface->getRootContext()->setContextProperty("offscreenFlags", flags); - _webSurface->getRootContext()->setContextProperty("AddressManager", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("Account", AccountScriptingInterface::getInstance()); - _webSurface->getRootContext()->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); - _webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("fileDialogHelper", new FileDialogHelper()); - _webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); - _webSurface->getRootContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("Tablet", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("Assets", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("LODManager", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("OctreeStats", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("DCModel", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); - _webSurface->getRootContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); - _webSurface->getRootContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); - _webSurface->getRootContext()->setContextProperty("AvatarList", DependencyManager::get().data()); - _webSurface->getRootContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags); + _webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); + _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get().data()); + _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()); + _webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance()); - _webSurface->getRootContext()->setContextProperty("pathToFonts", "../../"); + _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../"); tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data()); // mark the TabletProxy object as cpp ownership. QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); - _webSurface->getRootContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); + _webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); // Override min fps for tablet UI, for silky smooth scrolling setMaxFPS(90); } } - _webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } void Web3DOverlay::setMaxFPS(uint8_t maxFPS) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 0d286c46eb..3b3480443d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -127,7 +127,7 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); - _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); + _webSurface->getSurfaceContext()->setContextProperty("desktop", QVariant()); // FIXME - Keyboard HMD only: Possibly add "HMDinfo" object to context for WebView.qml. // forward web events to EntityScriptingInterface @@ -271,7 +271,7 @@ void RenderableWebEntityItem::loadSourceURL() { }); _webSurface->getRootItem()->setProperty("url", _sourceUrl); - _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); + _webSurface->getSurfaceContext()->setContextProperty("desktop", QVariant()); } else { _contentType = qmlContent; @@ -284,7 +284,7 @@ void RenderableWebEntityItem::loadSourceURL() { _webSurface->getRootItem(), _webSurface.data()); } } - _webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } @@ -420,7 +420,7 @@ void RenderableWebEntityItem::update(const quint64& now) { if (_webSurface) { // update globalPosition - _webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } auto interval = now - _lastRenderTime; diff --git a/libraries/gl/CMakeLists.txt b/libraries/gl/CMakeLists.txt index 3e2097e89e..fd3197410b 100644 --- a/libraries/gl/CMakeLists.txt +++ b/libraries/gl/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME gl) setup_hifi_library(OpenGL Qml Quick) -link_hifi_libraries(shared) +link_hifi_libraries(shared networking) target_opengl() diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 3bbd26e010..65c311424f 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include #include "OffscreenGLCanvas.h" #include "GLHelpers.h" @@ -41,6 +44,7 @@ Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml") Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl") +Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus") struct TextureSet { // The number of surfaces with this size @@ -254,8 +258,72 @@ QNetworkAccessManager* QmlNetworkAccessManagerFactory::create(QObject* parent) { return new QmlNetworkAccessManager(parent); } -Q_DECLARE_LOGGING_CATEGORY(offscreenFocus) -Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus") +static QQmlEngine* globalEngine { nullptr }; +static size_t globalEngineRefCount { 0 }; + +QString getEventBridgeJavascript() { + // FIXME: Refactor with similar code in RenderableWebEntityItem + QString javaScriptToInject; + QFile webChannelFile(":qtwebchannel/qwebchannel.js"); + QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js"); + if (webChannelFile.open(QFile::ReadOnly | QFile::Text) && + createGlobalEventBridgeFile.open(QFile::ReadOnly | QFile::Text)) { + QString webChannelStr = QTextStream(&webChannelFile).readAll(); + QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll(); + javaScriptToInject = webChannelStr + createGlobalEventBridgeStr; + } else { + qCWarning(glLogging) << "Unable to find qwebchannel.js or createGlobalEventBridge.js"; + } + return javaScriptToInject; +} + + +QQmlEngine* acquireEngine(QQuickWindow* window) { + Q_ASSERT(QThread::currentThread() == qApp->thread()); + if (!globalEngine) { + Q_ASSERT(0 == globalEngineRefCount); + globalEngine = new QQmlEngine(); + globalEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory); + + auto importList = globalEngine->importPathList(); + importList.insert(importList.begin(), PathUtils::resourcesPath()); + globalEngine->setImportPathList(importList); + for (const auto& path : importList) { + qDebug() << path; + } + + if (!globalEngine->incubationController()) { + globalEngine->setIncubationController(window->incubationController()); + } + auto rootContext = globalEngine->rootContext(); + rootContext->setContextProperty("GL", ::getGLContextData()); + rootContext->setContextProperty("urlHandler", new UrlHandler()); + rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath())); + rootContext->setContextProperty("pathToFonts", "../../"); + rootContext->setContextProperty("ApplicationInterface", qApp); + auto javaScriptToInject = getEventBridgeJavascript(); + if (!javaScriptToInject.isEmpty()) { + rootContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); + } + rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext)); + rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext)); + rootContext->setContextProperty("HFTabletWebEngineProfile", new HFTabletWebEngineProfile(rootContext)); + + + } + + ++globalEngineRefCount; + return globalEngine; +} + +void releaseEngine() { + Q_ASSERT(QThread::currentThread() == qApp->thread()); + Q_ASSERT(0 != globalEngineRefCount); + if (0 == --globalEngineRefCount) { + globalEngine->deleteLater(); + globalEngine = nullptr; + } +} void OffscreenQmlSurface::cleanup() { _canvas->makeCurrent(); @@ -294,6 +362,7 @@ void OffscreenQmlSurface::render() { GLuint texture = offscreenTextures.getNextTexture(_size); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _renderControl->render(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, texture); @@ -362,8 +431,8 @@ OffscreenQmlSurface::~OffscreenQmlSurface() { _canvas->deleteLater(); _rootItem->deleteLater(); _qmlComponent->deleteLater(); - _qmlEngine->deleteLater(); _quickWindow->deleteLater(); + releaseEngine(); } void OffscreenQmlSurface::onAboutToQuit() { @@ -375,6 +444,8 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { qCDebug(glLogging) << "Building QML surface"; _renderControl = new QMyQuickRenderControl(); + connect(_renderControl, &QQuickRenderControl::renderRequested, this, [this] { _render = true; }); + connect(_renderControl, &QQuickRenderControl::sceneChanged, this, [this] { _render = _polish = true; }); QQuickWindow::setDefaultAlphaBuffer(true); @@ -385,7 +456,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { // so we wait until after its ctor to move object/context to this thread. _quickWindow = new QQuickWindow(_renderControl); _quickWindow->setColor(QColor(255, 255, 255, 0)); - _quickWindow->setFlags(_quickWindow->flags() | static_cast(Qt::WA_TranslucentBackground)); + _quickWindow->setClearBeforeRendering(false); _renderControl->_renderWindow = _proxyWindow; @@ -398,32 +469,20 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, &OffscreenQmlSurface::onFocusObjectChanged); // Create a QML engine. - _qmlEngine = new QQmlEngine; + auto qmlEngine = acquireEngine(_quickWindow); + _qmlContext = new QQmlContext(qmlEngine->rootContext()); - _qmlEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory); + _qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); + _qmlContext->setContextProperty("globalEventBridge", this); + _qmlContext->setContextProperty("webEntity", this); - auto importList = _qmlEngine->importPathList(); - importList.insert(importList.begin(), PathUtils::resourcesPath()); - _qmlEngine->setImportPathList(importList); - if (!_qmlEngine->incubationController()) { - _qmlEngine->setIncubationController(_quickWindow->incubationController()); - } + _qmlComponent = new QQmlComponent(qmlEngine); - // FIXME - _glData = ::getGLContextData(); // Initialize JSON structure so that it can be filled in later and then used in QML. - _qmlEngine->rootContext()->setContextProperty("GL", _glData); - _qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); - _qmlComponent = new QQmlComponent(_qmlEngine); - - - connect(_renderControl, &QQuickRenderControl::renderRequested, this, [this] { _render = true; }); - connect(_renderControl, &QQuickRenderControl::sceneChanged, this, [this] { _render = _polish = true; }); if (!_canvas->makeCurrent()) { qWarning("Failed to make context current for QML Renderer"); return; } - _glData = ::getGLContextData(); _renderControl->initialize(_canvas->getContext()); // When Quick says there is a need to render, we will not render immediately. Instead, @@ -433,11 +492,6 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { _updateTimer.setTimerType(Qt::PreciseTimer); _updateTimer.setInterval(MIN_TIMER_MS); // 5ms, Qt::PreciseTimer required _updateTimer.start(); - - auto rootContext = getRootContext(); - rootContext->setContextProperty("urlHandler", new UrlHandler()); - rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath())); - rootContext->setContextProperty("pathToFonts", "../../"); } static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) { @@ -460,7 +514,7 @@ void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) { return; } - _qmlEngine->rootContext()->setContextProperty("surfaceSize", newSize); + _qmlContext->setContextProperty("surfaceSize", newSize); if (_rootItem) { _rootItem->setSize(newSize); @@ -520,14 +574,19 @@ QQuickItem* OffscreenQmlSurface::getRootItem() { } void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) { - _qmlEngine->setBaseUrl(baseUrl); + _qmlContext->setBaseUrl(baseUrl); } QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function f) { // Synchronous loading may take a while; restart the deadlock timer QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection); - _qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous); + if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) { + _qmlComponent->loadUrl(_qmlContext->resolvedUrl(qmlSource), QQmlComponent::PreferSynchronous); + } else { + _qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous); + } + if (_qmlComponent->isLoading()) { connect(_qmlComponent, &QQmlComponent::statusChanged, this, @@ -541,10 +600,22 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::functionengine()->clearComponentCache(); + _qmlContext->engine()->clearComponentCache(); } QObject* OffscreenQmlSurface::finishQmlLoad(std::function f) { +#if 0 + if (!_rootItem) { + QQmlComponent component(_qmlContext->engine()); + component.setData(R"QML( +import QtQuick 2.0 +import QtWebChannel 1.0 +Item { Component.onCompleted: globalEventBridge.WebChannel.id = "globalEventBridge"; } +)QML", QUrl()); + QObject *helper = component.create(_qmlContext); + qDebug() << "Created helper"; + } +#endif disconnect(_qmlComponent, &QQmlComponent::statusChanged, this, 0); if (_qmlComponent->isError()) { QList errorList = _qmlComponent->errors(); @@ -554,21 +625,8 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionbeginCreate(newContext); + QObject* newObject = _qmlComponent->beginCreate(_qmlContext); if (_qmlComponent->isError()) { QList errorList = _qmlComponent->errors(); foreach(const QQmlError& error, errorList) @@ -579,12 +637,10 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionsetObjectOwnership(this, QQmlEngine::CppOwnership); + _qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership); newObject->setProperty("eventBridge", QVariant::fromValue(this)); - newContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); - - f(newContext, newObject); + f(_qmlContext, newObject); _qmlComponent->completeCreate(); @@ -735,7 +791,7 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); if (event->type() == QEvent::MouseMove) { - _qmlEngine->rootContext()->setContextProperty("lastMousePosition", transformedPos); + _qmlContext->setContextProperty("lastMousePosition", transformedPos); } mappedEvent.ignore(); if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { @@ -762,9 +818,6 @@ void OffscreenQmlSurface::resume() { if (getRootItem()) { getRootItem()->setProperty("eventBridge", QVariant::fromValue(this)); } - if (getRootContext()) { - getRootContext()->setContextProperty("webEntity", this); - } } bool OffscreenQmlSurface::isPaused() const { @@ -790,8 +843,8 @@ QSize OffscreenQmlSurface::size() const { return _quickWindow->geometry().size(); } -QQmlContext* OffscreenQmlSurface::getRootContext() { - return _qmlEngine->rootContext(); +QQmlContext* OffscreenQmlSurface::getSurfaceContext() { + return _qmlContext; } Q_DECLARE_METATYPE(std::function); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index efd35fce8b..2a078d2b4f 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -73,7 +73,7 @@ public: QQuickItem* getRootItem(); QQuickWindow* getWindow(); QObject* getEventHandler(); - QQmlContext* getRootContext(); + QQmlContext* getSurfaceContext(); QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); bool eventFilter(QObject* originalDestination, QEvent* event) override; @@ -133,11 +133,10 @@ private slots: private: QQuickWindow* _quickWindow { nullptr }; QMyQuickRenderControl* _renderControl{ nullptr }; - QQmlEngine* _qmlEngine { nullptr }; + QQmlContext* _qmlContext { nullptr }; QQmlComponent* _qmlComponent { nullptr }; QQuickItem* _rootItem { nullptr }; OffscreenGLCanvas* _canvas { nullptr }; - QJsonObject _glData; QTimer _updateTimer; uint32_t _fbo { 0 }; diff --git a/libraries/gl/src/gl/OffscreenQmlSurfaceCache.cpp b/libraries/gl/src/gl/OffscreenQmlSurfaceCache.cpp index ad370a1f43..c047738e77 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurfaceCache.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurfaceCache.cpp @@ -49,7 +49,6 @@ QSharedPointer OffscreenQmlSurfaceCache::buildSurface(const surface->create(currentContext); surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); surface->load(rootSource); - surface->getRootContext()->setContextProperty("ApplicationInterface", qApp); surface->resize(QSize(100, 100)); currentContext->makeCurrent(currentSurface); return surface; diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 288e98d5a5..ff9a05b959 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME networking) -setup_hifi_library(Network) +setup_hifi_library(Network WebEngine) link_hifi_libraries(shared) target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes") diff --git a/interface/src/networking/FileTypeProfile.cpp b/libraries/networking/src/FileTypeProfile.cpp similarity index 100% rename from interface/src/networking/FileTypeProfile.cpp rename to libraries/networking/src/FileTypeProfile.cpp diff --git a/interface/src/networking/FileTypeProfile.h b/libraries/networking/src/FileTypeProfile.h similarity index 100% rename from interface/src/networking/FileTypeProfile.h rename to libraries/networking/src/FileTypeProfile.h diff --git a/interface/src/networking/FileTypeRequestInterceptor.cpp b/libraries/networking/src/FileTypeRequestInterceptor.cpp similarity index 100% rename from interface/src/networking/FileTypeRequestInterceptor.cpp rename to libraries/networking/src/FileTypeRequestInterceptor.cpp diff --git a/interface/src/networking/FileTypeRequestInterceptor.h b/libraries/networking/src/FileTypeRequestInterceptor.h similarity index 100% rename from interface/src/networking/FileTypeRequestInterceptor.h rename to libraries/networking/src/FileTypeRequestInterceptor.h diff --git a/interface/src/networking/HFTabletWebEngineProfile.cpp b/libraries/networking/src/HFTabletWebEngineProfile.cpp similarity index 95% rename from interface/src/networking/HFTabletWebEngineProfile.cpp rename to libraries/networking/src/HFTabletWebEngineProfile.cpp index 46634299bb..a3e3906497 100644 --- a/interface/src/networking/HFTabletWebEngineProfile.cpp +++ b/libraries/networking/src/HFTabletWebEngineProfile.cpp @@ -19,6 +19,7 @@ HFTabletWebEngineProfile::HFTabletWebEngineProfile(QObject* parent) : QQuickWebE static const QString WEB_ENGINE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; setHttpUserAgent(WEB_ENGINE_USER_AGENT); + setStorageName(QML_WEB_ENGINE_NAME); auto requestInterceptor = new HFTabletWebEngineRequestInterceptor(this); setRequestInterceptor(requestInterceptor); diff --git a/interface/src/networking/HFTabletWebEngineProfile.h b/libraries/networking/src/HFTabletWebEngineProfile.h similarity index 100% rename from interface/src/networking/HFTabletWebEngineProfile.h rename to libraries/networking/src/HFTabletWebEngineProfile.h diff --git a/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp b/libraries/networking/src/HFTabletWebEngineRequestInterceptor.cpp similarity index 98% rename from interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp rename to libraries/networking/src/HFTabletWebEngineRequestInterceptor.cpp index fd79fc1cb6..6ee8589615 100644 --- a/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp +++ b/libraries/networking/src/HFTabletWebEngineRequestInterceptor.cpp @@ -11,7 +11,7 @@ #include "HFTabletWebEngineRequestInterceptor.h" #include -#include +#include "AccountManager.h" bool isTabletAuthableHighFidelityURL(const QUrl& url) { static const QStringList HF_HOSTS = { diff --git a/interface/src/networking/HFTabletWebEngineRequestInterceptor.h b/libraries/networking/src/HFTabletWebEngineRequestInterceptor.h similarity index 100% rename from interface/src/networking/HFTabletWebEngineRequestInterceptor.h rename to libraries/networking/src/HFTabletWebEngineRequestInterceptor.h diff --git a/interface/src/networking/HFWebEngineProfile.cpp b/libraries/networking/src/HFWebEngineProfile.cpp similarity index 94% rename from interface/src/networking/HFWebEngineProfile.cpp rename to libraries/networking/src/HFWebEngineProfile.cpp index 6b377fa900..a69d4d653b 100644 --- a/interface/src/networking/HFWebEngineProfile.cpp +++ b/libraries/networking/src/HFWebEngineProfile.cpp @@ -20,6 +20,7 @@ HFWebEngineProfile::HFWebEngineProfile(QObject* parent) : { static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)"; setHttpUserAgent(WEB_ENGINE_USER_AGENT); + setStorageName(QML_WEB_ENGINE_STORAGE_NAME); // we use the HFWebEngineRequestInterceptor to make sure that web requests are authenticated for the interface user auto requestInterceptor = new HFWebEngineRequestInterceptor(this); diff --git a/interface/src/networking/HFWebEngineProfile.h b/libraries/networking/src/HFWebEngineProfile.h similarity index 100% rename from interface/src/networking/HFWebEngineProfile.h rename to libraries/networking/src/HFWebEngineProfile.h diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/libraries/networking/src/HFWebEngineRequestInterceptor.cpp similarity index 95% rename from interface/src/networking/HFWebEngineRequestInterceptor.cpp rename to libraries/networking/src/HFWebEngineRequestInterceptor.cpp index 59897d427f..eaf0de7245 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/libraries/networking/src/HFWebEngineRequestInterceptor.cpp @@ -13,7 +13,7 @@ #include -#include +#include "AccountManager.h" #include "RequestFilters.h" void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.h b/libraries/networking/src/HFWebEngineRequestInterceptor.h similarity index 100% rename from interface/src/networking/HFWebEngineRequestInterceptor.h rename to libraries/networking/src/HFWebEngineRequestInterceptor.h diff --git a/interface/src/networking/RequestFilters.cpp b/libraries/networking/src/RequestFilters.cpp similarity index 98% rename from interface/src/networking/RequestFilters.cpp rename to libraries/networking/src/RequestFilters.cpp index fedde94f15..3e72b8a8bd 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/libraries/networking/src/RequestFilters.cpp @@ -14,7 +14,7 @@ #include -#include +#include "AccountManager.h" namespace { diff --git a/interface/src/networking/RequestFilters.h b/libraries/networking/src/RequestFilters.h similarity index 100% rename from interface/src/networking/RequestFilters.h rename to libraries/networking/src/RequestFilters.h diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 84812b4f60..a80105293b 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -91,14 +91,14 @@ QObject* OffscreenUi::getFlags() { void OffscreenUi::create(QOpenGLContext* context) { OffscreenQmlSurface::create(context); - auto rootContext = getRootContext(); + auto myContext = getSurfaceContext(); - rootContext->setContextProperty("OffscreenUi", this); - rootContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags()); - rootContext->setContextProperty("fileDialogHelper", new FileDialogHelper()); + myContext->setContextProperty("OffscreenUi", this); + myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags()); + myContext->setContextProperty("fileDialogHelper", new FileDialogHelper()); auto tabletScriptingInterface = DependencyManager::get(); TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); - rootContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); + myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } void OffscreenUi::show(const QUrl& url, const QString& name, std::function f) { @@ -547,14 +547,14 @@ void OffscreenUi::createDesktop(const QUrl& url) { } #ifdef DEBUG - getRootContext()->setContextProperty("DebugQML", QVariant(true)); + getSurfaceContext()->setContextProperty("DebugQML", QVariant(true)); #else - getRootContext()->setContextProperty("DebugQML", QVariant(false)); + getSurfaceContext()->setContextProperty("DebugQML", QVariant(false)); #endif _desktop = dynamic_cast(load(url)); Q_ASSERT(_desktop); - getRootContext()->setContextProperty("desktop", _desktop); + getSurfaceContext()->setContextProperty("desktop", _desktop); _toolWindow = _desktop->findChild("ToolWindow"); diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index 878514dd41..3959e950e9 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -115,7 +115,7 @@ private: VrMenu::VrMenu(OffscreenUi* parent) : QObject(parent) { _rootMenu = parent->getRootItem()->findChild("rootMenu"); - parent->getRootContext()->setContextProperty("rootMenu", _rootMenu); + parent->getSurfaceContext()->setContextProperty("rootMenu", _rootMenu); } QObject* VrMenu::findMenuObject(const QString& menuOption) { From 90d241ca3c643ff5d0adec8afc5dbd4de83200b6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 6 Jun 2017 09:10:46 -0700 Subject: [PATCH 46/49] Account for avatar scale --- scripts/system/controllers/teleport.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index d6248fc6e0..b058ec670f 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -383,7 +383,7 @@ function getAvatarFootOffset() { // default vertical offset from foot to avatar root. return -MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex).y; } else { - return DEFAULT_ROOT_TO_FOOT_OFFSET; + return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale; } } From c3621d7c325c634d2b53e09eec78641b4ed0454f Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Tue, 6 Jun 2017 22:31:14 +0530 Subject: [PATCH 47/49] Resolved two issues: 1) While in HMD mode -> open Tablet -> Click Desktop. Desktop mode will be on. 2) Menu sync problem while switching modes. --- interface/src/Application.cpp | 13 +++++++------ interface/src/Application.h | 2 +- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 6 +++--- .../src/display-plugins/OpenGLDisplayPlugin.h | 4 ++-- libraries/plugins/src/plugins/Plugin.h | 14 +++++++------- plugins/oculus/src/OculusBaseDisplayPlugin.cpp | 4 +--- plugins/oculus/src/OculusBaseDisplayPlugin.h | 2 +- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c681f99ee2..314c51a4f2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1360,7 +1360,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (_autoSwitchDisplayModeSupportedHMDPlugin) { if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin && - !_autoSwitchDisplayModeSupportedHMDPlugin->isStandBySessionActive()) { + !_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { startHMDStandBySession(); } // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly. @@ -1602,8 +1602,8 @@ void Application::aboutToQuit() { getActiveDisplayPlugin()->deactivate(); if (_autoSwitchDisplayModeSupportedHMDPlugin - && _autoSwitchDisplayModeSupportedHMDPlugin->isStandBySessionActive()) { - _autoSwitchDisplayModeSupportedHMDPlugin->endStandBySession(); + && _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { + _autoSwitchDisplayModeSupportedHMDPlugin->endSession(); } // use the CloseEventSender via a QThread to send an event that says the user asked for the app to close auto closeEventSender = DependencyManager::get(); @@ -6827,13 +6827,14 @@ void Application::switchDisplayMode() { // Switch to respective mode as soon as currentHMDWornStatus changes if (currentHMDWornStatus) { qCDebug(interfaceapp) << "Switching from Desktop to HMD mode"; - endHMDStandBySession(); + endHMDSession(); setActiveDisplayPlugin(_autoSwitchDisplayModeSupportedHMDPluginName); } else { qCDebug(interfaceapp) << "Switching from HMD to desktop mode"; setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME); startHMDStandBySession(); } + emit activeDisplayPluginChanged(); } _previousHMDWornStatus = currentHMDWornStatus; } @@ -6842,8 +6843,8 @@ void Application::startHMDStandBySession() { _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession(); } -void Application::endHMDStandBySession() { - _autoSwitchDisplayModeSupportedHMDPlugin->endStandBySession(); +void Application::endHMDSession() { + _autoSwitchDisplayModeSupportedHMDPlugin->endSession(); } mat4 Application::getEyeProjection(int eye) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 4cd47ada58..46e5e882a4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -685,6 +685,6 @@ private: QString _autoSwitchDisplayModeSupportedHMDPluginName; bool _previousHMDWornStatus; void startHMDStandBySession(); - void endHMDStandBySession(); + void endHMDSession(); }; #endif // hifi_Application_h diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index fbdc1ad71e..bfd158ffb5 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -346,9 +346,9 @@ bool OpenGLDisplayPlugin::startStandBySession() { return Parent::startStandBySession(); } -void OpenGLDisplayPlugin::endStandBySession() { - deactivateStandBySession(); - Parent::endStandBySession(); +void OpenGLDisplayPlugin::endSession() { + deactivateSession(); + Parent::endSession(); } void OpenGLDisplayPlugin::customizeContext() { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 9681158c55..10a7558398 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -43,7 +43,7 @@ public: bool activate() override final; void deactivate() override final; bool startStandBySession() override final; - void endStandBySession() override final; + void endSession() override final; bool eventFilter(QObject* receiver, QEvent* event) override; bool isDisplayVisible() const override { return true; } @@ -104,7 +104,7 @@ protected: // Returns true on successful activation of standby session virtual bool activateStandBySession() { return true; } - virtual void deactivateStandBySession() {} + virtual void deactivateSession() {} // Plugin specific functionality to send the composed scene to the output window or device virtual void internalPresent(); diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index 11ea79186a..2d4a24a1fe 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -54,16 +54,16 @@ public: return _active; } virtual bool startStandBySession() { - _standbysessionstatus = true; - return _standbysessionstatus; + _sessionStatus = true; + return _sessionStatus; } - virtual void endStandBySession() { - _standbysessionstatus = false; + virtual void endSession() { + _sessionStatus = false; } - virtual bool isStandBySessionActive() { - return _standbysessionstatus; + virtual bool isSessionActive() { + return _sessionStatus; } /** @@ -85,7 +85,7 @@ signals: protected: bool _active { false }; - bool _standbysessionstatus { false }; + bool _sessionStatus { false }; PluginContainer* _container { nullptr }; static const char* UNKNOWN_PLUGIN_ID; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index df98abf408..93f4787f0f 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -123,8 +123,6 @@ bool OculusBaseDisplayPlugin::internalActivate() { void OculusBaseDisplayPlugin::internalDeactivate() { Parent::internalDeactivate(); - releaseOculusSession(); - _session = nullptr; } bool OculusBaseDisplayPlugin::activateStandBySession() { @@ -134,7 +132,7 @@ bool OculusBaseDisplayPlugin::activateStandBySession() { } return true; } -void OculusBaseDisplayPlugin::deactivateStandBySession() { +void OculusBaseDisplayPlugin::deactivateSession() { releaseOculusSession(); _session = nullptr; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index bfdcc5db1e..5230b11681 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -35,7 +35,7 @@ protected: bool internalActivate() override; void internalDeactivate() override; bool activateStandBySession() override; - void deactivateStandBySession() override; + void deactivateSession() override; void updatePresentPose() override; protected: From 40823bf5827526f6aae65bd89718c624bf63a724 Mon Sep 17 00:00:00 2001 From: seefo Date: Tue, 6 Jun 2017 10:11:46 -0700 Subject: [PATCH 48/49] Updated Windows build guide's markdown --- BUILD_WIN.md | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 311dfd9267..7c3f18592a 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -1,5 +1,7 @@ This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit. +## Building High Fidelity + ### Step 1. Installing Visual Studio 2013 If you don't already have the Community or Professional edition of Visual Studio 2013, download and install [Visual Studio Community 2013](https://www.visualstudio.com/en-us/news/releasenotes/vs2013-community-vs). You do not need to install any of the optional components when going through the installer. @@ -18,8 +20,8 @@ Keep the default components checked when going through the installer. ### Step 4. Setting Qt Environment Variable -Go to "Control Panel > System > Advanced System Settings > Environment Variables > New..." (or search “Environment Variables” in Start Search). -* Set "Variable name": QT_CMAKE_PREFIX_PATH +Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search). +* Set "Variable name": `QT_CMAKE_PREFIX_PATH` * Set "Variable value": `%QT_DIR%\5.6\msvc2013_64\lib\cmake` ### Step 5. Installing OpenSSL @@ -29,34 +31,36 @@ Download and install the [Win64 OpenSSL v1.0.2L Installer](https://slproweb.com/ ### Step 6. Running CMake to Generate Build Files Run Command Prompt from Start and run the following commands: - cd "%HIFI_DIR%" - mkdir build - cd build - cmake .. -G "Visual Studio 12 Win64" + +> cd "%HIFI_DIR%" +> mkdir build +> cd build +> cmake .. -G "Visual Studio 12 Win64" + -Where %HIFI_DIR% is the directory for the highfidelity repository. +Where `%HIFI_DIR%` is the directory for the highfidelity repository. ### Step 7. Making a Build -Open '%HIFI_DIR%\build\hifi.sln' using Visual Studio. +Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio. Change the Solution Configuration (next to the green play button) from "Debug" to "Release" for best performance. -Run Build > Build Solution. +Run `Build > Build Solution`. ### Step 8. Testing Interface Create another environment variable (see Step #4) -* Set "Variable name": _NO_DEBUG_HEAP -* Set "Variable value": 1 +* Set "Variable name": `_NO_DEBUG_HEAP` +* Set "Variable value": `1` -In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run Debug > Start Debugging. +In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run `Debug > Start Debugging`. Now, you should have a full build of High Fidelity and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow. -Note: You can also run Interface by launching it from command line or File Explorer from %HIFI_DIR%\build\interface\Release\interface.exe +Note: You can also run Interface by launching it from command line or File Explorer from `%HIFI_DIR%\build\interface\Release\interface.exe` -### Troubleshooting +## Troubleshooting For any problems after Step #6, first try this: * Delete your locally cloned copy of the highfidelity repository @@ -66,16 +70,16 @@ For any problems after Step #6, first try this: #### CMake gives you the same error message repeatedly after the build fails -Remove `CMakeCache.txt` found in the '%HIFI_DIR%\build' directory +Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory. #### nmake cannot be found Make sure nmake.exe is located at the following path: + C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin If not, add the directory where nmake is located to the PATH environment variable. #### Qt is throwing an error -Make sure you have the correct version (5.6.2) installed and 'QT_CMAKE_PREFIX_PATH' environment variable is set correctly. - +Make sure you have the correct version (5.6.2) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly. From aa13812e3fcb48453c78955b91ed07650e1043d3 Mon Sep 17 00:00:00 2001 From: seefo Date: Tue, 6 Jun 2017 15:20:26 -0700 Subject: [PATCH 49/49] Fixed multiline in BUILD_WIN.md --- BUILD_WIN.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 7c3f18592a..818a176f75 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -31,12 +31,12 @@ Download and install the [Win64 OpenSSL v1.0.2L Installer](https://slproweb.com/ ### Step 6. Running CMake to Generate Build Files Run Command Prompt from Start and run the following commands: - -> cd "%HIFI_DIR%" -> mkdir build -> cd build -> cmake .. -G "Visual Studio 12 Win64" - +```` +cd "%HIFI_DIR%" +mkdir build +cd build +cmake .. -G "Visual Studio 12 Win64" +```` Where `%HIFI_DIR%` is the directory for the highfidelity repository.