From 7298cd69404e04d2c46abb45954b16ff3d68eba4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 23 Jun 2017 10:54:31 -0700 Subject: [PATCH 01/24] Add support for vs2015 and vs2017 FBX libs --- cmake/modules/FindFBX.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/modules/FindFBX.cmake b/cmake/modules/FindFBX.cmake index 2e84d1ea19..b362d93cd3 100644 --- a/cmake/modules/FindFBX.cmake +++ b/cmake/modules/FindFBX.cmake @@ -56,6 +56,14 @@ elseif (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") endif() function(_fbx_find_library _name _lib _suffix) + if (MSVC15) + set(VS_PREFIX vs2017) + endif() + + if (MSVC14) + set(VS_PREFIX vs2015) + endif() + if (MSVC12) set(VS_PREFIX vs2013) endif() From b12018ccf3f7cb2dd5e76cbf05ccb7a1e6d91fbc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 23 Jun 2017 10:54:48 -0700 Subject: [PATCH 02/24] Fix Oven not properly handling native separators --- tools/oven/src/Oven.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/oven/src/Oven.cpp b/tools/oven/src/Oven.cpp index dc763cc82d..d0b8c3cd65 100644 --- a/tools/oven/src/Oven.cpp +++ b/tools/oven/src/Oven.cpp @@ -61,7 +61,9 @@ Oven::Oven(int argc, char* argv[]) : if (parser.isSet(CLI_INPUT_PARAMETER) || parser.isSet(CLI_OUTPUT_PARAMETER)) { if (parser.isSet(CLI_INPUT_PARAMETER) && parser.isSet(CLI_OUTPUT_PARAMETER)) { BakerCLI* cli = new BakerCLI(this); - cli->bakeFile(parser.value(CLI_INPUT_PARAMETER), parser.value(CLI_OUTPUT_PARAMETER)); + QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER))); + QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER))); + cli->bakeFile(inputUrl, outputUrl.toString()); } else { parser.showHelp(); QApplication::quit(); From 5f92c1adc09abb7c332a300c40fc1b352c1c6257 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 Jun 2017 09:40:07 -0700 Subject: [PATCH 03/24] Update FindFBX to use newer MSVC_VERSION --- cmake/modules/FindFBX.cmake | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/cmake/modules/FindFBX.cmake b/cmake/modules/FindFBX.cmake index b362d93cd3..9a1d08a010 100644 --- a/cmake/modules/FindFBX.cmake +++ b/cmake/modules/FindFBX.cmake @@ -56,27 +56,17 @@ elseif (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") endif() function(_fbx_find_library _name _lib _suffix) - if (MSVC15) + if (MSVC_VERSION EQUAL 1910) set(VS_PREFIX vs2017) - endif() - - if (MSVC14) + elseif (MSVC_VERSION EQUAL 1900) set(VS_PREFIX vs2015) - endif() - - if (MSVC12) + elseif (MSVC_VERSION EQUAL 1800) set(VS_PREFIX vs2013) - endif() - - if (MSVC11) + elseif (MSVC_VERSION EQUAL 1700) set(VS_PREFIX vs2012) - endif() - - if (MSVC10) + elseif (MSVC_VERSION EQUAL 1600) set(VS_PREFIX vs2010) - endif() - - if (MSVC90) + elseif (MSVC_VERSION EQUAL 1500) set(VS_PREFIX vs2008) endif() From 9d002d6f6b38dfadd8feaa88ad179a37a3652076 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Jun 2017 11:00:05 -0700 Subject: [PATCH 04/24] move the location of Q_DECLARE_METATYPE(std::function) so that the server-script AC can see it --- libraries/shared/src/RegisteredMetaTypes.cpp | 2 ++ libraries/shared/src/RegisteredMetaTypes.h | 2 ++ libraries/ui/src/ui/OffscreenQmlSurface.cpp | 6 ------ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 70067b93f3..f793b78b39 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -34,6 +34,8 @@ int pickRayMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); int qMapURLStringMetaTypeId = qRegisterMetaType>(); int socketErrorMetaTypeId = qRegisterMetaType(); +int voidLambdaType = qRegisterMetaType>(); +int variantLambdaType = qRegisterMetaType>(); void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, mat4toScriptValue, mat4FromScriptValue); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 8a15f62eed..255a8115a1 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -33,6 +33,8 @@ Q_DECLARE_METATYPE(xColor) Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(AACube) +Q_DECLARE_METATYPE(std::function); +Q_DECLARE_METATYPE(std::function); void registerMetaTypes(QScriptEngine* engine); diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index f0006cb399..648bdad1bf 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -886,12 +886,6 @@ QQmlContext* OffscreenQmlSurface::getSurfaceContext() { return _qmlContext; } -Q_DECLARE_METATYPE(std::function); -auto VoidLambdaType = qRegisterMetaType>(); -Q_DECLARE_METATYPE(std::function); -auto VariantLambdaType = qRegisterMetaType>(); - - void OffscreenQmlSurface::executeOnUiThread(std::function function, bool blocking ) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, From 3fa7d026a77606c9e8c3dc0c97558a41edbfbe3e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Jun 2017 14:18:14 -0700 Subject: [PATCH 05/24] make ResourceManager be owned by DependencyManager --- assignment-client/src/Agent.cpp | 7 ++--- .../src/entities/EntityServer.cpp | 2 +- .../src/scripts/EntityScriptServer.cpp | 7 ++--- interface/src/Application.cpp | 6 ++-- interface/src/assets/ATPAssetMigrator.cpp | 3 +- .../src/scripting/TestScriptingInterface.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 2 +- libraries/entities/src/EntityEditFilters.cpp | 2 +- libraries/fbx/src/OBJReader.cpp | 4 +-- .../src/model-networking/TextureCache.cpp | 4 +-- libraries/networking/src/AtpReply.cpp | 2 +- libraries/networking/src/ResourceCache.cpp | 2 +- libraries/networking/src/ResourceManager.cpp | 22 ++++++------- libraries/networking/src/ResourceManager.h | 31 ++++++++++++------- .../src/ResourceScriptingInterface.cpp | 2 +- libraries/octree/src/Octree.cpp | 3 +- .../procedural/src/procedural/Procedural.cpp | 2 +- .../src/FileScriptingInterface.cpp | 2 +- libraries/script-engine/src/ScriptCache.cpp | 8 ++--- libraries/script-engine/src/ScriptEngine.cpp | 2 +- tests/render-perf/src/main.cpp | 7 ++--- tests/render-texture-load/src/main.cpp | 4 +-- 22 files changed, 65 insertions(+), 61 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 260a6d6825..f336f1dad5 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -62,8 +62,6 @@ Agent::Agent(ReceivedMessage& message) : _entityEditSender.setPacketsPerSecond(DEFAULT_ENTITY_PPS_PER_SCRIPT); DependencyManager::get()->setPacketSender(&_entityEditSender); - ResourceManager::init(); - DependencyManager::registerInheritance(); DependencyManager::set(); @@ -81,6 +79,7 @@ Agent::Agent(ReceivedMessage& message) : DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); @@ -199,7 +198,7 @@ void Agent::requestScript() { return; } - auto request = ResourceManager::createResourceRequest(this, scriptURL); + auto request = DependencyManager::get()->createResourceRequest(this, scriptURL); if (!request) { qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString(); @@ -779,7 +778,7 @@ void Agent::aboutToFinish() { // our entity tree is going to go away so tell that to the EntityScriptingInterface DependencyManager::get()->setEntityTree(nullptr); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // cleanup the AudioInjectorManager (and any still running injectors) DependencyManager::destroy(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index dc0a2add3a..afcbcf4f1e 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -31,9 +31,9 @@ EntityServer::EntityServer(ReceivedMessage& message) : OctreeServer(message), _entitySimulation(NULL) { - ResourceManager::init(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics }, diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 1b226ab642..489478ff9a 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -54,7 +54,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::get()->setPacketSender(&_entityEditSender); - ResourceManager::init(); + DependencyManager::set(); DependencyManager::registerInheritance(); @@ -67,7 +67,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::set(); DependencyManager::set(ScriptEngine::ENTITY_SERVER_SCRIPT); - auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, this, "handleOctreePacket"); @@ -493,7 +492,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, bool if (entity && (reload || notRunning || details.scriptText != entity->getServerScripts())) { QString scriptUrl = entity->getServerScripts(); if (!scriptUrl.isEmpty()) { - scriptUrl = ResourceManager::normalizeURL(scriptUrl); + scriptUrl = DependencyManager::get()->normalizeURL(scriptUrl); qCDebug(entity_script_server) << "Loading entity server script" << scriptUrl << "for" << entityID; _entitiesScriptEngine->loadEntityScript(entityID, scriptUrl, reload); } @@ -551,7 +550,7 @@ void EntityScriptServer::aboutToFinish() { // our entity tree is going to go away so tell that to the EntityScriptingInterface DependencyManager::get()->setEntityTree(nullptr); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // cleanup the AudioInjectorManager (and any still running injectors) DependencyManager::destroy(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c138230893..cfb8db42d7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -574,6 +574,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -764,7 +765,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(this, &Application::activeDisplayPluginChanged, reinterpret_cast(audioScriptingInterface.data()), &scripting::Audio::onContextChanged); - ResourceManager::init(); // Make sure we don't time out during slow operations at startup updateHeartbeat(); @@ -1868,7 +1868,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // remove the NodeList from the DependencyManager DependencyManager::destroy(); @@ -5925,7 +5925,7 @@ void Application::addAssetToWorldFromURL(QString url) { addAssetToWorldInfo(filename, "Downloading model file " + filename + "."); - auto request = ResourceManager::createResourceRequest(nullptr, QUrl(url)); + auto request = DependencyManager::get()->createResourceRequest(nullptr, QUrl(url)); connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished); request->send(); } diff --git a/interface/src/assets/ATPAssetMigrator.cpp b/interface/src/assets/ATPAssetMigrator.cpp index e0e9d5a73a..667c2587b0 100644 --- a/interface/src/assets/ATPAssetMigrator.cpp +++ b/interface/src/assets/ATPAssetMigrator.cpp @@ -106,7 +106,8 @@ void ATPAssetMigrator::loadEntityServerFile() { jsonValue = entityObject; } else if (wantsToMigrateResource(migrationURL)) { - auto request = ResourceManager::createResourceRequest(this, migrationURL); + auto request = + DependencyManager::get()->createResourceRequest(this, migrationURL); if (request) { qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration"; diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index b8892fae7e..84c742d0ab 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -62,7 +62,7 @@ bool TestScriptingInterface::loadTestScene(QString scene) { static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/"; static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/"; return DependencyManager::get()->returnFromUiThread([scene]()->QVariant { - ResourceManager::setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/"); + DependencyManager::get()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/"); auto tree = qApp->getEntities()->getTree(); auto treeIsClient = tree->getIsClient(); // Force the tree to accept the load regardless of permissions diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ffaac3bf3e..42746d2046 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -880,7 +880,7 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool entity->scriptHasUnloaded(); } if (shouldLoad) { - scriptUrl = ResourceManager::normalizeURL(scriptUrl); + scriptUrl = DependencyManager::get()->normalizeURL(scriptUrl); _entitiesScriptEngine->loadEntityScript(entityID, scriptUrl, reload); entity->scriptHasPreloaded(); } diff --git a/libraries/entities/src/EntityEditFilters.cpp b/libraries/entities/src/EntityEditFilters.cpp index d62495d95e..5359ebd31b 100644 --- a/libraries/entities/src/EntityEditFilters.cpp +++ b/libraries/entities/src/EntityEditFilters.cpp @@ -132,7 +132,7 @@ void EntityEditFilters::addFilter(EntityItemID entityID, QString filterURL) { _filterDataMap.insert(entityID, filterData); _lock.unlock(); - auto scriptRequest = ResourceManager::createResourceRequest(this, scriptURL); + auto scriptRequest = DependencyManager::get()->createResourceRequest(this, scriptURL); if (!scriptRequest) { qWarning() << "Could not create ResourceRequest for Entity Edit filter script at" << scriptURL.toString(); scriptRequestFinished(entityID); diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 1445d14d84..417901b9ab 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -202,7 +202,7 @@ bool OBJReader::isValidTexture(const QByteArray &filename) { } QUrl candidateUrl = _url.resolved(QUrl(filename)); - return ResourceManager::resourceExists(candidateUrl); + return DependencyManager::get()->resourceExists(candidateUrl); } void OBJReader::parseMaterialLibrary(QIODevice* device) { @@ -267,7 +267,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } std::tuple requestData(QUrl& url) { - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); if (!request) { return std::make_tuple(false, QByteArray()); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index ed1715219a..5c8f59f20f 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -384,7 +384,7 @@ void NetworkTexture::makeRequest() { // Add a fragment to the base url so we can identify the section of the ktx being requested when debugging // The actual requested url is _activeUrl and will not contain the fragment _url.setFragment("head"); - _ktxHeaderRequest = ResourceManager::createResourceRequest(this, _activeUrl); + _ktxHeaderRequest = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_ktxHeaderRequest) { qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); @@ -454,7 +454,7 @@ void NetworkTexture::startMipRangeRequest(uint16_t low, uint16_t high) { bool isHighMipRequest = low == NULL_MIP_LEVEL && high == NULL_MIP_LEVEL; - _ktxMipRequest = ResourceManager::createResourceRequest(this, _activeUrl); + _ktxMipRequest = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_ktxMipRequest) { qCWarning(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); diff --git a/libraries/networking/src/AtpReply.cpp b/libraries/networking/src/AtpReply.cpp index 4440995ee0..6417478005 100644 --- a/libraries/networking/src/AtpReply.cpp +++ b/libraries/networking/src/AtpReply.cpp @@ -13,7 +13,7 @@ #include "AtpReply.h" AtpReply::AtpReply(const QUrl& url, QObject* parent) : - _resourceRequest(ResourceManager::createResourceRequest(parent, url)) { + _resourceRequest(DependencyManager::get()->createResourceRequest(parent, url)) { setOperation(QNetworkAccessManager::GetOperation); connect(_resourceRequest, &AssetResourceRequest::progress, this, &AtpReply::downloadProgress); diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 88ea68780b..f07514cd85 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -672,7 +672,7 @@ void Resource::makeRequest() { PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } }); - _request = ResourceManager::createResourceRequest(this, _activeUrl); + _request = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_request) { qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); diff --git a/libraries/networking/src/ResourceManager.cpp b/libraries/networking/src/ResourceManager.cpp index e2c1cf2431..3ee66f89c1 100644 --- a/libraries/networking/src/ResourceManager.cpp +++ b/libraries/networking/src/ResourceManager.cpp @@ -24,10 +24,16 @@ #include "NetworkAccessManager.h" #include "NetworkLogging.h" -QThread ResourceManager::_thread; -ResourceManager::PrefixMap ResourceManager::_prefixMap; -QMutex ResourceManager::_prefixMapLock; +ResourceManager::ResourceManager() { + _thread.setObjectName("Resource Manager Thread"); + + auto assetClient = DependencyManager::set(); + assetClient->moveToThread(&_thread); + QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init); + + _thread.start(); +} void ResourceManager::setUrlPrefixOverride(const QString& prefix, const QString& replacement) { QMutexLocker locker(&_prefixMapLock); @@ -75,16 +81,6 @@ QUrl ResourceManager::normalizeURL(const QUrl& originalUrl) { return url; } -void ResourceManager::init() { - _thread.setObjectName("Resource Manager Thread"); - - auto assetClient = DependencyManager::set(); - assetClient->moveToThread(&_thread); - QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init); - - _thread.start(); -} - void ResourceManager::cleanup() { // cleanup the AssetClient thread DependencyManager::destroy(); diff --git a/libraries/networking/src/ResourceManager.h b/libraries/networking/src/ResourceManager.h index 41da892701..f7495e71e9 100644 --- a/libraries/networking/src/ResourceManager.h +++ b/libraries/networking/src/ResourceManager.h @@ -14,7 +14,11 @@ #include +#include #include +#include + +#include #include "ResourceRequest.h" @@ -24,29 +28,34 @@ const QString URL_SCHEME_HTTPS = "https"; const QString URL_SCHEME_FTP = "ftp"; const QString URL_SCHEME_ATP = "atp"; -class ResourceManager { +class ResourceManager: public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + public: + ResourceManager(); - static void setUrlPrefixOverride(const QString& prefix, const QString& replacement); - static QString normalizeURL(const QString& urlString); - static QUrl normalizeURL(const QUrl& url); + void setUrlPrefixOverride(const QString& prefix, const QString& replacement); + QString normalizeURL(const QString& urlString); + QUrl normalizeURL(const QUrl& url); - static ResourceRequest* createResourceRequest(QObject* parent, const QUrl& url); + ResourceRequest* createResourceRequest(QObject* parent, const QUrl& url); - static void init(); - static void cleanup(); + void init(); + void cleanup(); // Blocking call to check if a resource exists. This function uses a QEventLoop internally // to return to the calling thread so that events can still be processed. - static bool resourceExists(const QUrl& url); + bool resourceExists(const QUrl& url); private: - static QThread _thread; + QThread _thread; using PrefixMap = std::map; - static PrefixMap _prefixMap; - static QMutex _prefixMapLock; + PrefixMap _prefixMap; + QMutex _prefixMapLock; + }; #endif diff --git a/libraries/networking/src/ResourceScriptingInterface.cpp b/libraries/networking/src/ResourceScriptingInterface.cpp index 38be49049c..3227d44de1 100644 --- a/libraries/networking/src/ResourceScriptingInterface.cpp +++ b/libraries/networking/src/ResourceScriptingInterface.cpp @@ -11,5 +11,5 @@ #include "ResourceManager.h" void ResourceScriptingInterface::overrideUrlPrefix(const QString& prefix, const QString& replacement) { - ResourceManager::setUrlPrefixOverride(prefix, replacement); + DependencyManager::get()->setUrlPrefixOverride(prefix, replacement); } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 180f25f106..2e93f3515f 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1668,7 +1668,8 @@ bool Octree::readJSONFromGzippedFile(QString qFileName) { } bool Octree::readFromURL(const QString& urlString) { - auto request = std::unique_ptr(ResourceManager::createResourceRequest(this, urlString)); + auto request = + std::unique_ptr(DependencyManager::get()->createResourceRequest(this, urlString)); if (!request) { return false; diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index e4ce3c691a..c38e562672 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -103,7 +103,7 @@ bool Procedural::parseVersion(const QJsonValue& version) { } bool Procedural::parseShader(const QUrl& shaderPath) { - auto shaderUrl = ResourceManager::normalizeURL(shaderPath); + auto shaderUrl = DependencyManager::get()->normalizeURL(shaderPath); if (!shaderUrl.isValid()) { if (!shaderUrl.isEmpty()) { diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 2f5cc2bc88..30d0a3a201 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -85,7 +85,7 @@ QString FileScriptingInterface::convertUrlToPath(QUrl url) { // this function is not in use void FileScriptingInterface::downloadZip(QString path, const QString link) { QUrl url = QUrl(link); - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); connect(request, &ResourceRequest::finished, this, [this, path]{ unzipFile(path, ""); // so intellisense isn't mad }); diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index 601ca6bc95..dba2db0458 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -57,7 +57,7 @@ void ScriptCache::clearATPScriptsFromCache() { } void ScriptCache::deleteScript(const QUrl& unnormalizedURL) { - QUrl url = ResourceManager::normalizeURL(unnormalizedURL); + QUrl url = DependencyManager::get()->normalizeURL(unnormalizedURL); Lock lock(_containerLock); if (_scriptCache.contains(url)) { qCDebug(scriptengine) << "Delete script from cache:" << url.toString(); @@ -70,7 +70,7 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable qCDebug(scriptengine) << "ScriptCache::getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif QUrl unnormalizedURL(scriptOrURL); - QUrl url = ResourceManager::normalizeURL(unnormalizedURL); + QUrl url = DependencyManager::get()->normalizeURL(unnormalizedURL); // attempt to determine if this is a URL to a script, or if this is actually a script itself (which is valid in the // entityScript use case) @@ -109,7 +109,7 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable #ifdef THREAD_DEBUGGING qCDebug(scriptengine) << "about to call: ResourceManager::createResourceRequest(this, url); on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); Q_ASSERT(request); request->setCacheEnabled(!forceDownload); connect(request, &ResourceRequest::finished, this, [=]{ scriptContentAvailable(maxRetries); }); @@ -166,7 +166,7 @@ void ScriptCache::scriptContentAvailable(int maxRetries) { qCDebug(scriptengine) << QString("Retrying script request [%1 / %2]: %3") .arg(attempt).arg(maxRetries).arg(url.toString()); - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); Q_ASSERT(request); // We've already made a request, so the cache must be disabled or it wasn't there, so enabling diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d9b41bb55d..59694cba6f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1755,7 +1755,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac QList urls; for (QString includeFile : includeFiles) { - QString file = ResourceManager::normalizeURL(includeFile); + QString file = DependencyManager::get()->normalizeURL(includeFile); QUrl thisURL; bool isStandardLibrary = false; if (file.startsWith("/~/")) { diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 52592cd202..c4543e354a 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -493,6 +493,7 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); } QTestWindow() { @@ -519,8 +520,6 @@ public: _entitySimulation = simpleSimulation; } - ResourceManager::init(); - setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); _renderThread._size = _size; @@ -574,7 +573,7 @@ public: DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // remove the NodeList from the DependencyManager DependencyManager::destroy(); } @@ -997,7 +996,7 @@ private: QFileInfo atpPathInfo(atpPath); if (atpPathInfo.exists()) { QString atpUrl = QUrl::fromLocalFile(atpPath).toString(); - ResourceManager::setUrlPrefixOverride("atp:/", atpUrl + "/"); + DependencyManager::get()->setUrlPrefixOverride("atp:/", atpUrl + "/"); } _octree->clear(); _octree->getTree()->readFromURL(fileName); diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index f426cd8024..5920e04558 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -289,6 +289,7 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); } struct TextureLoad { @@ -329,7 +330,6 @@ public: installEventFilter(this); QThreadPool::globalInstance()->setMaxThreadCount(2); QThread::currentThread()->setPriority(QThread::HighestPriority); - ResourceManager::init(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); _renderThread._size = _size; @@ -369,7 +369,7 @@ public: DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); } protected: From f59a94d4011be0423ecfa089f93ea98eb9217fcb Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Jun 2017 00:52:51 +0200 Subject: [PATCH 06/24] move the ResourceManager init back to where it was, to prevent problems --- assignment-client/src/Agent.cpp | 3 ++- assignment-client/src/entities/EntityServer.cpp | 2 +- tests/render-perf/src/main.cpp | 3 ++- tests/render-texture-load/src/main.cpp | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f336f1dad5..8aec5adb1f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -62,6 +62,8 @@ Agent::Agent(ReceivedMessage& message) : _entityEditSender.setPacketsPerSecond(DEFAULT_ENTITY_PPS_PER_SCRIPT); DependencyManager::get()->setPacketSender(&_entityEditSender); + DependencyManager::set(); + DependencyManager::registerInheritance(); DependencyManager::set(); @@ -79,7 +81,6 @@ Agent::Agent(ReceivedMessage& message) : DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index afcbcf4f1e..ac686e2e0a 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -31,9 +31,9 @@ EntityServer::EntityServer(ReceivedMessage& message) : OctreeServer(message), _entitySimulation(NULL) { + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics }, diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index c4543e354a..0b7e68301a 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -493,7 +493,6 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); } QTestWindow() { @@ -519,6 +518,8 @@ public: _octree->getTree()->setSimulation(simpleSimulation); _entitySimulation = simpleSimulation; } + + DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index 5920e04558..d85fcd6a32 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -289,7 +289,6 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); } struct TextureLoad { @@ -329,7 +328,8 @@ public: installEventFilter(this); QThreadPool::globalInstance()->setMaxThreadCount(2); - QThread::currentThread()->setPriority(QThread::HighestPriority); + QThread::currentThread()->setPriority(QThread::HighestPriority); + DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); _renderThread._size = _size; From 6c487ec0afce27d889bf5ed252a312bd37028e85 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Jun 2017 01:01:59 +0200 Subject: [PATCH 07/24] I need to setup my code-editor, spaces. --- tests/render-perf/src/main.cpp | 2 +- tests/render-texture-load/src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 0b7e68301a..d47821ab1c 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -518,7 +518,7 @@ public: _octree->getTree()->setSimulation(simpleSimulation); _entitySimulation = simpleSimulation; } - + DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index d85fcd6a32..67b80d9ba8 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -328,7 +328,7 @@ public: installEventFilter(this); QThreadPool::globalInstance()->setMaxThreadCount(2); - QThread::currentThread()->setPriority(QThread::HighestPriority); + QThread::currentThread()->setPriority(QThread::HighestPriority); DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); From b52dd7b8224f63da59da86ed099af26d21cad5b0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 29 Jun 2017 17:00:27 -0700 Subject: [PATCH 08/24] Don't use blocking connections on the main thread --- assignment-client/src/AssignmentClient.cpp | 3 +- .../src/avatars/ScriptableAvatar.cpp | 3 +- interface/src/Application.cpp | 45 +++++++++------ interface/src/Application.h | 4 +- interface/src/avatar/AvatarManager.cpp | 3 +- interface/src/avatar/MyAvatar.cpp | 9 +-- interface/src/scripting/Audio.cpp | 40 ++++++------- interface/src/scripting/Audio.h | 7 ++- interface/src/scripting/AudioDevices.cpp | 21 ++++--- interface/src/scripting/AudioDevices.h | 2 +- .../scripting/ClipboardScriptingInterface.cpp | 13 +++-- .../scripting/ClipboardScriptingInterface.h | 4 ++ .../src/scripting/MenuScriptingInterface.cpp | 11 ++-- .../scripting/WindowScriptingInterface.cpp | 7 ++- .../src/scripting/WindowScriptingInterface.h | 2 + interface/src/ui/JSConsole.cpp | 3 +- libraries/animation/src/AnimationCache.cpp | 13 +++-- libraries/audio-client/src/AudioClient.cpp | 19 ++++++- libraries/audio-client/src/AudioClient.h | 9 ++- libraries/audio/src/SoundCache.cpp | 9 ++- .../src/avatars-renderer/Avatar.cpp | 11 ++-- libraries/avatars/src/AvatarData.cpp | 31 +++++----- .../src/display-plugins/CompositorHelper.cpp | 6 +- .../src/EntityTreeRenderer.cpp | 5 +- .../entities/src/EntityScriptingInterface.cpp | 11 ++-- libraries/networking/src/NodeList.cpp | 3 +- libraries/networking/src/ResourceCache.cpp | 14 +++-- libraries/networking/src/udt/Socket.cpp | 3 +- .../src/plugins/InputConfiguration.cpp | 16 +++--- .../recording/src/recording/ClipCache.cpp | 4 +- libraries/render-utils/src/Model.cpp | 3 +- libraries/render/src/task/Config.cpp | 7 ++- .../src/AudioScriptingInterface.cpp | 4 +- .../src/RecordingScriptingInterface.cpp | 17 +++--- libraries/script-engine/src/ScriptEngine.cpp | 7 ++- libraries/script-engine/src/ScriptEngines.cpp | 3 +- libraries/shared/src/ThreadHelpers.h | 22 +++++++ libraries/shared/src/shared/QtHelpers.cpp | 57 +++++++++++++++++++ libraries/shared/src/shared/QtHelpers.h | 47 +++++++++++++++ libraries/ui/src/OffscreenUi.cpp | 15 ++--- libraries/ui/src/ui/Menu.cpp | 4 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 5 +- libraries/ui/src/ui/QmlWrapper.cpp | 6 +- .../ui/src/ui/TabletScriptingInterface.cpp | 15 ++--- .../ui/src/ui/ToolbarScriptingInterface.cpp | 12 ++-- 45 files changed, 377 insertions(+), 178 deletions(-) create mode 100644 libraries/shared/src/shared/QtHelpers.cpp create mode 100644 libraries/shared/src/shared/QtHelpers.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index abfc66ac55..2db1fba952 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -141,7 +142,7 @@ void AssignmentClient::stopAssignmentClient() { QThread* currentAssignmentThread = _currentAssignment->thread(); // ask the current assignment to stop - QMetaObject::invokeMethod(_currentAssignment, "stop", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(_currentAssignment, "stop"); // ask the current assignment to delete itself on its thread _currentAssignment->deleteLater(); diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 57456b00c3..4e2836119e 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include "ScriptableAvatar.h" @@ -49,7 +50,7 @@ void ScriptableAvatar::stopAnimation() { AnimationDetails ScriptableAvatar::getAnimationDetails() { if (QThread::currentThread() != thread()) { AnimationDetails result; - QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "getAnimationDetails", Q_RETURN_ARG(AnimationDetails, result)); return result; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75bcee0703..1a31877c1b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -48,6 +48,7 @@ #include +#include #include #include #include @@ -1208,15 +1209,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Make sure we don't time out during slow operations at startup updateHeartbeat(); - int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now - connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings); - connect(&_settingsThread, SIGNAL(started()), &_settingsTimer, SLOT(start())); - connect(&_settingsThread, SIGNAL(finished()), &_settingsTimer, SLOT(stop())); - _settingsTimer.moveToThread(&_settingsThread); - _settingsTimer.setSingleShot(false); - _settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable - _settingsThread.setPriority(QThread::LowestPriority); - _settingsThread.start(); + + QTimer* settingsTimer = new QTimer(); + moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{ + connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{ + // Disconnect the signal from the save settings + QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); + // Stop the settings timer + settingsTimer->stop(); + // Delete it (this will trigger the thread destruction + settingsTimer->deleteLater(); + // Mark the settings thread as finished, so we know we can safely save in the main application + // shutdown code + _settingsGuard.trigger(); + }); + + int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now + settingsTimer->setSingleShot(false); + settingsTimer->setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable + QObject::connect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); + }, QThread::LowestPriority); if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) { getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person. @@ -1644,7 +1656,7 @@ QString Application::getUserAgent() { if (QThread::currentThread() != thread()) { QString userAgent; - QMetaObject::invokeMethod(this, "getUserAgent", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, userAgent)); + hifi::qt::blockingInvokeMethod(this, "getUserAgent", Q_RETURN_ARG(QString, userAgent)); return userAgent; } @@ -1802,11 +1814,13 @@ void Application::cleanupBeforeQuit() { locationUpdateTimer.stop(); identityPacketTimer.stop(); pingTimer.stop(); - QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection); - // save state - _settingsThread.quit(); - saveSettings(); + // Wait for the settings thread to shut down, and save the settings one last time when it's safe + if (_settingsGuard.wait()) { + // save state + saveSettings(); + } + _window->saveGeometry(); // Destroy third party processes after scripts have finished using them. @@ -1830,8 +1844,7 @@ void Application::cleanupBeforeQuit() { // FIXME: something else is holding a reference to AudioClient, // so it must be explicitly synchronously stopped here - QMetaObject::invokeMethod(DependencyManager::get().data(), - "cleanupBeforeQuit", Qt::BlockingQueuedConnection); + QMetaObject::invokeMethod(DependencyManager::get().data(), "cleanupBeforeQuit", Qt::BlockingQueuedConnection); // destroy Audio so it and its threads have a chance to go down safely // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine diff --git a/interface/src/Application.h b/interface/src/Application.h index c26b3b215e..28d95a280c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -596,8 +597,7 @@ private: bool _notifiedPacketVersionMismatchThisDomain; - QThread _settingsThread; - QTimer _settingsTimer; + ConditionalGuard _settingsGuard; GLCanvas* _glWidget{ nullptr }; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 20b3949bc6..abdcd48b42 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -25,6 +25,7 @@ #endif +#include #include #include #include @@ -482,7 +483,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& const QScriptValue& avatarIdsToDiscard) { RayToAvatarIntersectionResult result; if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(const_cast(this), "findRayIntersection", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "findRayIntersection", Q_RETURN_ARG(RayToAvatarIntersectionResult, result), Q_ARG(const PickRay&, ray), Q_ARG(const QScriptValue&, avatarIdsToInclude), diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e5c4f4b972..404f8681f2 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -897,7 +898,7 @@ void MyAvatar::restoreAnimation() { QStringList MyAvatar::getAnimationRoles() { if (QThread::currentThread() != thread()) { QStringList result; - QMetaObject::invokeMethod(this, "getAnimationRoles", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QStringList, result)); + hifi::qt::blockingInvokeMethod(this, "getAnimationRoles", Q_RETURN_ARG(QStringList, result)); return result; } return _skeletonModel->getRig().getAnimationRoles(); @@ -1368,7 +1369,7 @@ void MyAvatar::resetFullAvatarURL() { void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "useFullAvatarURL", Q_ARG(const QUrl&, fullAvatarURL), Q_ARG(const QString&, modelName)); return; @@ -1394,7 +1395,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN void MyAvatar::setAttachmentData(const QVector& attachmentData) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setAttachmentData", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "setAttachmentData", Q_ARG(const QVector, attachmentData)); return; } @@ -2358,7 +2359,7 @@ bool MyAvatar::safeLanding(const glm::vec3& position) { if (QThread::currentThread() != thread()) { bool result; - QMetaObject::invokeMethod(this, "safeLanding", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result), Q_ARG(const glm::vec3&, position)); + hifi::qt::blockingInvokeMethod(this, "safeLanding", Q_RETURN_ARG(bool, result), Q_ARG(const glm::vec3&, position)); return result; } glm::vec3 better; diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 4576190413..8125f9a9f0 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -11,6 +11,8 @@ #include "Audio.h" +#include + #include "Application.h" #include "AudioClient.h" #include "ui/AvatarInputs.h" @@ -49,27 +51,22 @@ float Audio::loudnessToLevel(float loudness) { Audio::Audio() : _devices(_contextIsHMD) { auto client = DependencyManager::get().data(); connect(client, &AudioClient::muteToggled, this, &Audio::onMutedChanged); + connect(client, &AudioClient::noiseReductionChanged, this, &Audio::onNoiseReductionChanged); connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged); + connect(client, &AudioClient::inputVolumeChanged, this, &Audio::onInputVolumeChanged); connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged); - connect(&_devices._inputs, &AudioDeviceList::deviceChanged, this, &Audio::onInputChanged); enableNoiseReduction(enableNoiseReductionSetting.get()); } void Audio::setMuted(bool isMuted) { if (_isMuted != isMuted) { auto client = DependencyManager::get().data(); - QMetaObject::invokeMethod(client, "toggleMute", Qt::BlockingQueuedConnection); - - _isMuted = isMuted; - emit mutedChanged(_isMuted); + QMetaObject::invokeMethod(client, "toggleMute"); } } void Audio::onMutedChanged() { - auto client = DependencyManager::get().data(); - bool isMuted; - QMetaObject::invokeMethod(client, "isMuted", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isMuted)); - + bool isMuted = DependencyManager::get()->isMuted(); if (_isMuted != isMuted) { _isMuted = isMuted; emit mutedChanged(_isMuted); @@ -79,11 +76,16 @@ void Audio::onMutedChanged() { void Audio::enableNoiseReduction(bool enable) { if (_enableNoiseReduction != enable) { auto client = DependencyManager::get().data(); - QMetaObject::invokeMethod(client, "setNoiseReduction", Qt::BlockingQueuedConnection, Q_ARG(bool, enable)); - + QMetaObject::invokeMethod(client, "setNoiseReduction", Q_ARG(bool, enable)); enableNoiseReductionSetting.set(enable); - _enableNoiseReduction = enable; - emit noiseReductionChanged(enable); + } +} + +void Audio::onNoiseReductionChanged() { + bool noiseReductionEnabled = DependencyManager::get()->isNoiseReductionEnabled(); + if (_enableNoiseReduction != noiseReductionEnabled) { + _enableNoiseReduction = noiseReductionEnabled; + emit noiseReductionChanged(_enableNoiseReduction); } } @@ -93,19 +95,11 @@ void Audio::setInputVolume(float volume) { if (_inputVolume != volume) { auto client = DependencyManager::get().data(); - QMetaObject::invokeMethod(client, "setInputVolume", Qt::BlockingQueuedConnection, Q_ARG(float, volume)); - - _inputVolume = volume; - emit inputVolumeChanged(_inputVolume); + QMetaObject::invokeMethod(client, "setInputVolume", Q_ARG(float, volume)); } } -// different audio input devices may have different volumes -void Audio::onInputChanged() { - auto client = DependencyManager::get().data(); - float volume; - QMetaObject::invokeMethod(client, "getInputVolume", Qt::BlockingQueuedConnection, Q_RETURN_ARG(float, volume)); - +void Audio::onInputVolumeChanged(float volume) { if (_inputVolume != volume) { _inputVolume = volume; emit inputVolumeChanged(_inputVolume); diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index 953727ede8..ca89521489 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -62,9 +62,12 @@ signals: void contextChanged(const QString& context); public slots: - void onMutedChanged(); void onContextChanged(); - void onInputChanged(); + +private slots: + void onMutedChanged(); + void onNoiseReductionChanged(); + void onInputVolumeChanged(float volume); void onInputLoudnessChanged(float loudness); protected: diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index b0ea8226e8..98b8a7c12c 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -11,6 +11,8 @@ #include +#include + #include "AudioDevices.h" #include "Application.h" @@ -71,22 +73,14 @@ bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, i bool AudioDeviceList::setDevice(int row, bool fromUser) { bool success = false; auto& device = _devices[row]; + _userSelection = fromUser; // skip if already selected if (!device.selected) { auto client = DependencyManager::get(); - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, success), + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Q_ARG(QAudio::Mode, _mode), Q_ARG(const QAudioDeviceInfo&, device.info)); - - if (success) { - device.selected = true; - if (fromUser) { - emit deviceSelected(device.info, _selectedDevice); - } - emit deviceChanged(device.info); - } } emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); @@ -135,12 +129,12 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { } void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) { + auto oldDevice = _selectedDevice; _selectedDevice = device; QModelIndex index; for (auto i = 0; i < _devices.size(); ++i) { AudioDevice& device = _devices[i]; - if (device.selected && device.info != _selectedDevice) { device.selected = false; } else if (device.info == _selectedDevice) { @@ -149,6 +143,11 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) { } } + if (_userSelection) { + _userSelection = false; + emit deviceSelected(_selectedDevice, oldDevice); + } + emit deviceChanged(_selectedDevice); emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); } diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index cd47ab4191..8e82ddc4fb 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -58,7 +58,7 @@ private: static QHash _roles; static Qt::ItemFlags _flags; - + bool _userSelection { false }; QAudio::Mode _mode; QAudioDeviceInfo _selectedDevice; QList _devices; diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index b803080538..b443ba1ef0 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -8,9 +8,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Application.h" #include "ClipboardScriptingInterface.h" +#include + +#include "Application.h" + ClipboardScriptingInterface::ClipboardScriptingInterface() { } @@ -24,7 +27,7 @@ float ClipboardScriptingInterface::getClipboardContentsLargestDimension() { bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector& entityIDs) { bool retVal; - QMetaObject::invokeMethod(qApp, "exportEntities", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(qApp, "exportEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename), Q_ARG(const QVector&, entityIDs)); @@ -33,7 +36,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, const bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) { bool retVal; - QMetaObject::invokeMethod(qApp, "exportEntities", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(qApp, "exportEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename), Q_ARG(float, x), @@ -45,7 +48,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, float bool ClipboardScriptingInterface::importEntities(const QString& filename) { bool retVal; - QMetaObject::invokeMethod(qApp, "importEntities", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(qApp, "importEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename)); return retVal; @@ -53,7 +56,7 @@ bool ClipboardScriptingInterface::importEntities(const QString& filename) { QVector ClipboardScriptingInterface::pasteEntities(glm::vec3 position) { QVector retVal; - QMetaObject::invokeMethod(qApp, "pasteEntities", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(qApp, "pasteEntities", Q_RETURN_ARG(QVector, retVal), Q_ARG(float, position.x), Q_ARG(float, position.y), diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 3c10475242..826732c777 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -13,6 +13,10 @@ #include +#include + +#include + /**jsdoc * @namespace Clipboard */ diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index 91fba1ce9e..b3829ecb3b 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include "Menu.h" @@ -43,7 +44,7 @@ bool MenuScriptingInterface::menuExists(const QString& menu) { return Menu::getInstance()->menuExists(menu); } bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "menuExists", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(Menu::getInstance(), "menuExists", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menu)); return result; @@ -86,7 +87,7 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& return Menu::getInstance()->menuItemExists(menu, menuitem); } bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "menuItemExists", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(Menu::getInstance(), "menuItemExists", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menu), Q_ARG(const QString&, menuitem)); @@ -114,7 +115,7 @@ bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) { return Menu::getInstance()->isOptionChecked(menuOption); } bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "isOptionChecked", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(Menu::getInstance(), "isOptionChecked", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menuOption)); return result; @@ -131,7 +132,7 @@ bool MenuScriptingInterface::isMenuEnabled(const QString& menuOption) { return Menu::getInstance()->isOptionChecked(menuOption); } bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "isMenuEnabled", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(Menu::getInstance(), "isMenuEnabled", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menuOption)); return result; @@ -157,7 +158,7 @@ bool MenuScriptingInterface::isInfoViewVisible(const QString& path) { } bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "isInfoViewVisible", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(Menu::getInstance(), "isInfoViewVisible", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, path)); return result; } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 38f467f22b..a5d8544658 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -9,11 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "WindowScriptingInterface.h" + #include #include #include #include +#include #include #include @@ -24,8 +27,6 @@ #include "Menu.h" #include "OffscreenUi.h" -#include "WindowScriptingInterface.h" - static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation"; static const QString LAST_BROWSE_ASSETS_LOCATION_SETTING = "LastBrowseAssetsLocation"; @@ -316,7 +317,7 @@ bool WindowScriptingInterface::isPhysicsEnabled() { int WindowScriptingInterface::openMessageBox(QString title, QString text, int buttons, int defaultButton) { if (QThread::currentThread() != thread()) { int result; - QMetaObject::invokeMethod(this, "openMessageBox", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "openMessageBox", Q_RETURN_ARG(int, result), Q_ARG(QString, title), Q_ARG(QString, text), diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 4fb4829636..f8ed20f42f 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -18,6 +18,8 @@ #include #include +#include + class CustomPromptResult { public: QVariant value; diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 79314ce49a..4b03d1b575 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -115,7 +116,7 @@ void JSConsole::executeCommand(const QString& command) { QScriptValue JSConsole::executeCommandInWatcher(const QString& command) { QScriptValue result; - QMetaObject::invokeMethod(_scriptEngine, "evaluate", Qt::ConnectionType::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(_scriptEngine, "evaluate", Q_RETURN_ARG(QScriptValue, result), Q_ARG(const QString&, command), Q_ARG(const QString&, _consoleFileName)); diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 7d4c0f4e92..0bca721464 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -9,15 +9,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AnimationCache.h" + #include #include -#include "AnimationCache.h" -#include "AnimationLogging.h" +#include #include #include #include +#include "AnimationLogging.h" + int animationPointerMetaTypeId = qRegisterMetaType(); AnimationCache::AnimationCache(QObject* parent) : @@ -31,7 +34,7 @@ AnimationCache::AnimationCache(QObject* parent) : AnimationPointer AnimationCache::getAnimation(const QUrl& url) { if (QThread::currentThread() != thread()) { AnimationPointer result; - QMetaObject::invokeMethod(this, "getAnimation", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "getAnimation", Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url)); return result; } @@ -97,7 +100,7 @@ bool Animation::isLoaded() const { QStringList Animation::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; - QMetaObject::invokeMethod(const_cast(this), "getJointNames", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointNames", Q_RETURN_ARG(QStringList, result)); return result; } @@ -111,7 +114,7 @@ QStringList Animation::getJointNames() const { QVector Animation::getFrames() const { if (QThread::currentThread() != thread()) { QVector result; - QMetaObject::invokeMethod(const_cast(this), "getFrames", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getFrames", Q_RETURN_ARG(QVector, result)); return result; } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 43af7afdef..01af69e3ad 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1335,6 +1335,14 @@ void AudioClient::toggleMute() { emit muteToggled(); } +void AudioClient::setNoiseReduction(bool enable) { + if (_isNoiseGateEnabled != enable) { + _isNoiseGateEnabled = enable; + emit noiseReductionChanged(); + } +} + + void AudioClient::setIsStereoInput(bool isStereoInput) { if (isStereoInput != _isStereoInput) { _isStereoInput = isStereoInput; @@ -1446,6 +1454,8 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn _audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this); _numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat); _audioInput->setBufferSize(_numInputCallbackBytes); + // different audio input devices may have different volumes + emit inputVolumeChanged(_audioInput->volume()); // how do we want to handle input working, but output not working? int numFrameSamples = calculateNumberOfFrameSamples(_numInputCallbackBytes); @@ -1703,7 +1713,7 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) { // produce an oriented angle about the y-axis glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); - float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" + float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" return (direction.x < 0.0f) ? -angle : angle; } else { @@ -1847,3 +1857,10 @@ void AudioClient::setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 sca void AudioClient::startThread() { moveToNewNamedThread(this, "Audio Thread", [this] { start(); }); } + +void AudioClient::setInputVolume(float volume) { + if (_audioInput && volume != _audioInput->volume()) { + _audioInput->setVolume(volume); + emit inputVolumeChanged(_audioInput->volume()); + } +} diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 54ce3aa6c2..62b99d2443 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -180,7 +180,8 @@ public slots: virtual void setIsStereoInput(bool stereo) override; - void setNoiseReduction(bool isNoiseGateEnabled) { _isNoiseGateEnabled = isNoiseGateEnabled; } + void setNoiseReduction(bool isNoiseGateEnabled); + bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; } void toggleLocalEcho() { _shouldEchoLocally = !_shouldEchoLocally; } void toggleServerEcho() { _shouldEchoToServer = !_shouldEchoToServer; } @@ -197,7 +198,7 @@ public slots: bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName); float getInputVolume() const { return (_audioInput) ? (float)_audioInput->volume() : 0.0f; } - void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); } + void setInputVolume(float volume); void setReverb(bool reverb); void setReverbOptions(const AudioEffectOptions* options); @@ -207,7 +208,9 @@ public slots: void saveSettings(); signals: - bool muteToggled(); + void inputVolumeChanged(float volume); + void muteToggled(); + void noiseReductionChanged(); void mutedByMixer(); void inputReceived(const QByteArray& inputSamples); void inputLoudnessChanged(float loudness); diff --git a/libraries/audio/src/SoundCache.cpp b/libraries/audio/src/SoundCache.cpp index 1646540da6..dc20b9884d 100644 --- a/libraries/audio/src/SoundCache.cpp +++ b/libraries/audio/src/SoundCache.cpp @@ -9,10 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "SoundCache.h" + +#include + +#include #include "AudioLogging.h" -#include "SoundCache.h" static const int SOUNDS_LOADING_PRIORITY { -7 }; // Make sure sounds load after the low rez texture mips @@ -29,7 +32,7 @@ SoundCache::SoundCache(QObject* parent) : SharedSoundPointer SoundCache::getSound(const QUrl& url) { if (QThread::currentThread() != thread()) { SharedSoundPointer result; - QMetaObject::invokeMethod(this, "getSound", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "getSound", Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url)); return result; } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a0a348388e..faebeafb29 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -1010,7 +1011,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { int Avatar::getJointIndex(const QString& name) const { if (QThread::currentThread() != thread()) { int result; - QMetaObject::invokeMethod(const_cast(this), "getJointIndex", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointIndex", Q_RETURN_ARG(int, result), Q_ARG(const QString&, name)); return result; } @@ -1024,7 +1025,7 @@ int Avatar::getJointIndex(const QString& name) const { QStringList Avatar::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; - QMetaObject::invokeMethod(const_cast(this), "getJointNames", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointNames", Q_RETURN_ARG(QStringList, result)); return result; } @@ -1034,7 +1035,7 @@ QStringList Avatar::getJointNames() const { glm::vec3 Avatar::getJointPosition(int index) const { if (QThread::currentThread() != thread()) { glm::vec3 position; - QMetaObject::invokeMethod(const_cast(this), "getJointPosition", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointPosition", Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index)); return position; } @@ -1046,7 +1047,7 @@ glm::vec3 Avatar::getJointPosition(int index) const { glm::vec3 Avatar::getJointPosition(const QString& name) const { if (QThread::currentThread() != thread()) { glm::vec3 position; - QMetaObject::invokeMethod(const_cast(this), "getJointPosition", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointPosition", Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name)); return position; } @@ -1105,7 +1106,7 @@ static std::shared_ptr allocateAttachmentModel(bool isSoft, const Rig& ri void Avatar::setAttachmentData(const QVector& attachmentData) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setAttachmentData", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "setAttachmentData", Q_ARG(const QVector, attachmentData)); return; } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5023bd7ae5..5f63826a99 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1227,7 +1228,7 @@ bool AvatarData::isJointDataValid(int index) const { } if (QThread::currentThread() != thread()) { bool result; - QMetaObject::invokeMethod(const_cast(this), "isJointDataValid", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "isJointDataValid", Q_RETURN_ARG(bool, result), Q_ARG(int, index)); return result; } @@ -1240,7 +1241,7 @@ glm::quat AvatarData::getJointRotation(int index) const { } if (QThread::currentThread() != thread()) { glm::quat result; - QMetaObject::invokeMethod(const_cast(this), "getJointRotation", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointRotation", Q_RETURN_ARG(glm::quat, result), Q_ARG(int, index)); return result; } @@ -1255,7 +1256,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const { } if (QThread::currentThread() != thread()) { glm::vec3 result; - QMetaObject::invokeMethod(const_cast(this), "getJointTranslation", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointTranslation", Q_RETURN_ARG(glm::vec3, result), Q_ARG(int, index)); return result; } @@ -1266,7 +1267,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const { glm::vec3 AvatarData::getJointTranslation(const QString& name) const { if (QThread::currentThread() != thread()) { glm::vec3 result; - QMetaObject::invokeMethod(const_cast(this), "getJointTranslation", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointTranslation", Q_RETURN_ARG(glm::vec3, result), Q_ARG(const QString&, name)); return result; } @@ -1344,7 +1345,7 @@ void AvatarData::clearJointData(const QString& name) { bool AvatarData::isJointDataValid(const QString& name) const { if (QThread::currentThread() != thread()) { bool result; - QMetaObject::invokeMethod(const_cast(this), "isJointDataValid", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "isJointDataValid", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, name)); return result; } @@ -1354,7 +1355,7 @@ bool AvatarData::isJointDataValid(const QString& name) const { glm::quat AvatarData::getJointRotation(const QString& name) const { if (QThread::currentThread() != thread()) { glm::quat result; - QMetaObject::invokeMethod(const_cast(this), "getJointRotation", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointRotation", Q_RETURN_ARG(glm::quat, result), Q_ARG(const QString&, name)); return result; } @@ -1364,8 +1365,7 @@ glm::quat AvatarData::getJointRotation(const QString& name) const { QVector AvatarData::getJointRotations() const { if (QThread::currentThread() != thread()) { QVector result; - QMetaObject::invokeMethod(const_cast(this), - "getJointRotations", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointRotations", Q_RETURN_ARG(QVector, result)); return result; } @@ -1380,8 +1380,7 @@ QVector AvatarData::getJointRotations() const { void AvatarData::setJointRotations(QVector jointRotations) { if (QThread::currentThread() != thread()) { QVector result; - QMetaObject::invokeMethod(const_cast(this), - "setJointRotations", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "setJointRotations", Q_ARG(QVector, jointRotations)); } QWriteLocker writeLock(&_jointDataLock); @@ -1398,8 +1397,7 @@ void AvatarData::setJointRotations(QVector jointRotations) { QVector AvatarData::getJointTranslations() const { if (QThread::currentThread() != thread()) { QVector result; - QMetaObject::invokeMethod(const_cast(this), - "getJointTranslations", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointTranslations", Q_RETURN_ARG(QVector, result)); return result; } @@ -1414,8 +1412,7 @@ QVector AvatarData::getJointTranslations() const { void AvatarData::setJointTranslations(QVector jointTranslations) { if (QThread::currentThread() != thread()) { QVector result; - QMetaObject::invokeMethod(const_cast(this), - "setJointTranslations", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "setJointTranslations", Q_ARG(QVector, jointTranslations)); } QWriteLocker writeLock(&_jointDataLock); @@ -1616,7 +1613,7 @@ void AvatarData::setDisplayName(const QString& displayName) { QVector AvatarData::getAttachmentData() const { if (QThread::currentThread() != thread()) { QVector result; - QMetaObject::invokeMethod(const_cast(this), "getAttachmentData", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getAttachmentData", Q_RETURN_ARG(QVector, result)); return result; } @@ -2339,7 +2336,7 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID) { AvatarEntityMap AvatarData::getAvatarEntityData() const { AvatarEntityMap result; if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(const_cast(this), "getAvatarEntityData", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getAvatarEntityData", Q_RETURN_ARG(AvatarEntityMap, result)); return result; } @@ -2380,7 +2377,7 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() { AvatarEntityIDs result; if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(const_cast(this), "getAndClearRecentlyDetachedIDs", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getAndClearRecentlyDetachedIDs", Q_RETURN_ARG(AvatarEntityIDs, result)); return result; } diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index d8e0c59da7..92abec78fa 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -11,14 +11,16 @@ #include #include +#include + #include #include #include #include -#include #include #include +#include #include #include #include @@ -289,7 +291,7 @@ glm::vec2 CompositorHelper::getReticleMaximumPosition() const { void CompositorHelper::sendFakeMouseEvent() { if (qApp->thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "sendFakeMouseEvent", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "sendFakeMouseEvent"); return; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 1684c06512..fbf76df38e 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -380,7 +381,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading // Only create and delete models on the thread that owns the EntityTreeRenderer if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "allocateModel", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "allocateModel", Q_RETURN_ARG(ModelPointer, model), Q_ARG(const QString&, url)); @@ -397,7 +398,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading ModelPointer EntityTreeRenderer::updateModel(ModelPointer model, const QString& newUrl) { // Only create and delete models on the thread that owns the EntityTreeRenderer if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "updateModel", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "updateModel", Q_RETURN_ARG(ModelPointer, model), Q_ARG(ModelPointer, model), Q_ARG(const QString&, newUrl)); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7351d49dff..ae9f79f0f6 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -9,19 +9,20 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityScriptingInterface.h" + #include #include -#include "EntityScriptingInterface.h" - #include #include -#include "EntityItemID.h" +#include #include #include #include +#include "EntityItemID.h" #include "EntitiesLogging.h" #include "EntityDynamicFactoryInterface.h" #include "EntityDynamicInterface.h" @@ -1488,7 +1489,7 @@ int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString return -1; } int result; - QMetaObject::invokeMethod(_entityTree.get(), "getJointIndex", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(_entityTree.get(), "getJointIndex", Q_RETURN_ARG(int, result), Q_ARG(QUuid, entityID), Q_ARG(QString, name)); return result; } @@ -1498,7 +1499,7 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) { return QStringList(); } QStringList result; - QMetaObject::invokeMethod(_entityTree.get(), "getJointNames", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(_entityTree.get(), "getJointNames", Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID)); return result; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e8506e5263..82314d0cd1 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -232,7 +233,7 @@ void NodeList::processICEPingPacket(QSharedPointer message) { void NodeList::reset() { if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "reset", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "reset"); return; } diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index f07514cd85..0c91a581ce 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -9,22 +9,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ResourceCache.h" + #include #include +#include #include #include #include -#include +#include +#include +#include #include "NetworkAccessManager.h" #include "NetworkLogging.h" #include "NodeList.h" -#include "ResourceCache.h" -#include -#include #define clamp(x, min, max) (((x) < (min)) ? (min) :\ (((x) > (max)) ? (max) :\ @@ -178,7 +180,7 @@ ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) { if (QThread::currentThread() != thread()) { // Must be called in thread to ensure getResource returns a valid pointer - QMetaObject::invokeMethod(this, "prefetch", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "prefetch", Q_RETURN_ARG(ScriptableResource*, result), Q_ARG(QUrl, url), Q_ARG(void*, extra)); return result; @@ -301,7 +303,7 @@ QVariantList ResourceCache::getResourceList() { QVariantList list; if (QThread::currentThread() != thread()) { // NOTE: invokeMethod does not allow a const QObject* - QMetaObject::invokeMethod(this, "getResourceList", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "getResourceList", Q_RETURN_ARG(QVariantList, list)); } else { auto resources = _resources.uniqueKeys(); diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 357f8a64d8..89a6758366 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -17,6 +17,7 @@ #include +#include #include #include "../NetworkLogging.h" @@ -276,7 +277,7 @@ Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) { void Socket::clearConnections() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "clearConnections", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "clearConnections"); return; } diff --git a/libraries/plugins/src/plugins/InputConfiguration.cpp b/libraries/plugins/src/plugins/InputConfiguration.cpp index 04b1e3b370..8ce206988b 100644 --- a/libraries/plugins/src/plugins/InputConfiguration.cpp +++ b/libraries/plugins/src/plugins/InputConfiguration.cpp @@ -11,6 +11,8 @@ #include +#include + #include "DisplayPlugin.h" #include "InputPlugin.h" #include "PluginManager.h" @@ -21,7 +23,7 @@ InputConfiguration::InputConfiguration() { QStringList InputConfiguration::inputPlugins() { if (QThread::currentThread() != thread()) { QStringList result; - QMetaObject::invokeMethod(this, "inputPlugins", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "inputPlugins", Q_RETURN_ARG(QStringList, result)); return result; } @@ -42,7 +44,7 @@ QStringList InputConfiguration::inputPlugins() { QStringList InputConfiguration::activeInputPlugins() { if (QThread::currentThread() != thread()) { QStringList result; - QMetaObject::invokeMethod(this, "activeInputPlugins", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "activeInputPlugins", Q_RETURN_ARG(QStringList, result)); return result; } @@ -64,7 +66,7 @@ QStringList InputConfiguration::activeInputPlugins() { QString InputConfiguration::configurationLayout(QString pluginName) { if (QThread::currentThread() != thread()) { QString result; - QMetaObject::invokeMethod(this, "configurationLayout", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "configurationLayout", Q_RETURN_ARG(QString, result), Q_ARG(QString, pluginName)); return result; @@ -81,7 +83,7 @@ QString InputConfiguration::configurationLayout(QString pluginName) { void InputConfiguration::setConfigurationSettings(QJsonObject configurationSettings, QString pluginName) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setConfigurationSettings", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "setConfigurationSettings", Q_ARG(QJsonObject, configurationSettings), Q_ARG(QString, pluginName)); return; @@ -97,7 +99,7 @@ void InputConfiguration::setConfigurationSettings(QJsonObject configurationSetti QJsonObject InputConfiguration::configurationSettings(QString pluginName) { if (QThread::currentThread() != thread()) { QJsonObject result; - QMetaObject::invokeMethod(this, "configurationSettings", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "configurationSettings", Q_RETURN_ARG(QJsonObject, result), Q_ARG(QString, pluginName)); return result; @@ -113,7 +115,7 @@ QJsonObject InputConfiguration::configurationSettings(QString pluginName) { void InputConfiguration::calibratePlugin(QString pluginName) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "calibratePlugin", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "calibratePlugin"); return; } @@ -128,7 +130,7 @@ void InputConfiguration::calibratePlugin(QString pluginName) { bool InputConfiguration::uncalibratePlugin(QString pluginName) { if (QThread::currentThread() != thread()) { bool result; - QMetaObject::invokeMethod(this, "uncalibratePlugin", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "uncalibratePlugin", Q_ARG(bool, result)); return result; } diff --git a/libraries/recording/src/recording/ClipCache.cpp b/libraries/recording/src/recording/ClipCache.cpp index 5c55c6bb1c..458979bf96 100644 --- a/libraries/recording/src/recording/ClipCache.cpp +++ b/libraries/recording/src/recording/ClipCache.cpp @@ -8,6 +8,8 @@ #include +#include + #include "ClipCache.h" #include "impl/PointerClip.h" #include "Logging.h" @@ -37,7 +39,7 @@ ClipCache::ClipCache(QObject* parent) : NetworkClipLoaderPointer ClipCache::getClipLoader(const QUrl& url) { if (QThread::currentThread() != thread()) { NetworkClipLoaderPointer result; - QMetaObject::invokeMethod(this, "getClipLoader", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "getClipLoader", Q_RETURN_ARG(NetworkClipLoaderPointer, result), Q_ARG(const QUrl&, url)); return result; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 67452c5d33..94b074d1e3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -870,7 +871,7 @@ bool Model::getRelativeDefaultJointTranslation(int jointIndex, glm::vec3& transl QStringList Model::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; - QMetaObject::invokeMethod(const_cast(this), "getJointNames", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(const_cast(this), "getJointNames", Q_RETURN_ARG(QStringList, result)); return result; } diff --git a/libraries/render/src/task/Config.cpp b/libraries/render/src/task/Config.cpp index 0e630311f6..d1edd8bda8 100644 --- a/libraries/render/src/task/Config.cpp +++ b/libraries/render/src/task/Config.cpp @@ -10,9 +10,12 @@ // #include "Config.h" -#include "Task.h" #include +#include + +#include "Task.h" + using namespace task; void JobConfig::setPresetList(const QJsonObject& object) { @@ -58,7 +61,7 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) { void TaskConfig::refresh() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "refresh", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "refresh"); return; } diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index ecaffaf35c..4023af375a 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -13,6 +13,8 @@ #include +#include + #include "ScriptAudioInjector.h" #include "ScriptEngineLogging.h" @@ -32,7 +34,7 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(SharedSoundPointer sound if (QThread::currentThread() != thread()) { ScriptAudioInjector* injector = NULL; - QMetaObject::invokeMethod(this, "playSound", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "playSound", Q_RETURN_ARG(ScriptAudioInjector*, injector), Q_ARG(SharedSoundPointer, sound), Q_ARG(const AudioInjectorOptions&, injectorOptions)); diff --git a/libraries/script-engine/src/RecordingScriptingInterface.cpp b/libraries/script-engine/src/RecordingScriptingInterface.cpp index 7583f562e6..cd5b79b4a8 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.cpp +++ b/libraries/script-engine/src/RecordingScriptingInterface.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -98,7 +99,7 @@ void RecordingScriptingInterface::loadRecording(const QString& url, QScriptValue void RecordingScriptingInterface::startPlaying() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "startPlaying", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "startPlaying"); return; } @@ -115,7 +116,7 @@ void RecordingScriptingInterface::setPlayerAudioOffset(float audioOffset) { void RecordingScriptingInterface::setPlayerTime(float time) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setPlayerTime", Qt::BlockingQueuedConnection, Q_ARG(float, time)); + hifi::qt::blockingInvokeMethod(this, "setPlayerTime", Q_ARG(float, time)); return; } _player->seek(time); @@ -147,7 +148,7 @@ void RecordingScriptingInterface::setPlayerUseSkeletonModel(bool useSkeletonMode void RecordingScriptingInterface::pausePlayer() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "pausePlayer", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "pausePlayer"); return; } _player->pause(); @@ -155,7 +156,7 @@ void RecordingScriptingInterface::pausePlayer() { void RecordingScriptingInterface::stopPlaying() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "stopPlaying", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "stopPlaying"); return; } _player->stop(); @@ -176,7 +177,7 @@ void RecordingScriptingInterface::startRecording() { } if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "startRecording", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "startRecording"); return; } @@ -199,7 +200,7 @@ QString RecordingScriptingInterface::getDefaultRecordingSaveDirectory() { void RecordingScriptingInterface::saveRecording(const QString& filename) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "saveRecording", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "saveRecording", Q_ARG(QString, filename)); return; } @@ -220,7 +221,7 @@ bool RecordingScriptingInterface::saveRecordingToAsset(QScriptValue getClipAtpUr if (QThread::currentThread() != thread()) { bool result; - QMetaObject::invokeMethod(this, "saveRecordingToAsset", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "saveRecordingToAsset", Q_RETURN_ARG(bool, result), Q_ARG(QScriptValue, getClipAtpUrl)); return result; @@ -257,7 +258,7 @@ bool RecordingScriptingInterface::saveRecordingToAsset(QScriptValue getClipAtpUr void RecordingScriptingInterface::loadLastRecording() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "loadLastRecording", Qt::BlockingQueuedConnection); + hifi::qt::blockingInvokeMethod(this, "loadLastRecording"); return; } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 11bb044d72..52ce11c3cf 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -36,6 +36,7 @@ #include +#include #include #include #include @@ -436,12 +437,12 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { _fileNameString = url.toString(); _isReloading = reload; - // Check that script has a supported file extension + // Check that script has a supported file extension if (!hasValidScriptSuffix(_fileNameString)) { scriptErrorMessage("File extension of file: " + _fileNameString + " is not a currently supported script type"); emit errorLoadingScript(_fileNameString); return; - } + } const auto maxRetries = 0; // for consistency with previous scriptCache->getScript() behavior auto scriptCache = DependencyManager::get(); @@ -964,7 +965,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " "sourceCode:" << sourceCode << " fileName:" << fileName << "lineNumber:" << lineNumber; #endif - QMetaObject::invokeMethod(this, "evaluate", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "evaluate", Q_RETURN_ARG(QScriptValue, result), Q_ARG(const QString&, sourceCode), Q_ARG(const QString&, fileName), diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 72392ac376..254312fa45 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -452,7 +453,7 @@ ScriptEngine* ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserL bool activateMainWindow, bool reload) { if (thread() != QThread::currentThread()) { ScriptEngine* result { nullptr }; - QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result), + hifi::qt::blockingInvokeMethod(this, "loadScript", Q_RETURN_ARG(ScriptEngine*, result), Q_ARG(QUrl, scriptFilename), Q_ARG(bool, isUserLoaded), Q_ARG(bool, loadScriptFromEditor), diff --git a/libraries/shared/src/ThreadHelpers.h b/libraries/shared/src/ThreadHelpers.h index 6461fa5724..6e024f787a 100644 --- a/libraries/shared/src/ThreadHelpers.h +++ b/libraries/shared/src/ThreadHelpers.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -34,4 +35,25 @@ void withLock(QMutex& lock, F function) { void moveToNewNamedThread(QObject* object, const QString& name, std::function startCallback, QThread::Priority priority = QThread::InheritPriority); void moveToNewNamedThread(QObject* object, const QString& name, QThread::Priority priority = QThread::InheritPriority); +class ConditionalGuard { +public: + void trigger() { + QMutexLocker locker(&_mutex); + _triggered = true; + _condition.wakeAll(); + } + + bool wait(unsigned long time = ULONG_MAX) { + QMutexLocker locker(&_mutex); + if (!_triggered) { + _condition.wait(&_mutex, time); + } + return _triggered; + } +private: + QMutex _mutex; + QWaitCondition _condition; + bool _triggered { false }; +}; + #endif diff --git a/libraries/shared/src/shared/QtHelpers.cpp b/libraries/shared/src/shared/QtHelpers.cpp new file mode 100644 index 0000000000..3681136bf2 --- /dev/null +++ b/libraries/shared/src/shared/QtHelpers.cpp @@ -0,0 +1,57 @@ +// +// Created by Bradley Austin Davis on 2015/11/09 +// Copyright 2013-2015 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 "QtHelpers.h" + +#include +#include +#include + +Q_LOGGING_CATEGORY(thread_safety, "hifi.thread_safety") + +namespace hifi { namespace qt { + +bool blockingInvokeMethod( + QObject *obj, const char *member, + QGenericReturnArgument ret, + QGenericArgument val0, + QGenericArgument val1, + QGenericArgument val2, + QGenericArgument val3, + QGenericArgument val4, + QGenericArgument val5, + QGenericArgument val6, + QGenericArgument val7, + QGenericArgument val8, + QGenericArgument val9) { + if (QThread::currentThread() == qApp->thread()) { + qCWarning(thread_safety, "BlockingQueuedConnection invoked on main thread!"); + } + return QMetaObject::invokeMethod(obj, member, + Qt::BlockingQueuedConnection, ret, val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); +} + +bool blockingInvokeMethod( + QObject *obj, const char *member, + QGenericArgument val0, + QGenericArgument val1, + QGenericArgument val2, + QGenericArgument val3, + QGenericArgument val4, + QGenericArgument val5, + QGenericArgument val6, + QGenericArgument val7, + QGenericArgument val8, + QGenericArgument val9) { + qCWarning(thread_safety, "BlockingQueuedConnection invoked without return value!"); + return blockingInvokeMethod(obj, member, QGenericReturnArgument(), val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); +} + + + +} } diff --git a/libraries/shared/src/shared/QtHelpers.h b/libraries/shared/src/shared/QtHelpers.h new file mode 100644 index 0000000000..7b5a15a069 --- /dev/null +++ b/libraries/shared/src/shared/QtHelpers.h @@ -0,0 +1,47 @@ +// +// Created by Bradley Austin Davis on 2017/06/29 +// Copyright 2013-2015 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 +// + +#pragma once +#ifndef hifi_Shared_QtHelpers_h +#define hifi_Shared_QtHelpers_h + +#include + +namespace hifi { namespace qt { + +bool blockingInvokeMethod( + QObject *obj, const char *member, + QGenericReturnArgument ret, + QGenericArgument val0 = QGenericArgument(Q_NULLPTR), + QGenericArgument val1 = QGenericArgument(), + QGenericArgument val2 = QGenericArgument(), + QGenericArgument val3 = QGenericArgument(), + QGenericArgument val4 = QGenericArgument(), + QGenericArgument val5 = QGenericArgument(), + QGenericArgument val6 = QGenericArgument(), + QGenericArgument val7 = QGenericArgument(), + QGenericArgument val8 = QGenericArgument(), + QGenericArgument val9 = QGenericArgument()); + +bool blockingInvokeMethod( + QObject *obj, const char *member, + QGenericArgument val0 = QGenericArgument(Q_NULLPTR), + QGenericArgument val1 = QGenericArgument(), + QGenericArgument val2 = QGenericArgument(), + QGenericArgument val3 = QGenericArgument(), + QGenericArgument val4 = QGenericArgument(), + QGenericArgument val5 = QGenericArgument(), + QGenericArgument val6 = QGenericArgument(), + QGenericArgument val7 = QGenericArgument(), + QGenericArgument val8 = QGenericArgument(), + QGenericArgument val9 = QGenericArgument()); + +} } + + +#endif diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 76a8a780b9..2bc5f89d00 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -249,7 +250,7 @@ int OffscreenUi::waitForMessageBoxResult(QQuickItem* messageBox) { QMessageBox::StandardButton OffscreenUi::messageBox(Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { if (QThread::currentThread() != thread()) { QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton; - QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "messageBox", Q_RETURN_ARG(QMessageBox::StandardButton, result), Q_ARG(Icon, icon), Q_ARG(QString, title), @@ -351,7 +352,7 @@ QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) { if (QThread::currentThread() != thread()) { QVariant result; - QMetaObject::invokeMethod(this, "inputDialog", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "inputDialog", Q_RETURN_ARG(QVariant, result), Q_ARG(Icon, icon), Q_ARG(QString, title), @@ -366,7 +367,7 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q QVariant OffscreenUi::customInputDialog(const Icon icon, const QString& title, const QVariantMap& config) { if (QThread::currentThread() != thread()) { QVariant result; - QMetaObject::invokeMethod(this, "customInputDialog", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "customInputDialog", Q_RETURN_ARG(QVariant, result), Q_ARG(Icon, icon), Q_ARG(QString, title), @@ -640,7 +641,7 @@ QString OffscreenUi::fileDialog(const QVariantMap& properties) { QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { if (QThread::currentThread() != thread()) { QString result; - QMetaObject::invokeMethod(this, "fileOpenDialog", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "fileOpenDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), @@ -662,7 +663,7 @@ QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, QString OffscreenUi::fileSaveDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { if (QThread::currentThread() != thread()) { QString result; - QMetaObject::invokeMethod(this, "fileSaveDialog", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "fileSaveDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), @@ -686,7 +687,7 @@ QString OffscreenUi::fileSaveDialog(const QString& caption, const QString& dir, QString OffscreenUi::existingDirectoryDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { if (QThread::currentThread() != thread()) { QString result; - QMetaObject::invokeMethod(this, "existingDirectoryDialog", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "existingDirectoryDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), @@ -773,7 +774,7 @@ QString OffscreenUi::assetOpenDialog(const QString& caption, const QString& dir, // ATP equivalent of fileOpenDialog(). if (QThread::currentThread() != thread()) { QString result; - QMetaObject::invokeMethod(this, "assetOpenDialog", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "assetOpenDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index 7511448c38..7aa4bc5e17 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -13,12 +13,12 @@ #include #include +#include #include "../VrMenu.h" #include "../OffscreenUi.h" #include "Logging.h" - using namespace ui; static QList groups; @@ -246,7 +246,7 @@ void Menu::removeAction(MenuWrapper* menu, const QString& actionName) { void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) { if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "setIsOptionChecked", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "setIsOptionChecked", Q_ARG(const QString&, menuOption), Q_ARG(bool, isChecked)); return; diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 648bdad1bf..573d873bab 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include #include @@ -34,7 +36,6 @@ #include #include #include -#include #include #include @@ -899,7 +900,7 @@ void OffscreenQmlSurface::executeOnUiThread(std::function function, bool QVariant OffscreenQmlSurface::returnFromUiThread(std::function function) { if (QThread::currentThread() != thread()) { QVariant result; - QMetaObject::invokeMethod(this, "returnFromUiThread", Qt::BlockingQueuedConnection, + hifi::qt::blockingInvokeMethod(this, "returnFromUiThread", Q_RETURN_ARG(QVariant, result), Q_ARG(std::function, function)); return result; diff --git a/libraries/ui/src/ui/QmlWrapper.cpp b/libraries/ui/src/ui/QmlWrapper.cpp index 518a05613a..d0f9a5e535 100644 --- a/libraries/ui/src/ui/QmlWrapper.cpp +++ b/libraries/ui/src/ui/QmlWrapper.cpp @@ -11,6 +11,8 @@ #include #include +#include + QmlWrapper::QmlWrapper(QObject* qmlObject, QObject* parent) : QObject(parent), _qmlObject(qmlObject) { Q_ASSERT(QThread::currentThread() == qApp->thread()); @@ -36,7 +38,7 @@ void QmlWrapper::writeProperties(QVariant propertyMap) { QVariant QmlWrapper::readProperty(const QString& propertyName) { if (QThread::currentThread() != thread()) { QVariant result; - QMetaObject::invokeMethod(this, "readProperty", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVariant, result), Q_ARG(QString, propertyName)); + hifi::qt::blockingInvokeMethod(this, "readProperty", Q_RETURN_ARG(QVariant, result), Q_ARG(QString, propertyName)); return result; } @@ -46,7 +48,7 @@ QVariant QmlWrapper::readProperty(const QString& propertyName) { QVariant QmlWrapper::readProperties(const QVariant& propertyList) { if (QThread::currentThread() != thread()) { QVariant result; - QMetaObject::invokeMethod(this, "readProperties", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, propertyList)); + hifi::qt::blockingInvokeMethod(this, "readProperties", Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, propertyList)); return result; } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 1e426dd8f0..ade8c73df5 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,7 @@ ToolbarProxy* TabletScriptingInterface::getSystemToolbarProxy() { TabletProxy* TabletScriptingInterface::getTablet(const QString& tabletId) { TabletProxy* tabletProxy = nullptr; if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "getTablet", Qt::BlockingQueuedConnection, Q_RETURN_ARG(TabletProxy*, tabletProxy), Q_ARG(QString, tabletId)); + hifi::qt::blockingInvokeMethod(this, "getTablet", Q_RETURN_ARG(TabletProxy*, tabletProxy), Q_ARG(QString, tabletId)); return tabletProxy; } @@ -292,7 +293,7 @@ void TabletProxy::initialScreen(const QVariant& url) { bool TabletProxy::isMessageDialogOpen() { if (QThread::currentThread() != thread()) { bool result = false; - QMetaObject::invokeMethod(this, "isMessageDialogOpen", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result)); + hifi::qt::blockingInvokeMethod(this, "isMessageDialogOpen", Q_RETURN_ARG(bool, result)); return result; } @@ -317,7 +318,7 @@ void TabletProxy::emitWebEvent(const QVariant& msg) { bool TabletProxy::isPathLoaded(const QVariant& path) { if (QThread::currentThread() != thread()) { bool result = false; - QMetaObject::invokeMethod(this, "isPathLoaded", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); + hifi::qt::blockingInvokeMethod(this, "isPathLoaded", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); return result; } @@ -480,7 +481,7 @@ void TabletProxy::loadQMLSource(const QVariant& path) { bool TabletProxy::pushOntoStack(const QVariant& path) { if (QThread::currentThread() != thread()) { bool result = false; - QMetaObject::invokeMethod(this, "pushOntoStack", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); + hifi::qt::blockingInvokeMethod(this, "pushOntoStack", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); return result; } @@ -606,7 +607,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { if (QThread::currentThread() != thread()) { TabletButtonProxy* result = nullptr; - QMetaObject::invokeMethod(this, "addButton", Qt::BlockingQueuedConnection, Q_RETURN_ARG(TabletButtonProxy*, result), Q_ARG(QVariant, properties)); + hifi::qt::blockingInvokeMethod(this, "addButton", Q_RETURN_ARG(TabletButtonProxy*, result), Q_ARG(QVariant, properties)); return result; } @@ -633,7 +634,7 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { bool TabletProxy::onHomeScreen() { if (QThread::currentThread() != thread()) { bool result = false; - QMetaObject::invokeMethod(this, "onHomeScreen", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result)); + hifi::qt::blockingInvokeMethod(this, "onHomeScreen", Q_RETURN_ARG(bool, result)); return result; } @@ -840,7 +841,7 @@ void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { QVariantMap TabletButtonProxy::getProperties() { if (QThread::currentThread() != thread()) { QVariantMap result; - QMetaObject::invokeMethod(this, "getProperties", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVariantMap, result)); + hifi::qt::blockingInvokeMethod(this, "getProperties", Q_RETURN_ARG(QVariantMap, result)); return result; } diff --git a/libraries/ui/src/ui/ToolbarScriptingInterface.cpp b/libraries/ui/src/ui/ToolbarScriptingInterface.cpp index 330c652cdc..adfc15cc83 100644 --- a/libraries/ui/src/ui/ToolbarScriptingInterface.cpp +++ b/libraries/ui/src/ui/ToolbarScriptingInterface.cpp @@ -12,6 +12,8 @@ #include #include #include + +#include #include "../OffscreenUi.h" QScriptValue toolbarToScriptValue(QScriptEngine* engine, ToolbarProxy* const &in) { @@ -68,7 +70,7 @@ ToolbarProxy::ToolbarProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qml ToolbarButtonProxy* ToolbarProxy::addButton(const QVariant& properties) { if (QThread::currentThread() != thread()) { ToolbarButtonProxy* result = nullptr; - QMetaObject::invokeMethod(this, "addButton", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ToolbarButtonProxy*, result), Q_ARG(QVariant, properties)); + hifi::qt::blockingInvokeMethod(this, "addButton", Q_RETURN_ARG(ToolbarButtonProxy*, result), Q_ARG(QVariant, properties)); return result; } @@ -99,18 +101,14 @@ void ToolbarProxy::removeButton(const QVariant& name) { ToolbarProxy* ToolbarScriptingInterface::getToolbar(const QString& toolbarId) { if (QThread::currentThread() != thread()) { ToolbarProxy* result = nullptr; - QMetaObject::invokeMethod(this, "getToolbar", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ToolbarProxy*, result), Q_ARG(QString, toolbarId)); + hifi::qt::blockingInvokeMethod(this, "getToolbar", Q_RETURN_ARG(ToolbarProxy*, result), Q_ARG(QString, toolbarId)); return result; } auto offscreenUi = DependencyManager::get(); auto desktop = offscreenUi->getDesktop(); - Qt::ConnectionType connectionType = Qt::AutoConnection; - if (QThread::currentThread() != desktop->thread()) { - connectionType = Qt::BlockingQueuedConnection; - } QVariant resultVar; - bool invokeResult = QMetaObject::invokeMethod(desktop, "getToolbar", connectionType, Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, toolbarId)); + bool invokeResult = QMetaObject::invokeMethod(desktop, "getToolbar", Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, toolbarId)); if (!invokeResult) { return nullptr; } From a3db9ae726efe37e4da4e7909a702ca107c37801 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Fri, 30 Jun 2017 15:40:42 +0100 Subject: [PATCH 09/24] Begin Rocket Hands branch --- scripts/developer/rockethands.js | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 scripts/developer/rockethands.js diff --git a/scripts/developer/rockethands.js b/scripts/developer/rockethands.js new file mode 100644 index 0000000000..b68d6cc9c6 --- /dev/null +++ b/scripts/developer/rockethands.js @@ -0,0 +1,35 @@ +"use strict"; + +// +// rockethands.js +// system +// +// Created by Cain Kilgore on 30/06/2017 +// 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 +// + +(function() { + function logToConsole(message) { + console.log("[rockethands.js] " + message); + } + + logToConsole("Rockethands.js script is now active."); + + Script.setInterval(function() { + if(Controller.Hardware.Vive) { + var rightHand = Controller.getPoseValue(Controller.Hardware.Vive.RightHand).rotation.y; + + // logToConsole("Y VALUE: " + rightHand); + if(rightHand < -0.1 && rightHand > -0.4) { + logToConsole("Pointing down.. eye position: " + Camera.getOrientation().x + ", " + Camera.getOrientation().y + ", " + Camera.getOrientation().z + " - we have liftoff - I think!"); + MyAvatar.motorReferenceFrame = "world"; + // MyAvatar.motorVelocity = {x: Camera.getOrientation().x, y: Camera.getOrientation().y*3, z: Camera.getOrientation().z}; + MyAvatar.motorVelocity = Camera.getOrientation()*3; + MyAvatar.motorTimescale = 1.0; + } + } + }, 1000); +}()); From 8372d73fec32336f3b6dc20f06909f930601f320 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 30 Jun 2017 09:15:06 -0700 Subject: [PATCH 10/24] Additional thread safety --- gvr-interface/src/RenderingClient.cpp | 5 +- interface/src/Application.cpp | 2 +- .../src/scripting/HMDScriptingInterface.cpp | 32 ++-- .../src/scripting/HMDScriptingInterface.h | 8 +- .../src/scripting/TestScriptingInterface.cpp | 26 +-- interface/src/ui/overlays/Image3DOverlay.cpp | 2 + interface/src/ui/overlays/Overlay.h | 6 +- interface/src/ui/overlays/OverlayPanel.cpp | 3 + interface/src/ui/overlays/OverlayPanel.h | 3 + interface/src/ui/overlays/Overlays.cpp | 167 +++++++++++++---- interface/src/ui/overlays/Overlays.h | 41 +++-- interface/src/ui/overlays/PanelAttachable.cpp | 6 + interface/src/ui/overlays/PanelAttachable.h | 9 +- interface/src/ui/overlays/QmlOverlay.cpp | 50 +++--- interface/src/ui/overlays/QmlOverlay.h | 2 +- libraries/audio-client/src/AudioClient.cpp | 15 +- libraries/ui/src/QmlWebWindowClass.cpp | 59 +++--- libraries/ui/src/QmlWebWindowClass.h | 2 +- libraries/ui/src/QmlWindowClass.cpp | 170 +++++++++++------- libraries/ui/src/QmlWindowClass.h | 8 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 22 --- libraries/ui/src/ui/OffscreenQmlSurface.h | 4 - .../ui/src/ui/TabletScriptingInterface.cpp | 20 +-- 23 files changed, 413 insertions(+), 249 deletions(-) diff --git a/gvr-interface/src/RenderingClient.cpp b/gvr-interface/src/RenderingClient.cpp index b7c6f30a73..f04be5cb7f 100644 --- a/gvr-interface/src/RenderingClient.cpp +++ b/gvr-interface/src/RenderingClient.cpp @@ -63,10 +63,7 @@ void RenderingClient::sendAvatarPacket() { } void RenderingClient::cleanupBeforeQuit() { - - QMetaObject::invokeMethod(DependencyManager::get().data(), - "stop", Qt::BlockingQueuedConnection); - + DependencyManager::get()->cleanupBeforeQuit(); // destroy the AudioClient so it and its thread will safely go down DependencyManager::destroy(); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a31877c1b..2b6c6033a2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1844,7 +1844,7 @@ void Application::cleanupBeforeQuit() { // FIXME: something else is holding a reference to AudioClient, // so it must be explicitly synchronously stopped here - QMetaObject::invokeMethod(DependencyManager::get().data(), "cleanupBeforeQuit", Qt::BlockingQueuedConnection); + DependencyManager::get()->cleanupBeforeQuit(); // destroy Audio so it and its threads have a chance to go down safely // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 883a6e758e..81a806b8ab 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -13,6 +13,7 @@ #include +#include #include #include #include @@ -152,22 +153,31 @@ QString HMDScriptingInterface::preferredAudioOutput() const { return qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice(); } -bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const { +bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) { + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "setHandLasers", Q_RETURN_ARG(bool, result), + Q_ARG(int, hands), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); + return result; + } + auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([offscreenUi, enabled] { - offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); - }); + offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); return qApp->getActiveDisplayPlugin()->setHandLaser(hands, enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None, color, direction); } -bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) const { - auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([offscreenUi, enabled] { - offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); - }); +bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) { + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "setExtraLaser", Q_RETURN_ARG(bool, result), + Q_ARG(glm::vec3, worldStart), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); + return result; + } + auto offscreenUi = DependencyManager::get(); + offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); auto myAvatar = DependencyManager::get()->getMyAvatar(); auto sensorToWorld = myAvatar->getSensorToWorldMatrix(); @@ -179,11 +189,11 @@ bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enab color, sensorStart, sensorDirection); } -void HMDScriptingInterface::disableExtraLaser() const { +void HMDScriptingInterface::disableExtraLaser() { setExtraLaser(vec3(0), false, vec4(0), vec3(0)); } -void HMDScriptingInterface::disableHandLasers(int hands) const { +void HMDScriptingInterface::disableHandLasers(int hands) { setHandLasers(hands, false, vec4(0), vec3(0)); } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 4657e61d05..3ed7db0232 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -51,11 +51,11 @@ public: Q_INVOKABLE void requestHideHandControllers(); Q_INVOKABLE bool shouldShowHandControllers() const; - Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const; - Q_INVOKABLE void disableHandLasers(int hands) const; + Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction); + Q_INVOKABLE void disableHandLasers(int hands); - Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) const; - Q_INVOKABLE void disableExtraLaser() const; + Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction); + Q_INVOKABLE void disableExtraLaser(); /// Suppress the activation of any on-screen keyboard so that a script operation will diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index 84c742d0ab..4d3e3b94a1 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -57,20 +58,25 @@ void TestScriptingInterface::waitIdle() { } bool TestScriptingInterface::loadTestScene(QString scene) { + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "loadTestScene", Q_RETURN_ARG(bool, result), Q_ARG(QString, scene)); + return result; + } + static const QString TEST_ROOT = "https://raw.githubusercontent.com/highfidelity/hifi_tests/master/"; static const QString TEST_BINARY_ROOT = "https://hifi-public.s3.amazonaws.com/test_scene_data/"; static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/"; static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/"; - return DependencyManager::get()->returnFromUiThread([scene]()->QVariant { - DependencyManager::get()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/"); - auto tree = qApp->getEntities()->getTree(); - auto treeIsClient = tree->getIsClient(); - // Force the tree to accept the load regardless of permissions - tree->setIsClient(false); - auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json"); - tree->setIsClient(treeIsClient); - return result; - }).toBool(); + + DependencyManager::get()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/"); + auto tree = qApp->getEntities()->getTree(); + auto treeIsClient = tree->getIsClient(); + // Force the tree to accept the load regardless of permissions + tree->setIsClient(false); + auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json"); + tree->setIsClient(treeIsClient); + return result; } bool TestScriptingInterface::startTracing(QString logrules) { diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 3e0bb74bc4..c8c9c36a1d 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -45,11 +45,13 @@ Image3DOverlay::~Image3DOverlay() { } void Image3DOverlay::update(float deltatime) { +#if OVERLAY_PANELS if (usecTimestampNow() > _transformExpiry) { Transform transform = getTransform(); applyTransformTo(transform); setTransform(transform); } +#endif } void Image3DOverlay::render(RenderArgs* args) { diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 4ad1b070b1..494c287676 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -84,9 +84,9 @@ public: void setColorPulse(float value) { _colorPulse = value; } void setAlphaPulse(float value) { _alphaPulse = value; } - virtual void setProperties(const QVariantMap& properties); - virtual Overlay* createClone() const = 0; - virtual QVariant getProperty(const QString& property); + Q_INVOKABLE virtual void setProperties(const QVariantMap& properties); + Q_INVOKABLE virtual Overlay* createClone() const = 0; + Q_INVOKABLE virtual QVariant getProperty(const QString& property); render::ItemID getRenderItemID() const { return _renderItemID; } void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; } diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index df2b91c4ef..06480109ce 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -11,6 +11,8 @@ #include "OverlayPanel.h" +#if OVERLAY_PANELS + #include #include #include @@ -185,3 +187,4 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) { pointTransformAtCamera(transform, getOffsetRotation()); } } +#endif \ No newline at end of file diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 5bffe3851e..cff2bc224d 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -22,6 +22,7 @@ #include "Billboardable.h" #include "Overlay.h" +#if OVERLAY_PANELS class PropertyBinding { public: PropertyBinding() {} @@ -80,4 +81,6 @@ private: QScriptEngine* _scriptEngine; }; +#endif + #endif // hifi_OverlayPanel_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index a9efd51a3e..c27800a5bb 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -14,6 +14,7 @@ #include +#include #include #include #include @@ -40,8 +41,6 @@ Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") void Overlays::cleanupAllOverlays() { { - QWriteLocker lock(&_lock); - QWriteLocker deleteLock(&_deleteLock); foreach(Overlay::Pointer overlay, _overlaysHUD) { _overlaysToDelete.push_back(overlay); } @@ -50,19 +49,22 @@ void Overlays::cleanupAllOverlays() { } _overlaysHUD.clear(); _overlaysWorld.clear(); +#if OVERLAY_PANELS _panels.clear(); +#endif } cleanupOverlaysToDelete(); } void Overlays::init() { +#if OVERLAY_PANELS _scriptEngine = new QScriptEngine(); +#endif } void Overlays::update(float deltatime) { { - QWriteLocker lock(&_lock); foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { thisOverlay->update(deltatime); } @@ -80,8 +82,6 @@ void Overlays::cleanupOverlaysToDelete() { render::Transaction transaction; { - QWriteLocker lock(&_deleteLock); - do { Overlay::Pointer overlay = _overlaysToDelete.takeLast(); @@ -100,7 +100,6 @@ void Overlays::cleanupOverlaysToDelete() { void Overlays::renderHUD(RenderArgs* renderArgs) { PROFILE_RANGE(render_overlays, __FUNCTION__); - QReadLocker lock(&_lock); gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); @@ -126,12 +125,10 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { } void Overlays::disable() { - QWriteLocker lock(&_lock); _enabled = false; } void Overlays::enable() { - QWriteLocker lock(&_lock); _enabled = true; } @@ -146,6 +143,12 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const { } OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) { + if (QThread::currentThread() != thread()) { + OverlayID result; + hifi::qt::blockingInvokeMethod(this, "addOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(QString, type), Q_ARG(QVariant, properties)); + return result; + } + Overlay::Pointer thisOverlay = nullptr; if (type == ImageOverlay::TYPE) { @@ -185,8 +188,7 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) return UNKNOWN_OVERLAY_ID; } -OverlayID Overlays::addOverlay(Overlay::Pointer overlay) { - QWriteLocker lock(&_lock); +OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { OverlayID thisID = OverlayID(QUuid::createUuid()); overlay->setOverlayID(thisID); overlay->setStackOrder(_stackOrder++); @@ -205,14 +207,22 @@ OverlayID Overlays::addOverlay(Overlay::Pointer overlay) { } OverlayID Overlays::cloneOverlay(OverlayID id) { + if (QThread::currentThread() != thread()) { + OverlayID result; + hifi::qt::blockingInvokeMethod(this, "cloneOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(OverlayID, id)); + return result; + } + Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone())); +#if OVERLAY_PANELS auto attachable = std::dynamic_pointer_cast(thisOverlay); if (attachable && attachable->getParentPanel()) { attachable->getParentPanel()->addChild(cloneId); } +#endif return cloneId; } @@ -220,21 +230,29 @@ OverlayID Overlays::cloneOverlay(OverlayID id) { } bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { - QWriteLocker lock(&_lock); + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "editOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id), Q_ARG(QVariant, properties)); + return result; + } Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { thisOverlay->setProperties(properties.toMap()); - return true; } return false; } bool Overlays::editOverlays(const QVariant& propertiesById) { + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "editOverlays", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, propertiesById)); + return result; + } + QVariantMap map = propertiesById.toMap(); bool success = true; - QWriteLocker lock(&_lock); for (const auto& key : map.keys()) { OverlayID id = OverlayID(key); Overlay::Pointer thisOverlay = getOverlay(id); @@ -249,10 +267,14 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { } void Overlays::deleteOverlay(OverlayID id) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "deleteOverlay", Q_ARG(OverlayID, id)); + return; + } + Overlay::Pointer overlayToDelete; { - QWriteLocker lock(&_lock); if (_overlaysHUD.contains(id)) { overlayToDelete = _overlaysHUD.take(id); } else if (_overlaysWorld.contains(id)) { @@ -262,19 +284,25 @@ void Overlays::deleteOverlay(OverlayID id) { } } +#if OVERLAY_PANELS auto attachable = std::dynamic_pointer_cast(overlayToDelete); if (attachable && attachable->getParentPanel()) { attachable->getParentPanel()->removeChild(id); attachable->setParentPanel(nullptr); } +#endif - QWriteLocker lock(&_deleteLock); _overlaysToDelete.push_back(overlayToDelete); - emit overlayDeleted(id); } -QString Overlays::getOverlayType(OverlayID overlayId) const { +QString Overlays::getOverlayType(OverlayID overlayId) { + if (QThread::currentThread() != thread()) { + QString result; + hifi::qt::blockingInvokeMethod(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(OverlayID, overlayId)); + return result; + } + Overlay::Pointer overlay = getOverlay(overlayId); if (overlay) { return overlay->getType(); @@ -283,6 +311,12 @@ QString Overlays::getOverlayType(OverlayID overlayId) const { } QObject* Overlays::getOverlayObject(OverlayID id) { + if (QThread::currentThread() != thread()) { + QObject* result; + hifi::qt::blockingInvokeMethod(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id)); + return result; + } + Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { return qobject_cast(&(*thisOverlay)); @@ -290,6 +324,7 @@ QObject* Overlays::getOverlayObject(OverlayID id) { return nullptr; } +#if OVERLAY_PANELS OverlayID Overlays::getParentPanel(OverlayID childId) const { Overlay::Pointer overlay = getOverlay(childId); auto attachable = std::dynamic_pointer_cast(overlay); @@ -330,10 +365,16 @@ void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) { } } } +#endif OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { + if (QThread::currentThread() != thread()) { + OverlayID result; + hifi::qt::blockingInvokeMethod(this, "getOverlayAtPoint", Q_RETURN_ARG(OverlayID, result), Q_ARG(glm::vec2, point)); + return result; + } + glm::vec2 pointCopy = point; - QReadLocker lock(&_lock); if (!_enabled) { return UNKNOWN_OVERLAY_ID; } @@ -365,9 +406,14 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { } OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { + if (QThread::currentThread() != thread()) { + OverlayPropertyResult result; + hifi::qt::blockingInvokeMethod(this, "getProperty", Q_RETURN_ARG(OverlayPropertyResult, result), Q_ARG(OverlayID, id), Q_ARG(QString, property)); + return result; + } + OverlayPropertyResult result; Overlay::Pointer thisOverlay = getOverlay(id); - QReadLocker lock(&_lock); if (thisOverlay && thisOverlay->supportsGetProperty()) { result.value = thisOverlay->getProperty(property); } @@ -405,7 +451,18 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR const QVector& overlaysToInclude, const QVector& overlaysToDiscard, bool visibleOnly, bool collidableOnly) { - QReadLocker lock(&_lock); + if (QThread::currentThread() != thread()) { + RayToOverlayIntersectionResult result; + hifi::qt::blockingInvokeMethod(this, "findRayIntersectionInternal", Q_RETURN_ARG(RayToOverlayIntersectionResult, result), + Q_ARG(PickRay, ray), + Q_ARG(bool, precisionPicking), + Q_ARG(QVector, overlaysToInclude), + Q_ARG(QVector, overlaysToDiscard), + Q_ARG(bool, visibleOnly), + Q_ARG(bool, collidableOnly)); + return result; + } + float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; @@ -448,16 +505,6 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR return result; } -RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() : - intersects(false), - overlayID(UNKNOWN_OVERLAY_ID), - distance(0), - face(), - intersection(), - extraInfo() -{ -} - QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) { auto obj = engine->newObject(); obj.setProperty("intersects", value.intersects); @@ -531,7 +578,12 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar } bool Overlays::isLoaded(OverlayID id) { - QReadLocker lock(&_lock); + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); + return result; + } + Overlay::Pointer thisOverlay = getOverlay(id); if (!thisOverlay) { return false; // not found @@ -539,7 +591,13 @@ bool Overlays::isLoaded(OverlayID id) { return thisOverlay->isLoaded(); } -QSizeF Overlays::textSize(OverlayID id, const QString& text) const { +QSizeF Overlays::textSize(OverlayID id, const QString& text) { + if (QThread::currentThread() != thread()) { + QSizeF result; + hifi::qt::blockingInvokeMethod(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(OverlayID, id), Q_ARG(QString, text)); + return result; + } + Overlay::Pointer thisOverlay = _overlaysHUD[id]; if (thisOverlay) { if (auto textOverlay = std::dynamic_pointer_cast(thisOverlay)) { @@ -554,6 +612,7 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) const { return QSizeF(0.0f, 0.0f); } +#if OVERLAY_PANELS OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) { QWriteLocker lock(&_lock); @@ -607,8 +666,15 @@ void Overlays::deletePanel(OverlayID panelId) { emit panelDeleted(panelId); } +#endif bool Overlays::isAddedOverlay(OverlayID id) { + if (QThread::currentThread() != thread()) { + bool result; + hifi::qt::blockingInvokeMethod(this, "isAddedOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); + return result; + } + return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); } @@ -636,20 +702,43 @@ void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) { emit hoverLeaveOverlay(id, event); } -OverlayID Overlays::getKeyboardFocusOverlay() const { +OverlayID Overlays::getKeyboardFocusOverlay() { + if (QThread::currentThread() != thread()) { + OverlayID result; + hifi::qt::blockingInvokeMethod(this, "getKeyboardFocusOverlay", Q_RETURN_ARG(OverlayID, result)); + return result; + } + return qApp->getKeyboardFocusOverlay(); } void Overlays::setKeyboardFocusOverlay(OverlayID id) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setKeyboardFocusOverlay", Q_ARG(OverlayID, id)); + return; + } + qApp->setKeyboardFocusOverlay(id); } -float Overlays::width() const { +float Overlays::width() { + if (QThread::currentThread() != thread()) { + float result; + hifi::qt::blockingInvokeMethod(this, "width", Q_RETURN_ARG(float, result)); + return result; + } + auto offscreenUi = DependencyManager::get(); return offscreenUi->getWindow()->size().width(); } -float Overlays::height() const { +float Overlays::height() { + if (QThread::currentThread() != thread()) { + float result; + hifi::qt::blockingInvokeMethod(this, "height", Q_RETURN_ARG(float, result)); + return result; + } + auto offscreenUi = DependencyManager::get(); return offscreenUi->getWindow()->size().height(); } @@ -705,7 +794,6 @@ PointerEvent Overlays::calculatePointerEvent(Overlay::Pointer overlay, PickRay r auto thisOverlay = std::dynamic_pointer_cast(overlay); - QReadLocker lock(&_lock); auto position = thisOverlay->getPosition(); auto rotation = thisOverlay->getRotation(); auto dimensions = thisOverlay->getSize(); @@ -854,8 +942,13 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { return false; } -QVector Overlays::findOverlays(const glm::vec3& center, float radius) const { +QVector Overlays::findOverlays(const glm::vec3& center, float radius) { QVector result; + if (QThread::currentThread() != thread()) { + hifi::qt::blockingInvokeMethod(this, "findOverlays", Q_RETURN_ARG(QVector, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius)); + return result; + } + QMapIterator i(_overlaysWorld); int checked = 0; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index a1d4be8376..d3fa70225e 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -25,8 +25,9 @@ #include #include "Overlay.h" -#include "OverlayPanel.h" + #include "PanelAttachable.h" +#include "OverlayPanel.h" class PickRay; @@ -41,6 +42,8 @@ Q_DECLARE_METATYPE(OverlayPropertyResult); QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value); void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value); +const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); + /**jsdoc * @typedef Overlays.RayToOverlayIntersectionResult * @property {bool} intersects True if the PickRay intersected with a 3D overlay. @@ -51,10 +54,9 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPro */ class RayToOverlayIntersectionResult { public: - RayToOverlayIntersectionResult(); - bool intersects; - OverlayID overlayID; - float distance; + bool intersects { false }; + OverlayID overlayID { UNKNOWN_OVERLAY_ID }; + float distance { 0 }; BoxFace face; glm::vec3 surfaceNormal; glm::vec3 intersection; @@ -77,8 +79,6 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R * @namespace Overlays */ -const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); - class Overlays : public QObject { Q_OBJECT @@ -94,11 +94,13 @@ public: void enable(); Overlay::Pointer getOverlay(OverlayID id) const; +#if OVERLAY_PANELS OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; } +#endif /// adds an overlay that's already been created OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } - OverlayID addOverlay(Overlay::Pointer overlay); + OverlayID addOverlay(const Overlay::Pointer& overlay); bool mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); @@ -156,7 +158,7 @@ public slots: * @param {Overlays.OverlayID} overlayID The ID of the overlay to get the type of. * @return {string} The type of the overlay if found, otherwise the empty string. */ - QString getOverlayType(OverlayID overlayId) const; + QString getOverlayType(OverlayID overlayId); /**jsdoc * Get the overlay Script object. @@ -215,7 +217,7 @@ public slots: * @param {float} radius search radius * @return {Overlays.OverlayID[]} list of overlays withing the radius */ - QVector findOverlays(const glm::vec3& center, float radius) const; + QVector findOverlays(const glm::vec3& center, float radius); /**jsdoc * Check whether an overlay's assets have been loaded. For example, if the @@ -237,7 +239,7 @@ public slots: * @param {string} The string to measure. * @return {Vec2} The size of the text. */ - QSizeF textSize(OverlayID id, const QString& text) const; + QSizeF textSize(OverlayID id, const QString& text); /**jsdoc * Get the width of the virtual 2D HUD. @@ -245,7 +247,7 @@ public slots: * @function Overlays.width * @return {float} The width of the 2D HUD. */ - float width() const; + float width(); /**jsdoc * Get the height of the virtual 2D HUD. @@ -253,11 +255,12 @@ public slots: * @function Overlays.height * @return {float} The height of the 2D HUD. */ - float height() const; + float height(); /// return true if there is an overlay with that id else false bool isAddedOverlay(OverlayID id); +#if OVERLAY_PANELS OverlayID getParentPanel(OverlayID childId) const; void setParentPanel(OverlayID childId, OverlayID panelId); @@ -279,6 +282,8 @@ public slots: /// return true if there is a panel with that id else false bool isAddedPanel(OverlayID id) { return _panels.contains(id); } +#endif + void sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event); void sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event); void sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event); @@ -287,7 +292,7 @@ public slots: void sendHoverOverOverlay(OverlayID id, PointerEvent event); void sendHoverLeaveOverlay(OverlayID id, PointerEvent event); - OverlayID getKeyboardFocusOverlay() const; + OverlayID getKeyboardFocusOverlay(); void setKeyboardFocusOverlay(OverlayID id); signals: @@ -316,13 +321,15 @@ private: QMap _overlaysHUD; QMap _overlaysWorld; +#if OVERLAY_PANELS QMap _panels; +#endif QList _overlaysToDelete; unsigned int _stackOrder { 1 }; - QReadWriteLock _lock; - QReadWriteLock _deleteLock; +#if OVERLAY_PANELS QScriptEngine* _scriptEngine; +#endif bool _enabled = true; PointerEvent calculatePointerEvent(Overlay::Pointer overlay, PickRay ray, RayToOverlayIntersectionResult rayPickResult, @@ -331,7 +338,7 @@ private: OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; - RayToOverlayIntersectionResult findRayIntersectionInternal(const PickRay& ray, bool precisionPicking, + Q_INVOKABLE RayToOverlayIntersectionResult findRayIntersectionInternal(const PickRay& ray, bool precisionPicking, const QVector& overlaysToInclude, const QVector& overlaysToDiscard, bool visibleOnly = false, bool collidableOnly = false); diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 7f1c4e2e50..421155083c 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -16,11 +16,15 @@ #include "OverlayPanel.h" bool PanelAttachable::getParentVisible() const { +#if OVERLAY_PANELS if (getParentPanel()) { return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); } else { return true; } +#else + return true; +#endif } QVariant PanelAttachable::getProperty(const QString& property) { @@ -61,11 +65,13 @@ void PanelAttachable::applyTransformTo(Transform& transform, bool force) { if (force || usecTimestampNow() > _transformExpiry) { const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz _transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD; +#if OVERLAY_PANELS if (getParentPanel()) { getParentPanel()->applyTransformTo(transform, true); transform.postTranslate(getOffsetPosition()); transform.postRotate(getOffsetRotation()); transform.postScale(getOffsetScale()); } +#endif } } diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 270addbfcf..4f37cd2258 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -30,6 +30,8 @@ #ifndef hifi_PanelAttachable_h #define hifi_PanelAttachable_h +#define OVERLAY_PANELS 0 + #include #include @@ -39,18 +41,21 @@ #include class OverlayPanel; - class PanelAttachable { public: // getters +#if OVERLAY_PANELS std::shared_ptr getParentPanel() const { return _parentPanel; } +#endif glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); } glm::quat getOffsetRotation() const { return _offset.getRotation(); } glm::vec3 getOffsetScale() const { return _offset.getScale(); } bool getParentVisible() const; // setters +#if OVERLAY_PANELS void setParentPanel(std::shared_ptr panel) { _parentPanel = panel; } +#endif void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); } void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); } void setOffsetScale(float scale) { _offset.setScale(scale); } @@ -66,7 +71,9 @@ protected: quint64 _transformExpiry = 0; private: +#if OVERLAY_PANELS std::shared_ptr _parentPanel = nullptr; +#endif Transform _offset; }; diff --git a/interface/src/ui/overlays/QmlOverlay.cpp b/interface/src/ui/overlays/QmlOverlay.cpp index eb909de993..15e72cf1e3 100644 --- a/interface/src/ui/overlays/QmlOverlay.cpp +++ b/interface/src/ui/overlays/QmlOverlay.cpp @@ -32,21 +32,20 @@ QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay) } void QmlOverlay::buildQmlElement(const QUrl& url) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "buildQmlElement", Q_ARG(QUrl, url)); + return; + } + auto offscreenUi = DependencyManager::get(); - offscreenUi->returnFromUiThread([=] { - offscreenUi->load(url, [=](QQmlContext* context, QObject* object) { - QQuickItem* rawPtr = dynamic_cast(object); - // Create a shared ptr with a custom deleter lambda, that calls deleteLater - _qmlElement = std::shared_ptr(rawPtr, [](QQuickItem* ptr) { - if (ptr) { - ptr->deleteLater(); - } - }); + offscreenUi->load(url, [=](QQmlContext* context, QObject* object) { + QQuickItem* rawPtr = dynamic_cast(object); + // Create a shared ptr with a custom deleter lambda, that calls deleteLater + _qmlElement = std::shared_ptr(rawPtr, [](QQuickItem* ptr) { + if (ptr) { + ptr->deleteLater(); + } }); - while (!_qmlElement) { - qApp->processEvents(); - } - return QVariant(); }); } @@ -55,20 +54,23 @@ QmlOverlay::~QmlOverlay() { } void QmlOverlay::setProperties(const QVariantMap& properties) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setProperties", Q_ARG(QVariantMap, properties)); + return; + } + Overlay2D::setProperties(properties); auto bounds = _bounds; std::weak_ptr weakQmlElement = _qmlElement; - DependencyManager::get()->executeOnUiThread([weakQmlElement, bounds, properties] { - // check to see if qmlElement still exists - auto qmlElement = weakQmlElement.lock(); - if (qmlElement) { - qmlElement->setX(bounds.left()); - qmlElement->setY(bounds.top()); - qmlElement->setWidth(bounds.width()); - qmlElement->setHeight(bounds.height()); - QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties)); - } - }); + // check to see if qmlElement still exists + auto qmlElement = weakQmlElement.lock(); + if (qmlElement) { + qmlElement->setX(bounds.left()); + qmlElement->setY(bounds.top()); + qmlElement->setWidth(bounds.width()); + qmlElement->setHeight(bounds.height()); + QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties)); + } } void QmlOverlay::render(RenderArgs* args) { diff --git a/interface/src/ui/overlays/QmlOverlay.h b/interface/src/ui/overlays/QmlOverlay.h index 736d3884b5..ced2b6fa1f 100644 --- a/interface/src/ui/overlays/QmlOverlay.h +++ b/interface/src/ui/overlays/QmlOverlay.h @@ -32,7 +32,7 @@ public: void render(RenderArgs* args) override; private: - void buildQmlElement(const QUrl& url); + Q_INVOKABLE void buildQmlElement(const QUrl& url); protected: std::shared_ptr _qmlElement; diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 01af69e3ad..c630fe09e4 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -259,10 +259,21 @@ void AudioClient::customDeleter() { void AudioClient::cleanupBeforeQuit() { // FIXME: this should be put in customDeleter, but there is still a reference to this when it is called, // so this must be explicitly, synchronously stopped + static ConditionalGuard guard; + if (QThread::currentThread() != thread()) { + // This will likely be called from the main thread, but we don't want to do blocking queued calls + // from the main thread, so we use a normal auto-connection invoke, and then use a conditional to wait + // for completion + // The effect is the same, yes, but we actually want to avoid the use of Qt::BlockingQueuedConnection + // in the code + QMetaObject::invokeMethod(this, "cleanupBeforeQuit"); + guard.wait(); + return; + } stop(); - _checkDevicesTimer->stop(); + guard.trigger(); } void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) { @@ -1859,7 +1870,7 @@ void AudioClient::startThread() { } void AudioClient::setInputVolume(float volume) { - if (_audioInput && volume != _audioInput->volume()) { + if (_audioInput && volume != (float)_audioInput->volume()) { _audioInput->setVolume(volume); emit inputVolumeChanged(_audioInput->volume()); } diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index 68bb872667..a370d7999b 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "OffscreenUi.h" static const char* const URL_PROPERTY = "source"; @@ -21,39 +22,51 @@ static const char* const SCRIPT_PROPERTY = "scriptUrl"; // Method called by Qt scripts to create a new web window in the overlay QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) { auto properties = parseArguments(context); - QmlWebWindowClass* retVal { nullptr }; auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([&] { - retVal = new QmlWebWindowClass(); - retVal->initQml(properties); - }, true); + QmlWebWindowClass* retVal = new QmlWebWindowClass(); Q_ASSERT(retVal); + if (QThread::currentThread() != qApp->thread()) { + retVal->moveToThread(qApp->thread()); + QMetaObject::invokeMethod(retVal, "initQml", Q_ARG(QVariantMap, properties)); + } else { + retVal->initQml(properties); + } connect(engine, &QScriptEngine::destroyed, retVal, &QmlWindowClass::deleteLater); return engine->newQObject(retVal); } -QString QmlWebWindowClass::getURL() const { - QVariant result = DependencyManager::get()->returnFromUiThread([&]()->QVariant { - if (_qmlWindow.isNull()) { - return QVariant(); - } - return _qmlWindow->property(URL_PROPERTY); - }); - return result.toString(); +QString QmlWebWindowClass::getURL() { + if (QThread::currentThread() != thread()) { + QString result = false; + hifi::qt::blockingInvokeMethod(this, "getURL", Q_RETURN_ARG(QString, result)); + return result; + } + + if (_qmlWindow.isNull()) { + return QString(); + } + + return _qmlWindow->property(URL_PROPERTY).toString(); } void QmlWebWindowClass::setURL(const QString& urlString) { - DependencyManager::get()->executeOnUiThread([=] { - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(URL_PROPERTY, urlString); - } - }); + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setURL", Q_ARG(QString, urlString)); + return; + } + + if (!_qmlWindow.isNull()) { + _qmlWindow->setProperty(URL_PROPERTY, urlString); + } } void QmlWebWindowClass::setScriptURL(const QString& script) { - DependencyManager::get()->executeOnUiThread([=] { - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(SCRIPT_PROPERTY, script); - } - }); + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setScriptURL", Q_ARG(QString, script)); + return; + } + + if (!_qmlWindow.isNull()) { + _qmlWindow->setProperty(SCRIPT_PROPERTY, script); + } } diff --git a/libraries/ui/src/QmlWebWindowClass.h b/libraries/ui/src/QmlWebWindowClass.h index 15ebe74a4f..cdc07265cd 100644 --- a/libraries/ui/src/QmlWebWindowClass.h +++ b/libraries/ui/src/QmlWebWindowClass.h @@ -20,7 +20,7 @@ public: static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine); public slots: - QString getURL() const; + QString getURL(); void setURL(const QString& url); void setScriptURL(const QString& script); diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index f5bb880957..e773ea0c5d 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "OffscreenUi.h" static const char* const SOURCE_PROPERTY = "source"; @@ -73,13 +74,15 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) { // Method called by Qt scripts to create a new web window in the overlay QScriptValue QmlWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) { auto properties = parseArguments(context); - QmlWindowClass* retVal { nullptr }; auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([&] { - retVal = new QmlWindowClass(); - retVal->initQml(properties); - }, true); + QmlWindowClass* retVal = new QmlWindowClass(); Q_ASSERT(retVal); + if (QThread::currentThread() != qApp->thread()) { + retVal->moveToThread(qApp->thread()); + hifi::qt::blockingInvokeMethod(retVal, "initQml", Q_ARG(QVariantMap, properties)); + } else { + retVal->initQml(properties); + } connect(engine, &QScriptEngine::destroyed, retVal, &QmlWindowClass::deleteLater); return engine->newQObject(retVal); } @@ -214,49 +217,64 @@ QQuickItem* QmlWindowClass::asQuickItem() const { } void QmlWindowClass::setVisible(bool visible) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setVisible", Q_ARG(bool, visible)); + return; + } + QQuickItem* targetWindow = asQuickItem(); if (_toolWindow) { // For tool window tabs we special case visibility as a function call on the tab parent // The tool window itself has special logic based on whether any tabs are visible QMetaObject::invokeMethod(targetWindow, "showTabForUrl", Qt::QueuedConnection, Q_ARG(QVariant, _source), Q_ARG(QVariant, visible)); } else { - DependencyManager::get()->executeOnUiThread([=] { - targetWindow->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible); - }); + targetWindow->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible); } } -bool QmlWindowClass::isVisible() const { +bool QmlWindowClass::isVisible() { + if (QThread::currentThread() != thread()) { + bool result = false; + hifi::qt::blockingInvokeMethod(this, "isVisible", Q_RETURN_ARG(bool, result)); + return result; + } + // The tool window itself has special logic based on whether any tabs are enabled - return DependencyManager::get()->returnFromUiThread([&] { - if (_qmlWindow.isNull()) { - return QVariant::fromValue(false); - } - if (_toolWindow) { - return QVariant::fromValue(dynamic_cast(_qmlWindow.data())->isEnabled()); - } else { - return QVariant::fromValue(asQuickItem()->isVisible()); - } - }).toBool(); + if (_qmlWindow.isNull()) { + return false; + } + + if (_toolWindow) { + return dynamic_cast(_qmlWindow.data())->isEnabled(); + } + + return asQuickItem()->isVisible(); } -glm::vec2 QmlWindowClass::getPosition() const { - QVariant result = DependencyManager::get()->returnFromUiThread([&]()->QVariant { - if (_qmlWindow.isNull()) { - return QVariant(QPointF(0, 0)); - } - return asQuickItem()->position(); - }); - return toGlm(result.toPointF()); +glm::vec2 QmlWindowClass::getPosition() { + if (QThread::currentThread() != thread()) { + vec2 result; + hifi::qt::blockingInvokeMethod(this, "getPosition", Q_RETURN_ARG(vec2, result)); + return result; + } + + if (_qmlWindow.isNull()) { + return {}; + } + + return toGlm(asQuickItem()->position()); } void QmlWindowClass::setPosition(const glm::vec2& position) { - DependencyManager::get()->executeOnUiThread([=] { - if (!_qmlWindow.isNull()) { - asQuickItem()->setPosition(QPointF(position.x, position.y)); - } - }); + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setPosition", Q_ARG(vec2, position)); + return; + } + + if (!_qmlWindow.isNull()) { + asQuickItem()->setPosition(QPointF(position.x, position.y)); + } } void QmlWindowClass::setPosition(int x, int y) { @@ -268,23 +286,29 @@ glm::vec2 toGlm(const QSizeF& size) { return glm::vec2(size.width(), size.height()); } -glm::vec2 QmlWindowClass::getSize() const { - QVariant result = DependencyManager::get()->returnFromUiThread([&]()->QVariant { - if (_qmlWindow.isNull()) { - return QVariant(QSizeF(0, 0)); - } - QQuickItem* targetWindow = asQuickItem(); - return QSizeF(targetWindow->width(), targetWindow->height()); - }); - return toGlm(result.toSizeF()); +glm::vec2 QmlWindowClass::getSize() { + if (QThread::currentThread() != thread()) { + vec2 result; + hifi::qt::blockingInvokeMethod(this, "getSize", Q_RETURN_ARG(vec2, result)); + return result; + } + + if (_qmlWindow.isNull()) { + return {}; + } + QQuickItem* targetWindow = asQuickItem(); + return vec2(targetWindow->width(), targetWindow->height()); } void QmlWindowClass::setSize(const glm::vec2& size) { - DependencyManager::get()->executeOnUiThread([=] { - if (!_qmlWindow.isNull()) { - asQuickItem()->setSize(QSizeF(size.x, size.y)); - } - }); + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setSize", Q_ARG(vec2, size)); + return; + } + + if (!_qmlWindow.isNull()) { + asQuickItem()->setSize(QSizeF(size.x, size.y)); + } } void QmlWindowClass::setSize(int width, int height) { @@ -292,28 +316,33 @@ void QmlWindowClass::setSize(int width, int height) { } void QmlWindowClass::setTitle(const QString& title) { - DependencyManager::get()->executeOnUiThread([=] { - if (!_qmlWindow.isNull()) { - asQuickItem()->setProperty(TITLE_PROPERTY, title); - } - }); + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setTitle", Q_ARG(QString, title)); + return; + } + + if (!_qmlWindow.isNull()) { + asQuickItem()->setProperty(TITLE_PROPERTY, title); + } } void QmlWindowClass::close() { - if (_qmlWindow) { - if (_toolWindow) { - auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([=] { - auto toolWindow = offscreenUi->getToolWindow(); - auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::DirectConnection, - Q_ARG(QVariant, _source)); - Q_ASSERT(invokeResult); - }); - } else { - _qmlWindow->deleteLater(); - } - _qmlWindow = nullptr; + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "close"); + return; } + + if (_toolWindow) { + auto offscreenUi = DependencyManager::get(); + auto toolWindow = offscreenUi->getToolWindow(); + auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::DirectConnection, + Q_ARG(QVariant, _source)); + Q_ASSERT(invokeResult); + return; + } else if (_qmlWindow) { + _qmlWindow->deleteLater(); + } + _qmlWindow = nullptr; } void QmlWindowClass::hasMoved(QVector2D position) { @@ -325,10 +354,13 @@ void QmlWindowClass::hasClosed() { } void QmlWindowClass::raise() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "raise"); + return; + } + auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([=] { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(asQuickItem(), "raise", Qt::DirectConnection); - } - }); + if (_qmlWindow) { + QMetaObject::invokeMethod(asQuickItem(), "raise", Qt::DirectConnection); + } } diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index 4f604133a5..d3e1912d45 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -31,18 +31,18 @@ public: QmlWindowClass(); ~QmlWindowClass(); - virtual void initQml(QVariantMap properties); + Q_INVOKABLE virtual void initQml(QVariantMap properties); QQuickItem* asQuickItem() const; public slots: - bool isVisible() const; + bool isVisible(); void setVisible(bool visible); - glm::vec2 getPosition() const; + glm::vec2 getPosition(); void setPosition(const glm::vec2& position); void setPosition(int x, int y); - glm::vec2 getSize() const; + glm::vec2 getSize(); void setSize(const glm::vec2& size); void setSize(int width, int height); void setTitle(const QString& title); diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 573d873bab..19cd37a6cb 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -887,28 +887,6 @@ QQmlContext* OffscreenQmlSurface::getSurfaceContext() { return _qmlContext; } -void OffscreenQmlSurface::executeOnUiThread(std::function function, bool blocking ) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, - Q_ARG(std::function, function)); - return; - } - - function(); -} - -QVariant OffscreenQmlSurface::returnFromUiThread(std::function function) { - if (QThread::currentThread() != thread()) { - QVariant result; - hifi::qt::blockingInvokeMethod(this, "returnFromUiThread", - Q_RETURN_ARG(QVariant, result), - Q_ARG(std::function, function)); - return result; - } - - return function(); -} - void OffscreenQmlSurface::focusDestroyed(QObject *obj) { _currentFocusItem = nullptr; } diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index ae81ae48b4..54f27e3b1f 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -55,10 +55,6 @@ public: return load(QUrl(qmlSourceFile), f); } void clearCache(); - - Q_INVOKABLE void executeOnUiThread(std::function function, bool blocking = false); - Q_INVOKABLE QVariant returnFromUiThread(std::function function); - void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; } // Optional values for event handling void setProxyWindow(QWindow* window); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index ade8c73df5..0dbcfac25c 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -214,20 +214,18 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { // create new desktop window auto offscreenUi = DependencyManager::get(); - offscreenUi->executeOnUiThread([=] { - auto tabletRootWindow = new TabletRootWindow(); - tabletRootWindow->initQml(QVariantMap()); - auto quickItem = tabletRootWindow->asQuickItem(); - _desktopWindow = tabletRootWindow; - QMetaObject::invokeMethod(quickItem, "setShown", Q_ARG(const QVariant&, QVariant(false))); + auto tabletRootWindow = new TabletRootWindow(); + tabletRootWindow->initQml(QVariantMap()); + auto quickItem = tabletRootWindow->asQuickItem(); + _desktopWindow = tabletRootWindow; + QMetaObject::invokeMethod(quickItem, "setShown", Q_ARG(const QVariant&, QVariant(false))); - QObject::connect(quickItem, SIGNAL(windowClosed()), this, SLOT(desktopWindowClosed())); + QObject::connect(quickItem, SIGNAL(windowClosed()), this, SLOT(desktopWindowClosed())); - QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection); + QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection); - // forward qml surface events to interface js - connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); - }); + // forward qml surface events to interface js + connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); } else { _state = State::Home; removeButtonsFromToolbar(); From 9c37b28ba0b96430ec7f14019da18363ed4ccda6 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 30 Jun 2017 10:40:17 -0700 Subject: [PATCH 11/24] Remove tool window logic --- libraries/ui/src/QmlWebWindowClass.cpp | 2 +- libraries/ui/src/QmlWindowClass.cpp | 26 ++++++++++++++++++++------ libraries/ui/src/QmlWindowClass.h | 5 +++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index a370d7999b..13fc9cc018 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -37,7 +37,7 @@ QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngi QString QmlWebWindowClass::getURL() { if (QThread::currentThread() != thread()) { - QString result = false; + QString result; hifi::qt::blockingInvokeMethod(this, "getURL", Q_RETURN_ARG(QString, result)); return result; } diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index e773ea0c5d..8d93af15f5 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -93,9 +93,10 @@ QmlWindowClass::QmlWindowClass() { void QmlWindowClass::initQml(QVariantMap properties) { auto offscreenUi = DependencyManager::get(); - _toolWindow = properties.contains(TOOLWINDOW_PROPERTY) && properties[TOOLWINDOW_PROPERTY].toBool(); _source = properties[SOURCE_PROPERTY].toString(); +#if QML_TOOL_WINDOW + _toolWindow = properties.contains(TOOLWINDOW_PROPERTY) && properties[TOOLWINDOW_PROPERTY].toBool(); if (_toolWindow) { // Build the event bridge and wrapper on the main thread _qmlWindow = offscreenUi->getToolWindow(); @@ -106,6 +107,7 @@ void QmlWindowClass::initQml(QVariantMap properties) { Q_ARG(QVariant, QVariant::fromValue(properties))); Q_ASSERT(invokeResult); } else { +#endif // Build the event bridge and wrapper on the main thread offscreenUi->loadInNewContext(qmlSource(), [&](QQmlContext* context, QObject* object) { _qmlWindow = object; @@ -136,7 +138,9 @@ void QmlWindowClass::initQml(QVariantMap properties) { connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection); connect(_qmlWindow, SIGNAL(windowClosed()), this, SLOT(hasClosed()), Qt::QueuedConnection); }); +#if QML_TOOL_WINDOW } +#endif Q_ASSERT(_qmlWindow); Q_ASSERT(dynamic_cast(_qmlWindow.data())); } @@ -210,9 +214,11 @@ QmlWindowClass::~QmlWindowClass() { } QQuickItem* QmlWindowClass::asQuickItem() const { +#if QML_TOOL_WINDOW if (_toolWindow) { return DependencyManager::get()->getToolWindow(); } +#endif return _qmlWindow.isNull() ? nullptr : dynamic_cast(_qmlWindow.data()); } @@ -223,13 +229,15 @@ void QmlWindowClass::setVisible(bool visible) { } QQuickItem* targetWindow = asQuickItem(); +#if QML_TOOL_WINDOW if (_toolWindow) { // For tool window tabs we special case visibility as a function call on the tab parent // The tool window itself has special logic based on whether any tabs are visible QMetaObject::invokeMethod(targetWindow, "showTabForUrl", Qt::QueuedConnection, Q_ARG(QVariant, _source), Q_ARG(QVariant, visible)); - } else { - targetWindow->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible); - } + return; + } +#endif + targetWindow->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible); } bool QmlWindowClass::isVisible() { @@ -244,10 +252,12 @@ bool QmlWindowClass::isVisible() { return false; } +#if QML_TOOL_WINDOW if (_toolWindow) { return dynamic_cast(_qmlWindow.data())->isEnabled(); } - +#endif + return asQuickItem()->isVisible(); } @@ -332,6 +342,7 @@ void QmlWindowClass::close() { return; } +#if QML_TOOL_WINDOW if (_toolWindow) { auto offscreenUi = DependencyManager::get(); auto toolWindow = offscreenUi->getToolWindow(); @@ -339,7 +350,10 @@ void QmlWindowClass::close() { Q_ARG(QVariant, _source)); Q_ASSERT(invokeResult); return; - } else if (_qmlWindow) { + } +#endif + + if (_qmlWindow) { _qmlWindow->deleteLater(); } _qmlWindow = nullptr; diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index d3e1912d45..e01bc8f14b 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -19,6 +19,8 @@ class QScriptEngine; class QScriptContext; +#define QML_TOOL_WINDOW 0 + // FIXME refactor this class to be a QQuickItem derived type and eliminate the needless wrapping class QmlWindowClass : public QObject { Q_OBJECT @@ -85,9 +87,12 @@ protected: virtual QString qmlSource() const { return "QmlWindow.qml"; } +#if QML_TOOL_WINDOW // FIXME needs to be initialized in the ctor once we have support // for tool window panes in QML bool _toolWindow { false }; +#endif + QPointer _qmlWindow; QString _source; From 6fc82bb351626d901aa060009dafc67d25c15683 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 30 Jun 2017 11:34:54 -0700 Subject: [PATCH 12/24] Switch to preprocessor macro for blocking invokes to capture function information --- assignment-client/src/AssignmentClient.cpp | 2 +- .../src/avatars/ScriptableAvatar.cpp | 2 +- interface/src/Application.cpp | 2 +- interface/src/avatar/AvatarManager.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 8 ++--- .../scripting/ClipboardScriptingInterface.cpp | 8 ++--- .../src/scripting/HMDScriptingInterface.cpp | 4 +-- .../src/scripting/MenuScriptingInterface.cpp | 10 +++--- .../src/scripting/TestScriptingInterface.cpp | 2 +- .../scripting/WindowScriptingInterface.cpp | 2 +- interface/src/ui/JSConsole.cpp | 2 +- interface/src/ui/overlays/Overlays.cpp | 32 +++++++++---------- libraries/animation/src/AnimationCache.cpp | 6 ++-- libraries/audio/src/SoundCache.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 10 +++--- libraries/avatars/src/AvatarData.cpp | 26 +++++++-------- .../src/display-plugins/CompositorHelper.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 4 +-- .../entities/src/EntityScriptingInterface.cpp | 4 +-- libraries/networking/src/NodeList.cpp | 2 +- libraries/networking/src/ResourceCache.cpp | 4 +-- libraries/networking/src/udt/Socket.cpp | 2 +- .../src/plugins/InputConfiguration.cpp | 14 ++++---- .../recording/src/recording/ClipCache.cpp | 2 +- libraries/render-utils/src/Model.cpp | 2 +- libraries/render/src/task/Config.cpp | 2 +- .../src/AudioScriptingInterface.cpp | 2 +- .../src/RecordingScriptingInterface.cpp | 16 +++++----- libraries/script-engine/src/ScriptEngine.cpp | 2 +- libraries/script-engine/src/ScriptEngines.cpp | 2 +- libraries/shared/src/shared/QtHelpers.cpp | 7 ++-- libraries/shared/src/shared/QtHelpers.h | 5 +++ libraries/ui/src/OffscreenUi.cpp | 14 ++++---- libraries/ui/src/QmlWebWindowClass.cpp | 2 +- libraries/ui/src/QmlWindowClass.cpp | 10 +++--- libraries/ui/src/ui/Menu.cpp | 2 +- libraries/ui/src/ui/QmlWrapper.cpp | 4 +-- .../ui/src/ui/TabletScriptingInterface.cpp | 14 ++++---- .../ui/src/ui/ToolbarScriptingInterface.cpp | 4 +-- 39 files changed, 124 insertions(+), 118 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 2db1fba952..efced972a0 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -142,7 +142,7 @@ void AssignmentClient::stopAssignmentClient() { QThread* currentAssignmentThread = _currentAssignment->thread(); // ask the current assignment to stop - hifi::qt::blockingInvokeMethod(_currentAssignment, "stop"); + BLOCKING_INVOKE_METHOD(_currentAssignment, "stop"); // ask the current assignment to delete itself on its thread _currentAssignment->deleteLater(); diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 4e2836119e..6443e7bf4b 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -50,7 +50,7 @@ void ScriptableAvatar::stopAnimation() { AnimationDetails ScriptableAvatar::getAnimationDetails() { if (QThread::currentThread() != thread()) { AnimationDetails result; - hifi::qt::blockingInvokeMethod(this, "getAnimationDetails", + BLOCKING_INVOKE_METHOD(this, "getAnimationDetails", Q_RETURN_ARG(AnimationDetails, result)); return result; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2b6c6033a2..d5b6f06d45 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1656,7 +1656,7 @@ QString Application::getUserAgent() { if (QThread::currentThread() != thread()) { QString userAgent; - hifi::qt::blockingInvokeMethod(this, "getUserAgent", Q_RETURN_ARG(QString, userAgent)); + BLOCKING_INVOKE_METHOD(this, "getUserAgent", Q_RETURN_ARG(QString, userAgent)); return userAgent; } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index abdcd48b42..c46d61cf68 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -483,7 +483,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& const QScriptValue& avatarIdsToDiscard) { RayToAvatarIntersectionResult result; if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(const_cast(this), "findRayIntersection", + BLOCKING_INVOKE_METHOD(const_cast(this), "findRayIntersection", Q_RETURN_ARG(RayToAvatarIntersectionResult, result), Q_ARG(const PickRay&, ray), Q_ARG(const QScriptValue&, avatarIdsToInclude), diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 404f8681f2..230ea7616a 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -898,7 +898,7 @@ void MyAvatar::restoreAnimation() { QStringList MyAvatar::getAnimationRoles() { if (QThread::currentThread() != thread()) { QStringList result; - hifi::qt::blockingInvokeMethod(this, "getAnimationRoles", Q_RETURN_ARG(QStringList, result)); + BLOCKING_INVOKE_METHOD(this, "getAnimationRoles", Q_RETURN_ARG(QStringList, result)); return result; } return _skeletonModel->getRig().getAnimationRoles(); @@ -1369,7 +1369,7 @@ void MyAvatar::resetFullAvatarURL() { void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "useFullAvatarURL", + BLOCKING_INVOKE_METHOD(this, "useFullAvatarURL", Q_ARG(const QUrl&, fullAvatarURL), Q_ARG(const QString&, modelName)); return; @@ -1395,7 +1395,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN void MyAvatar::setAttachmentData(const QVector& attachmentData) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "setAttachmentData", + BLOCKING_INVOKE_METHOD(this, "setAttachmentData", Q_ARG(const QVector, attachmentData)); return; } @@ -2359,7 +2359,7 @@ bool MyAvatar::safeLanding(const glm::vec3& position) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "safeLanding", Q_RETURN_ARG(bool, result), Q_ARG(const glm::vec3&, position)); + BLOCKING_INVOKE_METHOD(this, "safeLanding", Q_RETURN_ARG(bool, result), Q_ARG(const glm::vec3&, position)); return result; } glm::vec3 better; diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index b443ba1ef0..f8db061299 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -27,7 +27,7 @@ float ClipboardScriptingInterface::getClipboardContentsLargestDimension() { bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector& entityIDs) { bool retVal; - hifi::qt::blockingInvokeMethod(qApp, "exportEntities", + BLOCKING_INVOKE_METHOD(qApp, "exportEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename), Q_ARG(const QVector&, entityIDs)); @@ -36,7 +36,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, const bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) { bool retVal; - hifi::qt::blockingInvokeMethod(qApp, "exportEntities", + BLOCKING_INVOKE_METHOD(qApp, "exportEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename), Q_ARG(float, x), @@ -48,7 +48,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, float bool ClipboardScriptingInterface::importEntities(const QString& filename) { bool retVal; - hifi::qt::blockingInvokeMethod(qApp, "importEntities", + BLOCKING_INVOKE_METHOD(qApp, "importEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename)); return retVal; @@ -56,7 +56,7 @@ bool ClipboardScriptingInterface::importEntities(const QString& filename) { QVector ClipboardScriptingInterface::pasteEntities(glm::vec3 position) { QVector retVal; - hifi::qt::blockingInvokeMethod(qApp, "pasteEntities", + BLOCKING_INVOKE_METHOD(qApp, "pasteEntities", Q_RETURN_ARG(QVector, retVal), Q_ARG(float, position.x), Q_ARG(float, position.y), diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 81a806b8ab..35f2e2aa86 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -156,7 +156,7 @@ QString HMDScriptingInterface::preferredAudioOutput() const { bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "setHandLasers", Q_RETURN_ARG(bool, result), + BLOCKING_INVOKE_METHOD(this, "setHandLasers", Q_RETURN_ARG(bool, result), Q_ARG(int, hands), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); return result; } @@ -171,7 +171,7 @@ bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::ve bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "setExtraLaser", Q_RETURN_ARG(bool, result), + BLOCKING_INVOKE_METHOD(this, "setExtraLaser", Q_RETURN_ARG(bool, result), Q_ARG(glm::vec3, worldStart), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); return result; } diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index b3829ecb3b..d9372978e8 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -44,7 +44,7 @@ bool MenuScriptingInterface::menuExists(const QString& menu) { return Menu::getInstance()->menuExists(menu); } bool result; - hifi::qt::blockingInvokeMethod(Menu::getInstance(), "menuExists", + BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuExists", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menu)); return result; @@ -87,7 +87,7 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& return Menu::getInstance()->menuItemExists(menu, menuitem); } bool result; - hifi::qt::blockingInvokeMethod(Menu::getInstance(), "menuItemExists", + BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuItemExists", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menu), Q_ARG(const QString&, menuitem)); @@ -115,7 +115,7 @@ bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) { return Menu::getInstance()->isOptionChecked(menuOption); } bool result; - hifi::qt::blockingInvokeMethod(Menu::getInstance(), "isOptionChecked", + BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isOptionChecked", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menuOption)); return result; @@ -132,7 +132,7 @@ bool MenuScriptingInterface::isMenuEnabled(const QString& menuOption) { return Menu::getInstance()->isOptionChecked(menuOption); } bool result; - hifi::qt::blockingInvokeMethod(Menu::getInstance(), "isMenuEnabled", + BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isMenuEnabled", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, menuOption)); return result; @@ -158,7 +158,7 @@ bool MenuScriptingInterface::isInfoViewVisible(const QString& path) { } bool result; - hifi::qt::blockingInvokeMethod(Menu::getInstance(), "isInfoViewVisible", + BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isInfoViewVisible", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, path)); return result; } diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index 4d3e3b94a1..d4b4ba1480 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -60,7 +60,7 @@ void TestScriptingInterface::waitIdle() { bool TestScriptingInterface::loadTestScene(QString scene) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "loadTestScene", Q_RETURN_ARG(bool, result), Q_ARG(QString, scene)); + BLOCKING_INVOKE_METHOD(this, "loadTestScene", Q_RETURN_ARG(bool, result), Q_ARG(QString, scene)); return result; } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index a5d8544658..84f4cbbbd8 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -317,7 +317,7 @@ bool WindowScriptingInterface::isPhysicsEnabled() { int WindowScriptingInterface::openMessageBox(QString title, QString text, int buttons, int defaultButton) { if (QThread::currentThread() != thread()) { int result; - hifi::qt::blockingInvokeMethod(this, "openMessageBox", + BLOCKING_INVOKE_METHOD(this, "openMessageBox", Q_RETURN_ARG(int, result), Q_ARG(QString, title), Q_ARG(QString, text), diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 4b03d1b575..443f11fb23 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -116,7 +116,7 @@ void JSConsole::executeCommand(const QString& command) { QScriptValue JSConsole::executeCommandInWatcher(const QString& command) { QScriptValue result; - hifi::qt::blockingInvokeMethod(_scriptEngine, "evaluate", + BLOCKING_INVOKE_METHOD(_scriptEngine, "evaluate", Q_RETURN_ARG(QScriptValue, result), Q_ARG(const QString&, command), Q_ARG(const QString&, _consoleFileName)); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c27800a5bb..0c73f1fa70 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -145,7 +145,7 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const { OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) { if (QThread::currentThread() != thread()) { OverlayID result; - hifi::qt::blockingInvokeMethod(this, "addOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(QString, type), Q_ARG(QVariant, properties)); + BLOCKING_INVOKE_METHOD(this, "addOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(QString, type), Q_ARG(QVariant, properties)); return result; } @@ -209,7 +209,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { OverlayID Overlays::cloneOverlay(OverlayID id) { if (QThread::currentThread() != thread()) { OverlayID result; - hifi::qt::blockingInvokeMethod(this, "cloneOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(OverlayID, id)); + BLOCKING_INVOKE_METHOD(this, "cloneOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(OverlayID, id)); return result; } @@ -232,7 +232,7 @@ OverlayID Overlays::cloneOverlay(OverlayID id) { bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "editOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id), Q_ARG(QVariant, properties)); + BLOCKING_INVOKE_METHOD(this, "editOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id), Q_ARG(QVariant, properties)); return result; } @@ -247,7 +247,7 @@ bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { bool Overlays::editOverlays(const QVariant& propertiesById) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "editOverlays", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, propertiesById)); + BLOCKING_INVOKE_METHOD(this, "editOverlays", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, propertiesById)); return result; } @@ -299,7 +299,7 @@ void Overlays::deleteOverlay(OverlayID id) { QString Overlays::getOverlayType(OverlayID overlayId) { if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(OverlayID, overlayId)); + BLOCKING_INVOKE_METHOD(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(OverlayID, overlayId)); return result; } @@ -313,7 +313,7 @@ QString Overlays::getOverlayType(OverlayID overlayId) { QObject* Overlays::getOverlayObject(OverlayID id) { if (QThread::currentThread() != thread()) { QObject* result; - hifi::qt::blockingInvokeMethod(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id)); + BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id)); return result; } @@ -370,7 +370,7 @@ void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) { OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { if (QThread::currentThread() != thread()) { OverlayID result; - hifi::qt::blockingInvokeMethod(this, "getOverlayAtPoint", Q_RETURN_ARG(OverlayID, result), Q_ARG(glm::vec2, point)); + BLOCKING_INVOKE_METHOD(this, "getOverlayAtPoint", Q_RETURN_ARG(OverlayID, result), Q_ARG(glm::vec2, point)); return result; } @@ -408,7 +408,7 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { if (QThread::currentThread() != thread()) { OverlayPropertyResult result; - hifi::qt::blockingInvokeMethod(this, "getProperty", Q_RETURN_ARG(OverlayPropertyResult, result), Q_ARG(OverlayID, id), Q_ARG(QString, property)); + BLOCKING_INVOKE_METHOD(this, "getProperty", Q_RETURN_ARG(OverlayPropertyResult, result), Q_ARG(OverlayID, id), Q_ARG(QString, property)); return result; } @@ -453,7 +453,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR bool visibleOnly, bool collidableOnly) { if (QThread::currentThread() != thread()) { RayToOverlayIntersectionResult result; - hifi::qt::blockingInvokeMethod(this, "findRayIntersectionInternal", Q_RETURN_ARG(RayToOverlayIntersectionResult, result), + BLOCKING_INVOKE_METHOD(this, "findRayIntersectionInternal", Q_RETURN_ARG(RayToOverlayIntersectionResult, result), Q_ARG(PickRay, ray), Q_ARG(bool, precisionPicking), Q_ARG(QVector, overlaysToInclude), @@ -580,7 +580,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar bool Overlays::isLoaded(OverlayID id) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); + BLOCKING_INVOKE_METHOD(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); return result; } @@ -594,7 +594,7 @@ bool Overlays::isLoaded(OverlayID id) { QSizeF Overlays::textSize(OverlayID id, const QString& text) { if (QThread::currentThread() != thread()) { QSizeF result; - hifi::qt::blockingInvokeMethod(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(OverlayID, id), Q_ARG(QString, text)); + BLOCKING_INVOKE_METHOD(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(OverlayID, id), Q_ARG(QString, text)); return result; } @@ -671,7 +671,7 @@ void Overlays::deletePanel(OverlayID panelId) { bool Overlays::isAddedOverlay(OverlayID id) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "isAddedOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); + BLOCKING_INVOKE_METHOD(this, "isAddedOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); return result; } @@ -705,7 +705,7 @@ void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) { OverlayID Overlays::getKeyboardFocusOverlay() { if (QThread::currentThread() != thread()) { OverlayID result; - hifi::qt::blockingInvokeMethod(this, "getKeyboardFocusOverlay", Q_RETURN_ARG(OverlayID, result)); + BLOCKING_INVOKE_METHOD(this, "getKeyboardFocusOverlay", Q_RETURN_ARG(OverlayID, result)); return result; } @@ -724,7 +724,7 @@ void Overlays::setKeyboardFocusOverlay(OverlayID id) { float Overlays::width() { if (QThread::currentThread() != thread()) { float result; - hifi::qt::blockingInvokeMethod(this, "width", Q_RETURN_ARG(float, result)); + BLOCKING_INVOKE_METHOD(this, "width", Q_RETURN_ARG(float, result)); return result; } @@ -735,7 +735,7 @@ float Overlays::width() { float Overlays::height() { if (QThread::currentThread() != thread()) { float result; - hifi::qt::blockingInvokeMethod(this, "height", Q_RETURN_ARG(float, result)); + BLOCKING_INVOKE_METHOD(this, "height", Q_RETURN_ARG(float, result)); return result; } @@ -945,7 +945,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { QVector Overlays::findOverlays(const glm::vec3& center, float radius) { QVector result; if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "findOverlays", Q_RETURN_ARG(QVector, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius)); + BLOCKING_INVOKE_METHOD(this, "findOverlays", Q_RETURN_ARG(QVector, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius)); return result; } diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 0bca721464..9aa315beb8 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -34,7 +34,7 @@ AnimationCache::AnimationCache(QObject* parent) : AnimationPointer AnimationCache::getAnimation(const QUrl& url) { if (QThread::currentThread() != thread()) { AnimationPointer result; - hifi::qt::blockingInvokeMethod(this, "getAnimation", + BLOCKING_INVOKE_METHOD(this, "getAnimation", Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url)); return result; } @@ -100,7 +100,7 @@ bool Animation::isLoaded() const { QStringList Animation::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointNames", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointNames", Q_RETURN_ARG(QStringList, result)); return result; } @@ -114,7 +114,7 @@ QStringList Animation::getJointNames() const { QVector Animation::getFrames() const { if (QThread::currentThread() != thread()) { QVector result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getFrames", + BLOCKING_INVOKE_METHOD(const_cast(this), "getFrames", Q_RETURN_ARG(QVector, result)); return result; } diff --git a/libraries/audio/src/SoundCache.cpp b/libraries/audio/src/SoundCache.cpp index dc20b9884d..162e833da2 100644 --- a/libraries/audio/src/SoundCache.cpp +++ b/libraries/audio/src/SoundCache.cpp @@ -32,7 +32,7 @@ SoundCache::SoundCache(QObject* parent) : SharedSoundPointer SoundCache::getSound(const QUrl& url) { if (QThread::currentThread() != thread()) { SharedSoundPointer result; - hifi::qt::blockingInvokeMethod(this, "getSound", + BLOCKING_INVOKE_METHOD(this, "getSound", Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url)); return result; } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index faebeafb29..d303b2e66d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1011,7 +1011,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { int Avatar::getJointIndex(const QString& name) const { if (QThread::currentThread() != thread()) { int result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointIndex", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointIndex", Q_RETURN_ARG(int, result), Q_ARG(const QString&, name)); return result; } @@ -1025,7 +1025,7 @@ int Avatar::getJointIndex(const QString& name) const { QStringList Avatar::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointNames", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointNames", Q_RETURN_ARG(QStringList, result)); return result; } @@ -1035,7 +1035,7 @@ QStringList Avatar::getJointNames() const { glm::vec3 Avatar::getJointPosition(int index) const { if (QThread::currentThread() != thread()) { glm::vec3 position; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointPosition", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointPosition", Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index)); return position; } @@ -1047,7 +1047,7 @@ glm::vec3 Avatar::getJointPosition(int index) const { glm::vec3 Avatar::getJointPosition(const QString& name) const { if (QThread::currentThread() != thread()) { glm::vec3 position; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointPosition", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointPosition", Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name)); return position; } @@ -1106,7 +1106,7 @@ static std::shared_ptr allocateAttachmentModel(bool isSoft, const Rig& ri void Avatar::setAttachmentData(const QVector& attachmentData) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "setAttachmentData", + BLOCKING_INVOKE_METHOD(this, "setAttachmentData", Q_ARG(const QVector, attachmentData)); return; } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5f63826a99..6eed23fb5b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1228,7 +1228,7 @@ bool AvatarData::isJointDataValid(int index) const { } if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(const_cast(this), "isJointDataValid", + BLOCKING_INVOKE_METHOD(const_cast(this), "isJointDataValid", Q_RETURN_ARG(bool, result), Q_ARG(int, index)); return result; } @@ -1241,7 +1241,7 @@ glm::quat AvatarData::getJointRotation(int index) const { } if (QThread::currentThread() != thread()) { glm::quat result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointRotation", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointRotation", Q_RETURN_ARG(glm::quat, result), Q_ARG(int, index)); return result; } @@ -1256,7 +1256,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const { } if (QThread::currentThread() != thread()) { glm::vec3 result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointTranslation", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointTranslation", Q_RETURN_ARG(glm::vec3, result), Q_ARG(int, index)); return result; } @@ -1267,7 +1267,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const { glm::vec3 AvatarData::getJointTranslation(const QString& name) const { if (QThread::currentThread() != thread()) { glm::vec3 result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointTranslation", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointTranslation", Q_RETURN_ARG(glm::vec3, result), Q_ARG(const QString&, name)); return result; } @@ -1345,7 +1345,7 @@ void AvatarData::clearJointData(const QString& name) { bool AvatarData::isJointDataValid(const QString& name) const { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(const_cast(this), "isJointDataValid", + BLOCKING_INVOKE_METHOD(const_cast(this), "isJointDataValid", Q_RETURN_ARG(bool, result), Q_ARG(const QString&, name)); return result; } @@ -1355,7 +1355,7 @@ bool AvatarData::isJointDataValid(const QString& name) const { glm::quat AvatarData::getJointRotation(const QString& name) const { if (QThread::currentThread() != thread()) { glm::quat result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointRotation", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointRotation", Q_RETURN_ARG(glm::quat, result), Q_ARG(const QString&, name)); return result; } @@ -1365,7 +1365,7 @@ glm::quat AvatarData::getJointRotation(const QString& name) const { QVector AvatarData::getJointRotations() const { if (QThread::currentThread() != thread()) { QVector result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointRotations", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointRotations", Q_RETURN_ARG(QVector, result)); return result; } @@ -1380,7 +1380,7 @@ QVector AvatarData::getJointRotations() const { void AvatarData::setJointRotations(QVector jointRotations) { if (QThread::currentThread() != thread()) { QVector result; - hifi::qt::blockingInvokeMethod(const_cast(this), "setJointRotations", + BLOCKING_INVOKE_METHOD(const_cast(this), "setJointRotations", Q_ARG(QVector, jointRotations)); } QWriteLocker writeLock(&_jointDataLock); @@ -1397,7 +1397,7 @@ void AvatarData::setJointRotations(QVector jointRotations) { QVector AvatarData::getJointTranslations() const { if (QThread::currentThread() != thread()) { QVector result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointTranslations", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointTranslations", Q_RETURN_ARG(QVector, result)); return result; } @@ -1412,7 +1412,7 @@ QVector AvatarData::getJointTranslations() const { void AvatarData::setJointTranslations(QVector jointTranslations) { if (QThread::currentThread() != thread()) { QVector result; - hifi::qt::blockingInvokeMethod(const_cast(this), "setJointTranslations", + BLOCKING_INVOKE_METHOD(const_cast(this), "setJointTranslations", Q_ARG(QVector, jointTranslations)); } QWriteLocker writeLock(&_jointDataLock); @@ -1613,7 +1613,7 @@ void AvatarData::setDisplayName(const QString& displayName) { QVector AvatarData::getAttachmentData() const { if (QThread::currentThread() != thread()) { QVector result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getAttachmentData", + BLOCKING_INVOKE_METHOD(const_cast(this), "getAttachmentData", Q_RETURN_ARG(QVector, result)); return result; } @@ -2336,7 +2336,7 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID) { AvatarEntityMap AvatarData::getAvatarEntityData() const { AvatarEntityMap result; if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(const_cast(this), "getAvatarEntityData", + BLOCKING_INVOKE_METHOD(const_cast(this), "getAvatarEntityData", Q_RETURN_ARG(AvatarEntityMap, result)); return result; } @@ -2377,7 +2377,7 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() { AvatarEntityIDs result; if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(const_cast(this), "getAndClearRecentlyDetachedIDs", + BLOCKING_INVOKE_METHOD(const_cast(this), "getAndClearRecentlyDetachedIDs", Q_RETURN_ARG(AvatarEntityIDs, result)); return result; } diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 92abec78fa..29b8aee08b 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -291,7 +291,7 @@ glm::vec2 CompositorHelper::getReticleMaximumPosition() const { void CompositorHelper::sendFakeMouseEvent() { if (qApp->thread() != QThread::currentThread()) { - hifi::qt::blockingInvokeMethod(this, "sendFakeMouseEvent"); + BLOCKING_INVOKE_METHOD(this, "sendFakeMouseEvent"); return; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index fbf76df38e..a8eca41077 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -381,7 +381,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading // Only create and delete models on the thread that owns the EntityTreeRenderer if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "allocateModel", + BLOCKING_INVOKE_METHOD(this, "allocateModel", Q_RETURN_ARG(ModelPointer, model), Q_ARG(const QString&, url)); @@ -398,7 +398,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading ModelPointer EntityTreeRenderer::updateModel(ModelPointer model, const QString& newUrl) { // Only create and delete models on the thread that owns the EntityTreeRenderer if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "updateModel", + BLOCKING_INVOKE_METHOD(this, "updateModel", Q_RETURN_ARG(ModelPointer, model), Q_ARG(ModelPointer, model), Q_ARG(const QString&, newUrl)); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index ae9f79f0f6..f22631d363 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1489,7 +1489,7 @@ int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString return -1; } int result; - hifi::qt::blockingInvokeMethod(_entityTree.get(), "getJointIndex", + BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointIndex", Q_RETURN_ARG(int, result), Q_ARG(QUuid, entityID), Q_ARG(QString, name)); return result; } @@ -1499,7 +1499,7 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) { return QStringList(); } QStringList result; - hifi::qt::blockingInvokeMethod(_entityTree.get(), "getJointNames", + BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointNames", Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID)); return result; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 82314d0cd1..262f0318b6 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -233,7 +233,7 @@ void NodeList::processICEPingPacket(QSharedPointer message) { void NodeList::reset() { if (thread() != QThread::currentThread()) { - hifi::qt::blockingInvokeMethod(this, "reset"); + QMetaObject::invokeMethod(this, "reset"); return; } diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 0c91a581ce..43f0e9335d 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -180,7 +180,7 @@ ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) { if (QThread::currentThread() != thread()) { // Must be called in thread to ensure getResource returns a valid pointer - hifi::qt::blockingInvokeMethod(this, "prefetch", + BLOCKING_INVOKE_METHOD(this, "prefetch", Q_RETURN_ARG(ScriptableResource*, result), Q_ARG(QUrl, url), Q_ARG(void*, extra)); return result; @@ -303,7 +303,7 @@ QVariantList ResourceCache::getResourceList() { QVariantList list; if (QThread::currentThread() != thread()) { // NOTE: invokeMethod does not allow a const QObject* - hifi::qt::blockingInvokeMethod(this, "getResourceList", + BLOCKING_INVOKE_METHOD(this, "getResourceList", Q_RETURN_ARG(QVariantList, list)); } else { auto resources = _resources.uniqueKeys(); diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 89a6758366..a3374a0f47 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -277,7 +277,7 @@ Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) { void Socket::clearConnections() { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "clearConnections"); + BLOCKING_INVOKE_METHOD(this, "clearConnections"); return; } diff --git a/libraries/plugins/src/plugins/InputConfiguration.cpp b/libraries/plugins/src/plugins/InputConfiguration.cpp index 8ce206988b..9234ac6585 100644 --- a/libraries/plugins/src/plugins/InputConfiguration.cpp +++ b/libraries/plugins/src/plugins/InputConfiguration.cpp @@ -23,7 +23,7 @@ InputConfiguration::InputConfiguration() { QStringList InputConfiguration::inputPlugins() { if (QThread::currentThread() != thread()) { QStringList result; - hifi::qt::blockingInvokeMethod(this, "inputPlugins", + BLOCKING_INVOKE_METHOD(this, "inputPlugins", Q_RETURN_ARG(QStringList, result)); return result; } @@ -44,7 +44,7 @@ QStringList InputConfiguration::inputPlugins() { QStringList InputConfiguration::activeInputPlugins() { if (QThread::currentThread() != thread()) { QStringList result; - hifi::qt::blockingInvokeMethod(this, "activeInputPlugins", + BLOCKING_INVOKE_METHOD(this, "activeInputPlugins", Q_RETURN_ARG(QStringList, result)); return result; } @@ -66,7 +66,7 @@ QStringList InputConfiguration::activeInputPlugins() { QString InputConfiguration::configurationLayout(QString pluginName) { if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "configurationLayout", + BLOCKING_INVOKE_METHOD(this, "configurationLayout", Q_RETURN_ARG(QString, result), Q_ARG(QString, pluginName)); return result; @@ -83,7 +83,7 @@ QString InputConfiguration::configurationLayout(QString pluginName) { void InputConfiguration::setConfigurationSettings(QJsonObject configurationSettings, QString pluginName) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "setConfigurationSettings", + BLOCKING_INVOKE_METHOD(this, "setConfigurationSettings", Q_ARG(QJsonObject, configurationSettings), Q_ARG(QString, pluginName)); return; @@ -99,7 +99,7 @@ void InputConfiguration::setConfigurationSettings(QJsonObject configurationSetti QJsonObject InputConfiguration::configurationSettings(QString pluginName) { if (QThread::currentThread() != thread()) { QJsonObject result; - hifi::qt::blockingInvokeMethod(this, "configurationSettings", + BLOCKING_INVOKE_METHOD(this, "configurationSettings", Q_RETURN_ARG(QJsonObject, result), Q_ARG(QString, pluginName)); return result; @@ -115,7 +115,7 @@ QJsonObject InputConfiguration::configurationSettings(QString pluginName) { void InputConfiguration::calibratePlugin(QString pluginName) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "calibratePlugin"); + BLOCKING_INVOKE_METHOD(this, "calibratePlugin"); return; } @@ -130,7 +130,7 @@ void InputConfiguration::calibratePlugin(QString pluginName) { bool InputConfiguration::uncalibratePlugin(QString pluginName) { if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "uncalibratePlugin", + BLOCKING_INVOKE_METHOD(this, "uncalibratePlugin", Q_ARG(bool, result)); return result; } diff --git a/libraries/recording/src/recording/ClipCache.cpp b/libraries/recording/src/recording/ClipCache.cpp index 458979bf96..0fbbf1bc8e 100644 --- a/libraries/recording/src/recording/ClipCache.cpp +++ b/libraries/recording/src/recording/ClipCache.cpp @@ -39,7 +39,7 @@ ClipCache::ClipCache(QObject* parent) : NetworkClipLoaderPointer ClipCache::getClipLoader(const QUrl& url) { if (QThread::currentThread() != thread()) { NetworkClipLoaderPointer result; - hifi::qt::blockingInvokeMethod(this, "getClipLoader", + BLOCKING_INVOKE_METHOD(this, "getClipLoader", Q_RETURN_ARG(NetworkClipLoaderPointer, result), Q_ARG(const QUrl&, url)); return result; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 94b074d1e3..45be09b701 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -871,7 +871,7 @@ bool Model::getRelativeDefaultJointTranslation(int jointIndex, glm::vec3& transl QStringList Model::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; - hifi::qt::blockingInvokeMethod(const_cast(this), "getJointNames", + BLOCKING_INVOKE_METHOD(const_cast(this), "getJointNames", Q_RETURN_ARG(QStringList, result)); return result; } diff --git a/libraries/render/src/task/Config.cpp b/libraries/render/src/task/Config.cpp index d1edd8bda8..b378237c9c 100644 --- a/libraries/render/src/task/Config.cpp +++ b/libraries/render/src/task/Config.cpp @@ -61,7 +61,7 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) { void TaskConfig::refresh() { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "refresh"); + BLOCKING_INVOKE_METHOD(this, "refresh"); return; } diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index 4023af375a..28bf5ed163 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -34,7 +34,7 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(SharedSoundPointer sound if (QThread::currentThread() != thread()) { ScriptAudioInjector* injector = NULL; - hifi::qt::blockingInvokeMethod(this, "playSound", + BLOCKING_INVOKE_METHOD(this, "playSound", Q_RETURN_ARG(ScriptAudioInjector*, injector), Q_ARG(SharedSoundPointer, sound), Q_ARG(const AudioInjectorOptions&, injectorOptions)); diff --git a/libraries/script-engine/src/RecordingScriptingInterface.cpp b/libraries/script-engine/src/RecordingScriptingInterface.cpp index cd5b79b4a8..b51e9cd529 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.cpp +++ b/libraries/script-engine/src/RecordingScriptingInterface.cpp @@ -99,7 +99,7 @@ void RecordingScriptingInterface::loadRecording(const QString& url, QScriptValue void RecordingScriptingInterface::startPlaying() { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "startPlaying"); + BLOCKING_INVOKE_METHOD(this, "startPlaying"); return; } @@ -116,7 +116,7 @@ void RecordingScriptingInterface::setPlayerAudioOffset(float audioOffset) { void RecordingScriptingInterface::setPlayerTime(float time) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "setPlayerTime", Q_ARG(float, time)); + BLOCKING_INVOKE_METHOD(this, "setPlayerTime", Q_ARG(float, time)); return; } _player->seek(time); @@ -148,7 +148,7 @@ void RecordingScriptingInterface::setPlayerUseSkeletonModel(bool useSkeletonMode void RecordingScriptingInterface::pausePlayer() { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "pausePlayer"); + BLOCKING_INVOKE_METHOD(this, "pausePlayer"); return; } _player->pause(); @@ -156,7 +156,7 @@ void RecordingScriptingInterface::pausePlayer() { void RecordingScriptingInterface::stopPlaying() { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "stopPlaying"); + BLOCKING_INVOKE_METHOD(this, "stopPlaying"); return; } _player->stop(); @@ -177,7 +177,7 @@ void RecordingScriptingInterface::startRecording() { } if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "startRecording"); + BLOCKING_INVOKE_METHOD(this, "startRecording"); return; } @@ -200,7 +200,7 @@ QString RecordingScriptingInterface::getDefaultRecordingSaveDirectory() { void RecordingScriptingInterface::saveRecording(const QString& filename) { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "saveRecording", + BLOCKING_INVOKE_METHOD(this, "saveRecording", Q_ARG(QString, filename)); return; } @@ -221,7 +221,7 @@ bool RecordingScriptingInterface::saveRecordingToAsset(QScriptValue getClipAtpUr if (QThread::currentThread() != thread()) { bool result; - hifi::qt::blockingInvokeMethod(this, "saveRecordingToAsset", + BLOCKING_INVOKE_METHOD(this, "saveRecordingToAsset", Q_RETURN_ARG(bool, result), Q_ARG(QScriptValue, getClipAtpUrl)); return result; @@ -258,7 +258,7 @@ bool RecordingScriptingInterface::saveRecordingToAsset(QScriptValue getClipAtpUr void RecordingScriptingInterface::loadLastRecording() { if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "loadLastRecording"); + BLOCKING_INVOKE_METHOD(this, "loadLastRecording"); return; } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 52ce11c3cf..b51cb0ee3b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -965,7 +965,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " "sourceCode:" << sourceCode << " fileName:" << fileName << "lineNumber:" << lineNumber; #endif - hifi::qt::blockingInvokeMethod(this, "evaluate", + BLOCKING_INVOKE_METHOD(this, "evaluate", Q_RETURN_ARG(QScriptValue, result), Q_ARG(const QString&, sourceCode), Q_ARG(const QString&, fileName), diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 254312fa45..57b04eeb82 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -453,7 +453,7 @@ ScriptEngine* ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserL bool activateMainWindow, bool reload) { if (thread() != QThread::currentThread()) { ScriptEngine* result { nullptr }; - hifi::qt::blockingInvokeMethod(this, "loadScript", Q_RETURN_ARG(ScriptEngine*, result), + BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEngine*, result), Q_ARG(QUrl, scriptFilename), Q_ARG(bool, isUserLoaded), Q_ARG(bool, loadScriptFromEditor), diff --git a/libraries/shared/src/shared/QtHelpers.cpp b/libraries/shared/src/shared/QtHelpers.cpp index 3681136bf2..1ce1c3e07c 100644 --- a/libraries/shared/src/shared/QtHelpers.cpp +++ b/libraries/shared/src/shared/QtHelpers.cpp @@ -17,6 +17,7 @@ Q_LOGGING_CATEGORY(thread_safety, "hifi.thread_safety") namespace hifi { namespace qt { bool blockingInvokeMethod( + const char* function, QObject *obj, const char *member, QGenericReturnArgument ret, QGenericArgument val0, @@ -30,13 +31,14 @@ bool blockingInvokeMethod( QGenericArgument val8, QGenericArgument val9) { if (QThread::currentThread() == qApp->thread()) { - qCWarning(thread_safety, "BlockingQueuedConnection invoked on main thread!"); + qCWarning(thread_safety) << "BlockingQueuedConnection invoked on main thread from " << function; } return QMetaObject::invokeMethod(obj, member, Qt::BlockingQueuedConnection, ret, val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); } bool blockingInvokeMethod( + const char* function, QObject *obj, const char *member, QGenericArgument val0, QGenericArgument val1, @@ -48,8 +50,7 @@ bool blockingInvokeMethod( QGenericArgument val7, QGenericArgument val8, QGenericArgument val9) { - qCWarning(thread_safety, "BlockingQueuedConnection invoked without return value!"); - return blockingInvokeMethod(obj, member, QGenericReturnArgument(), val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); + return blockingInvokeMethod(function, obj, member, QGenericReturnArgument(), val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); } diff --git a/libraries/shared/src/shared/QtHelpers.h b/libraries/shared/src/shared/QtHelpers.h index 7b5a15a069..5da65a378f 100644 --- a/libraries/shared/src/shared/QtHelpers.h +++ b/libraries/shared/src/shared/QtHelpers.h @@ -12,9 +12,11 @@ #include + namespace hifi { namespace qt { bool blockingInvokeMethod( + const char* function, QObject *obj, const char *member, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(Q_NULLPTR), @@ -29,6 +31,7 @@ bool blockingInvokeMethod( QGenericArgument val9 = QGenericArgument()); bool blockingInvokeMethod( + const char* function, QObject *obj, const char *member, QGenericArgument val0 = QGenericArgument(Q_NULLPTR), QGenericArgument val1 = QGenericArgument(), @@ -43,5 +46,7 @@ bool blockingInvokeMethod( } } +#define BLOCKING_INVOKE_METHOD(obj, member, ...) \ + hifi::qt::blockingInvokeMethod(__FUNCTION__, obj, member, ##__VA_ARGS__) #endif diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 2bc5f89d00..135729653e 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -250,7 +250,7 @@ int OffscreenUi::waitForMessageBoxResult(QQuickItem* messageBox) { QMessageBox::StandardButton OffscreenUi::messageBox(Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { if (QThread::currentThread() != thread()) { QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton; - hifi::qt::blockingInvokeMethod(this, "messageBox", + BLOCKING_INVOKE_METHOD(this, "messageBox", Q_RETURN_ARG(QMessageBox::StandardButton, result), Q_ARG(Icon, icon), Q_ARG(QString, title), @@ -352,7 +352,7 @@ QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) { if (QThread::currentThread() != thread()) { QVariant result; - hifi::qt::blockingInvokeMethod(this, "inputDialog", + BLOCKING_INVOKE_METHOD(this, "inputDialog", Q_RETURN_ARG(QVariant, result), Q_ARG(Icon, icon), Q_ARG(QString, title), @@ -367,7 +367,7 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q QVariant OffscreenUi::customInputDialog(const Icon icon, const QString& title, const QVariantMap& config) { if (QThread::currentThread() != thread()) { QVariant result; - hifi::qt::blockingInvokeMethod(this, "customInputDialog", + BLOCKING_INVOKE_METHOD(this, "customInputDialog", Q_RETURN_ARG(QVariant, result), Q_ARG(Icon, icon), Q_ARG(QString, title), @@ -641,7 +641,7 @@ QString OffscreenUi::fileDialog(const QVariantMap& properties) { QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "fileOpenDialog", + BLOCKING_INVOKE_METHOD(this, "fileOpenDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), @@ -663,7 +663,7 @@ QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, QString OffscreenUi::fileSaveDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "fileSaveDialog", + BLOCKING_INVOKE_METHOD(this, "fileSaveDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), @@ -687,7 +687,7 @@ QString OffscreenUi::fileSaveDialog(const QString& caption, const QString& dir, QString OffscreenUi::existingDirectoryDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "existingDirectoryDialog", + BLOCKING_INVOKE_METHOD(this, "existingDirectoryDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), @@ -774,7 +774,7 @@ QString OffscreenUi::assetOpenDialog(const QString& caption, const QString& dir, // ATP equivalent of fileOpenDialog(). if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "assetOpenDialog", + BLOCKING_INVOKE_METHOD(this, "assetOpenDialog", Q_RETURN_ARG(QString, result), Q_ARG(QString, caption), Q_ARG(QString, dir), diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index 13fc9cc018..44a0af7787 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -38,7 +38,7 @@ QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngi QString QmlWebWindowClass::getURL() { if (QThread::currentThread() != thread()) { QString result; - hifi::qt::blockingInvokeMethod(this, "getURL", Q_RETURN_ARG(QString, result)); + BLOCKING_INVOKE_METHOD(this, "getURL", Q_RETURN_ARG(QString, result)); return result; } diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 8d93af15f5..14d8ec8985 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -79,7 +79,7 @@ QScriptValue QmlWindowClass::constructor(QScriptContext* context, QScriptEngine* Q_ASSERT(retVal); if (QThread::currentThread() != qApp->thread()) { retVal->moveToThread(qApp->thread()); - hifi::qt::blockingInvokeMethod(retVal, "initQml", Q_ARG(QVariantMap, properties)); + BLOCKING_INVOKE_METHOD(retVal, "initQml", Q_ARG(QVariantMap, properties)); } else { retVal->initQml(properties); } @@ -111,7 +111,7 @@ void QmlWindowClass::initQml(QVariantMap properties) { // Build the event bridge and wrapper on the main thread offscreenUi->loadInNewContext(qmlSource(), [&](QQmlContext* context, QObject* object) { _qmlWindow = object; - context->setContextProperty("eventBridge", this); + context->setContextProperty(EVENT_BRIDGE_PROPERTY, this); context->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership); context->engine()->setObjectOwnership(object, QQmlEngine::CppOwnership); if (properties.contains(TITLE_PROPERTY)) { @@ -243,7 +243,7 @@ void QmlWindowClass::setVisible(bool visible) { bool QmlWindowClass::isVisible() { if (QThread::currentThread() != thread()) { bool result = false; - hifi::qt::blockingInvokeMethod(this, "isVisible", Q_RETURN_ARG(bool, result)); + BLOCKING_INVOKE_METHOD(this, "isVisible", Q_RETURN_ARG(bool, result)); return result; } @@ -264,7 +264,7 @@ bool QmlWindowClass::isVisible() { glm::vec2 QmlWindowClass::getPosition() { if (QThread::currentThread() != thread()) { vec2 result; - hifi::qt::blockingInvokeMethod(this, "getPosition", Q_RETURN_ARG(vec2, result)); + BLOCKING_INVOKE_METHOD(this, "getPosition", Q_RETURN_ARG(vec2, result)); return result; } @@ -299,7 +299,7 @@ glm::vec2 toGlm(const QSizeF& size) { glm::vec2 QmlWindowClass::getSize() { if (QThread::currentThread() != thread()) { vec2 result; - hifi::qt::blockingInvokeMethod(this, "getSize", Q_RETURN_ARG(vec2, result)); + BLOCKING_INVOKE_METHOD(this, "getSize", Q_RETURN_ARG(vec2, result)); return result; } diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index 7aa4bc5e17..4e61eba28f 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -246,7 +246,7 @@ void Menu::removeAction(MenuWrapper* menu, const QString& actionName) { void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) { if (thread() != QThread::currentThread()) { - hifi::qt::blockingInvokeMethod(this, "setIsOptionChecked", + BLOCKING_INVOKE_METHOD(this, "setIsOptionChecked", Q_ARG(const QString&, menuOption), Q_ARG(bool, isChecked)); return; diff --git a/libraries/ui/src/ui/QmlWrapper.cpp b/libraries/ui/src/ui/QmlWrapper.cpp index d0f9a5e535..3879e1bc8f 100644 --- a/libraries/ui/src/ui/QmlWrapper.cpp +++ b/libraries/ui/src/ui/QmlWrapper.cpp @@ -38,7 +38,7 @@ void QmlWrapper::writeProperties(QVariant propertyMap) { QVariant QmlWrapper::readProperty(const QString& propertyName) { if (QThread::currentThread() != thread()) { QVariant result; - hifi::qt::blockingInvokeMethod(this, "readProperty", Q_RETURN_ARG(QVariant, result), Q_ARG(QString, propertyName)); + BLOCKING_INVOKE_METHOD(this, "readProperty", Q_RETURN_ARG(QVariant, result), Q_ARG(QString, propertyName)); return result; } @@ -48,7 +48,7 @@ QVariant QmlWrapper::readProperty(const QString& propertyName) { QVariant QmlWrapper::readProperties(const QVariant& propertyList) { if (QThread::currentThread() != thread()) { QVariant result; - hifi::qt::blockingInvokeMethod(this, "readProperties", Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, propertyList)); + BLOCKING_INVOKE_METHOD(this, "readProperties", Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, propertyList)); return result; } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 0dbcfac25c..857cae15cc 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -43,7 +43,7 @@ ToolbarProxy* TabletScriptingInterface::getSystemToolbarProxy() { TabletProxy* TabletScriptingInterface::getTablet(const QString& tabletId) { TabletProxy* tabletProxy = nullptr; if (QThread::currentThread() != thread()) { - hifi::qt::blockingInvokeMethod(this, "getTablet", Q_RETURN_ARG(TabletProxy*, tabletProxy), Q_ARG(QString, tabletId)); + BLOCKING_INVOKE_METHOD(this, "getTablet", Q_RETURN_ARG(TabletProxy*, tabletProxy), Q_ARG(QString, tabletId)); return tabletProxy; } @@ -291,7 +291,7 @@ void TabletProxy::initialScreen(const QVariant& url) { bool TabletProxy::isMessageDialogOpen() { if (QThread::currentThread() != thread()) { bool result = false; - hifi::qt::blockingInvokeMethod(this, "isMessageDialogOpen", Q_RETURN_ARG(bool, result)); + BLOCKING_INVOKE_METHOD(this, "isMessageDialogOpen", Q_RETURN_ARG(bool, result)); return result; } @@ -316,7 +316,7 @@ void TabletProxy::emitWebEvent(const QVariant& msg) { bool TabletProxy::isPathLoaded(const QVariant& path) { if (QThread::currentThread() != thread()) { bool result = false; - hifi::qt::blockingInvokeMethod(this, "isPathLoaded", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); + BLOCKING_INVOKE_METHOD(this, "isPathLoaded", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); return result; } @@ -479,7 +479,7 @@ void TabletProxy::loadQMLSource(const QVariant& path) { bool TabletProxy::pushOntoStack(const QVariant& path) { if (QThread::currentThread() != thread()) { bool result = false; - hifi::qt::blockingInvokeMethod(this, "pushOntoStack", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); + BLOCKING_INVOKE_METHOD(this, "pushOntoStack", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, path)); return result; } @@ -605,7 +605,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { if (QThread::currentThread() != thread()) { TabletButtonProxy* result = nullptr; - hifi::qt::blockingInvokeMethod(this, "addButton", Q_RETURN_ARG(TabletButtonProxy*, result), Q_ARG(QVariant, properties)); + BLOCKING_INVOKE_METHOD(this, "addButton", Q_RETURN_ARG(TabletButtonProxy*, result), Q_ARG(QVariant, properties)); return result; } @@ -632,7 +632,7 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { bool TabletProxy::onHomeScreen() { if (QThread::currentThread() != thread()) { bool result = false; - hifi::qt::blockingInvokeMethod(this, "onHomeScreen", Q_RETURN_ARG(bool, result)); + BLOCKING_INVOKE_METHOD(this, "onHomeScreen", Q_RETURN_ARG(bool, result)); return result; } @@ -839,7 +839,7 @@ void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { QVariantMap TabletButtonProxy::getProperties() { if (QThread::currentThread() != thread()) { QVariantMap result; - hifi::qt::blockingInvokeMethod(this, "getProperties", Q_RETURN_ARG(QVariantMap, result)); + BLOCKING_INVOKE_METHOD(this, "getProperties", Q_RETURN_ARG(QVariantMap, result)); return result; } diff --git a/libraries/ui/src/ui/ToolbarScriptingInterface.cpp b/libraries/ui/src/ui/ToolbarScriptingInterface.cpp index adfc15cc83..d01b538004 100644 --- a/libraries/ui/src/ui/ToolbarScriptingInterface.cpp +++ b/libraries/ui/src/ui/ToolbarScriptingInterface.cpp @@ -70,7 +70,7 @@ ToolbarProxy::ToolbarProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qml ToolbarButtonProxy* ToolbarProxy::addButton(const QVariant& properties) { if (QThread::currentThread() != thread()) { ToolbarButtonProxy* result = nullptr; - hifi::qt::blockingInvokeMethod(this, "addButton", Q_RETURN_ARG(ToolbarButtonProxy*, result), Q_ARG(QVariant, properties)); + BLOCKING_INVOKE_METHOD(this, "addButton", Q_RETURN_ARG(ToolbarButtonProxy*, result), Q_ARG(QVariant, properties)); return result; } @@ -101,7 +101,7 @@ void ToolbarProxy::removeButton(const QVariant& name) { ToolbarProxy* ToolbarScriptingInterface::getToolbar(const QString& toolbarId) { if (QThread::currentThread() != thread()) { ToolbarProxy* result = nullptr; - hifi::qt::blockingInvokeMethod(this, "getToolbar", Q_RETURN_ARG(ToolbarProxy*, result), Q_ARG(QString, toolbarId)); + BLOCKING_INVOKE_METHOD(this, "getToolbar", Q_RETURN_ARG(ToolbarProxy*, result), Q_ARG(QString, toolbarId)); return result; } From e0120ebf3011a3d5cb477c437ba076d8e9d983b2 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Sun, 2 Jul 2017 03:20:07 +0100 Subject: [PATCH 13/24] Rocket Hands --- .../marketplace/rocketHands/rockethands.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 unpublishedScripts/marketplace/rocketHands/rockethands.js diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js new file mode 100644 index 0000000000..678e51565d --- /dev/null +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -0,0 +1,43 @@ +"use strict"; + +/* + rockethands.js + system + + Created by Cain Kilgore on 30/06/2017 + 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 +*/ + +(function() { + var isRocketing = false; + + Script.setInterval(function() { + if (Controller.Hardware.Vive) { + var rightHand = Controller.getPoseValue(Controller.Hardware.Vive.RightHand); + var getHip = MyAvatar.getJointPosition("Hips"); + var worldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); + + if ((worldControllerPos.y > (getHip.y - 0.1)) && (worldControllerPos.y < (getHip.y + 0.1))) { + if (rightHand.rotation.y < 0.25 && rightHand.rotation.y > -0.25) { + isRocketing = true; + Controller.triggerHapticPulse(0.1, 120, 2); + MyAvatar.motorReferenceFrame = "world"; + var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); + if(!MyAvatar.isFlying()) { + moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); + } + MyAvatar.motorVelocity = moveVector; + MyAvatar.motorTimescale = 1.0; + } else { + if (isRocketing) { + MyAvatar.motorVelocity = 0; + isRocketing = false; + } + } + } + } + }, 100); +}()); \ No newline at end of file From a693a61ec891dd3f44fcd2f1d9e06eabb7353f04 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Sun, 2 Jul 2017 03:20:54 +0100 Subject: [PATCH 14/24] Cleanup --- scripts/developer/rockethands.js | 35 -------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 scripts/developer/rockethands.js diff --git a/scripts/developer/rockethands.js b/scripts/developer/rockethands.js deleted file mode 100644 index b68d6cc9c6..0000000000 --- a/scripts/developer/rockethands.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; - -// -// rockethands.js -// system -// -// Created by Cain Kilgore on 30/06/2017 -// 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 -// - -(function() { - function logToConsole(message) { - console.log("[rockethands.js] " + message); - } - - logToConsole("Rockethands.js script is now active."); - - Script.setInterval(function() { - if(Controller.Hardware.Vive) { - var rightHand = Controller.getPoseValue(Controller.Hardware.Vive.RightHand).rotation.y; - - // logToConsole("Y VALUE: " + rightHand); - if(rightHand < -0.1 && rightHand > -0.4) { - logToConsole("Pointing down.. eye position: " + Camera.getOrientation().x + ", " + Camera.getOrientation().y + ", " + Camera.getOrientation().z + " - we have liftoff - I think!"); - MyAvatar.motorReferenceFrame = "world"; - // MyAvatar.motorVelocity = {x: Camera.getOrientation().x, y: Camera.getOrientation().y*3, z: Camera.getOrientation().z}; - MyAvatar.motorVelocity = Camera.getOrientation()*3; - MyAvatar.motorTimescale = 1.0; - } - } - }, 1000); -}()); From 44f0b8bd6043484d9aadb14e2e5c2171e1935f98 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Sun, 2 Jul 2017 11:41:33 +0100 Subject: [PATCH 15/24] Support for Oculus & Vive - cleaned up some code, using Script.connect instead of setInterval --- .../marketplace/rocketHands/rockethands.js | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index 678e51565d..a4a4cf777c 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -13,15 +13,18 @@ (function() { var isRocketing = false; + MyAvatar.motorVelocity = 0; - Script.setInterval(function() { - if (Controller.Hardware.Vive) { - var rightHand = Controller.getPoseValue(Controller.Hardware.Vive.RightHand); - var getHip = MyAvatar.getJointPosition("Hips"); - var worldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); - - if ((worldControllerPos.y > (getHip.y - 0.1)) && (worldControllerPos.y < (getHip.y + 0.1))) { - if (rightHand.rotation.y < 0.25 && rightHand.rotation.y > -0.25) { + function checkRocketting() { + if (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) { + var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); + var rightHand = Controller.getPoseValue(Controller.Standard.RightHand); + var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); + var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); + var hipPosition = MyAvatar.getJointPosition("Hips"); + + if ((leftWorldControllerPos.y > (hipPosition.y - 0.1)) && (leftWorldControllerPos.y < (hipPosition.y + 0.1)) && rightWorldControllerPos.y > (hipPosition.y - 0.1) && (rightWorldControllerPos.y < (hipPosition.y + 0.1))) { + if (leftHand.rotation.y < 0.25 && leftHand.rotation.y > -0.25 && rightHand.rotation.y < 0.25 && rightHand.rotation.y > -0.25) { isRocketing = true; Controller.triggerHapticPulse(0.1, 120, 2); MyAvatar.motorReferenceFrame = "world"; @@ -31,13 +34,20 @@ } MyAvatar.motorVelocity = moveVector; MyAvatar.motorTimescale = 1.0; - } else { - if (isRocketing) { - MyAvatar.motorVelocity = 0; - isRocketing = false; - } - } + } else { + if (isRocketing) { + MyAvatar.motorVelocity = 0; + isRocketing = false; + } + } + } else { + if (isRocketing) { + MyAvatar.motorVelocity = 0; + isRocketing = false; + } } } - }, 100); + }; + + Script.update.connect(checkRocketting); }()); \ No newline at end of file From 7d382d9da0bbd70dc3e726fff4ef52cc1e0af85d Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 17:47:54 +0100 Subject: [PATCH 16/24] Fixed spelling, added is in HMD Check, removed Haptic Feedback as it wasn't part of the WL --- .../marketplace/rocketHands/rockethands.js | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index a4a4cf777c..0e8746add1 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -12,39 +12,45 @@ */ (function() { - var isRocketing = false; + var isRocketting = false; MyAvatar.motorVelocity = 0; function checkRocketting() { - if (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) { - var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); - var rightHand = Controller.getPoseValue(Controller.Standard.RightHand); - var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); - var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); - var hipPosition = MyAvatar.getJointPosition("Hips"); - - if ((leftWorldControllerPos.y > (hipPosition.y - 0.1)) && (leftWorldControllerPos.y < (hipPosition.y + 0.1)) && rightWorldControllerPos.y > (hipPosition.y - 0.1) && (rightWorldControllerPos.y < (hipPosition.y + 0.1))) { - if (leftHand.rotation.y < 0.25 && leftHand.rotation.y > -0.25 && rightHand.rotation.y < 0.25 && rightHand.rotation.y > -0.25) { - isRocketing = true; - Controller.triggerHapticPulse(0.1, 120, 2); - MyAvatar.motorReferenceFrame = "world"; - var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); - if(!MyAvatar.isFlying()) { - moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); + if (HMD.active) { + if (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) { + var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); + var rightHand = Controller.getPoseValue(Controller.Standard.RightHand); + var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); + var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); + var hipPosition = MyAvatar.getJointPosition("Hips"); + + if ((leftWorldControllerPos.y > (hipPosition.y - 0.1)) && (leftWorldControllerPos.y < (hipPosition.y + 0.1)) && rightWorldControllerPos.y > (hipPosition.y - 0.1) && (rightWorldControllerPos.y < (hipPosition.y + 0.1))) { + if (leftHand.rotation.y < 0.25 && leftHand.rotation.y > -0.25 && rightHand.rotation.y < 0.25 && rightHand.rotation.y > -0.25) { + isRocketting = true; + MyAvatar.motorReferenceFrame = "world"; + var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); + if(!MyAvatar.isFlying()) { + moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); + } + MyAvatar.motorVelocity = moveVector; + MyAvatar.motorTimescale = 1.0; + } else { + if (isRocketting) { + MyAvatar.motorVelocity = 0; + isRocketting = false; + } } - MyAvatar.motorVelocity = moveVector; - MyAvatar.motorTimescale = 1.0; } else { - if (isRocketing) { + if (isRocketting) { MyAvatar.motorVelocity = 0; - isRocketing = false; + isRocketting = false; } } - } else { - if (isRocketing) { - MyAvatar.motorVelocity = 0; - isRocketing = false; - } + } + } else { + if(isRocketting) { + MyAvatar.motorVelocity = 0; + isRocketting = false; } } }; From 2c53b5b372312ea7ec800a1d4721ec48a2b1c7d7 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 19:09:54 +0100 Subject: [PATCH 17/24] QA Cleanup --- .../marketplace/rocketHands/rockethands.js | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index 0e8746add1..f8a22be579 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -12,10 +12,9 @@ */ (function() { - var isRocketting = false; - MyAvatar.motorVelocity = 0; + var isRocketing = false; - function checkRocketting() { + function checkRocketing() { if (HMD.active) { if (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) { var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); @@ -23,37 +22,36 @@ var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); var hipPosition = MyAvatar.getJointPosition("Hips"); + var controllerHipThreshold = 0.1; + var controllerRotationThreshold = 0.25; - if ((leftWorldControllerPos.y > (hipPosition.y - 0.1)) && (leftWorldControllerPos.y < (hipPosition.y + 0.1)) && rightWorldControllerPos.y > (hipPosition.y - 0.1) && (rightWorldControllerPos.y < (hipPosition.y + 0.1))) { - if (leftHand.rotation.y < 0.25 && leftHand.rotation.y > -0.25 && rightHand.rotation.y < 0.25 && rightHand.rotation.y > -0.25) { - isRocketting = true; + if ((leftWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && (leftWorldControllerPos.y < (hipPosition.y + controllerHipThreshold)) && rightWorldControllerPos.y > (hipPosition.y - controllerHipThreshold) && (rightWorldControllerPos.y < (hipPosition.y + controllerHipThreshold))) { + if (leftHand.rotation.y < controllerRotationThreshold && leftHand.rotation.y > -controllerRotationThreshold && rightHand.rotation.y < controllerRotationThreshold && rightHand.rotation.y > -controllerRotationThreshold) { + isRocketing = true; MyAvatar.motorReferenceFrame = "world"; var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); - if(!MyAvatar.isFlying()) { + if (!MyAvatar.isFlying()) { moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); } MyAvatar.motorVelocity = moveVector; MyAvatar.motorTimescale = 1.0; } else { - if (isRocketting) { - MyAvatar.motorVelocity = 0; - isRocketting = false; - } + checkCanStopRocketing(); } } else { - if (isRocketting) { - MyAvatar.motorVelocity = 0; - isRocketting = false; - } + checkCanStopRocketing(); } } } else { - if(isRocketting) { - MyAvatar.motorVelocity = 0; - isRocketting = false; - } + checkCanStopRocketing(); } }; - Script.update.connect(checkRocketting); + function checkCanStopRocketing() { + if(isRocketing) { + MyAvatar.motorVelocity = 0; + isRocketing = false; + } + } + Script.update.connect(checkRocketing); }()); \ No newline at end of file From 44624c5fab70acde0af6e94c95f2b2bcf5465e58 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 19:11:57 +0100 Subject: [PATCH 18/24] space --- unpublishedScripts/marketplace/rocketHands/rockethands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index f8a22be579..e7d60d47a6 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -48,7 +48,7 @@ }; function checkCanStopRocketing() { - if(isRocketing) { + if (isRocketing) { MyAvatar.motorVelocity = 0; isRocketing = false; } From 5f600b4ea96b01efed573ec319f6a225988b5362 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 19:31:41 +0100 Subject: [PATCH 19/24] Cleanup again --- .../marketplace/rocketHands/rockethands.js | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index e7d60d47a6..da80a84432 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -22,28 +22,34 @@ var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); var hipPosition = MyAvatar.getJointPosition("Hips"); - var controllerHipThreshold = 0.1; - var controllerRotationThreshold = 0.25; + var controllerHipThreshold = 0.1; // In Meters. Experimentally determined. Used to figure out if user's hands are "close enough" to their hips. + var controllerRotationThreshold = 0.25; // In Radians. Experimentally determined. Used to figure out if user's hands are within a rotation threshold. - if ((leftWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && (leftWorldControllerPos.y < (hipPosition.y + controllerHipThreshold)) && rightWorldControllerPos.y > (hipPosition.y - controllerHipThreshold) && (rightWorldControllerPos.y < (hipPosition.y + controllerHipThreshold))) { - if (leftHand.rotation.y < controllerRotationThreshold && leftHand.rotation.y > -controllerRotationThreshold && rightHand.rotation.y < controllerRotationThreshold && rightHand.rotation.y > -controllerRotationThreshold) { - isRocketing = true; - MyAvatar.motorReferenceFrame = "world"; - var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); - if (!MyAvatar.isFlying()) { - moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); + if ((leftWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && + (leftWorldControllerPos.y < (hipPosition.y + controllerHipThreshold)) && + (rightWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && + (rightWorldControllerPos.y < (hipPosition.y + controllerHipThreshold))) { + if ((leftHand.rotation.y < controllerRotationThreshold) && + (leftHand.rotation.y > -controllerRotationThreshold) && + (rightHand.rotation.y < controllerRotationThreshold) && + (rightHand.rotation.y > -controllerRotationThreshold)) { + isRocketing = true; + MyAvatar.motorReferenceFrame = "world"; + var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); + if (!MyAvatar.isFlying()) { + moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); + } + MyAvatar.motorVelocity = moveVector; + MyAvatar.motorTimescale = 1.0; + } else { + checkCanStopRocketing(); } - MyAvatar.motorVelocity = moveVector; - MyAvatar.motorTimescale = 1.0; } else { checkCanStopRocketing(); } - } else { - checkCanStopRocketing(); } - } - } else { - checkCanStopRocketing(); + } else { + checkCanStopRocketing(); } }; From bfcddcf3b7ecaf1b95361ebd44b4831a18f40194 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 19:53:29 +0100 Subject: [PATCH 20/24] Cleaned up the code, created a function to check if the hands are in the right position. --- .../marketplace/rocketHands/rockethands.js | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index da80a84432..d5dfe48ea0 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -17,39 +17,23 @@ function checkRocketing() { if (HMD.active) { if (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) { - var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); - var rightHand = Controller.getPoseValue(Controller.Standard.RightHand); - var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); - var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); - var hipPosition = MyAvatar.getJointPosition("Hips"); - var controllerHipThreshold = 0.1; // In Meters. Experimentally determined. Used to figure out if user's hands are "close enough" to their hips. - var controllerRotationThreshold = 0.25; // In Radians. Experimentally determined. Used to figure out if user's hands are within a rotation threshold. - - if ((leftWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && - (leftWorldControllerPos.y < (hipPosition.y + controllerHipThreshold)) && - (rightWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && - (rightWorldControllerPos.y < (hipPosition.y + controllerHipThreshold))) { - if ((leftHand.rotation.y < controllerRotationThreshold) && - (leftHand.rotation.y > -controllerRotationThreshold) && - (rightHand.rotation.y < controllerRotationThreshold) && - (rightHand.rotation.y > -controllerRotationThreshold)) { - isRocketing = true; - MyAvatar.motorReferenceFrame = "world"; - var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); - if (!MyAvatar.isFlying()) { - moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); - } - MyAvatar.motorVelocity = moveVector; - MyAvatar.motorTimescale = 1.0; - } else { - checkCanStopRocketing(); - } - } else { - checkCanStopRocketing(); + if (canRocket()) { + isRocketing = true; + MyAvatar.motorReferenceFrame = "world"; + var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); + if (!MyAvatar.isFlying()) { + moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); } + MyAvatar.motorVelocity = moveVector; + MyAvatar.motorTimescale = 1.0; + } else { + checkCanStopRocketing(); } } else { checkCanStopRocketing(); + } + } else { + checkCanStopRocketing(); } }; @@ -59,5 +43,25 @@ isRocketing = false; } } + + function canRocket() { + var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); + var rightHand = Controller.getPoseValue(Controller.Standard.RightHand); + var leftWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); + var rightWorldControllerPos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); + var hipPosition = MyAvatar.getJointPosition("Hips"); + var controllerHipThreshold = 0.1; // In Meters. Experimentally determined. Used to figure out if user's hands are "close enough" to their hips. + var controllerRotationThreshold = 0.25; // In Radians. Experimentally determined. Used to figure out if user's hands are within a rotation threshold. + + return ((leftWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && + (leftWorldControllerPos.y < (hipPosition.y + controllerHipThreshold)) && + (rightWorldControllerPos.y > (hipPosition.y - controllerHipThreshold)) && + (rightWorldControllerPos.y < (hipPosition.y + controllerHipThreshold)) && + leftHand.rotation.y < controllerRotationThreshold && + leftHand.rotation.y > -controllerRotationThreshold && + rightHand.rotation.y < controllerRotationThreshold && + rightHand.rotation.y > -controllerRotationThreshold); + } + Script.update.connect(checkRocketing); }()); \ No newline at end of file From 1c5923914b4cf5bd99388e8a7a39fb459bd77a2d Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 19:58:26 +0100 Subject: [PATCH 21/24] Combining three if statements into one! --- .../marketplace/rocketHands/rockethands.js | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index d5dfe48ea0..1025dcb0aa 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -15,23 +15,15 @@ var isRocketing = false; function checkRocketing() { - if (HMD.active) { - if (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) { - if (canRocket()) { - isRocketing = true; - MyAvatar.motorReferenceFrame = "world"; - var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); - if (!MyAvatar.isFlying()) { - moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); - } - MyAvatar.motorVelocity = moveVector; - MyAvatar.motorTimescale = 1.0; - } else { - checkCanStopRocketing(); - } - } else { - checkCanStopRocketing(); + if (HMD.active && (Controller.Hardware.Vive || Controller.Hardware.OculusTouch) && canRocket()) { + isRocketing = true; + MyAvatar.motorReferenceFrame = "world"; + var moveVector = Vec3.multiply(Quat.getFront(Camera.getOrientation()), 10); + if (!MyAvatar.isFlying()) { + moveVector = Vec3.sum(moveVector, {x: 0, y: 1, z: 0}); } + MyAvatar.motorVelocity = moveVector; + MyAvatar.motorTimescale = 1.0; } else { checkCanStopRocketing(); } From eddb7a349c18334c56a27f24d90d609ff258cb00 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 3 Jul 2017 20:01:01 +0100 Subject: [PATCH 22/24] Boilerplate --- unpublishedScripts/marketplace/rocketHands/rockethands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/rocketHands/rockethands.js b/unpublishedScripts/marketplace/rocketHands/rockethands.js index 1025dcb0aa..672dcf2540 100644 --- a/unpublishedScripts/marketplace/rocketHands/rockethands.js +++ b/unpublishedScripts/marketplace/rocketHands/rockethands.js @@ -2,7 +2,7 @@ /* rockethands.js - system + unpublishedScripts/marketplace/rocketHands/rockethands.js Created by Cain Kilgore on 30/06/2017 Copyright 2017 High Fidelity, Inc. From 6c86c297cb64d1301e3df3a2e5c75104a3b2b51b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Jul 2017 12:40:52 -0700 Subject: [PATCH 23/24] Don't use a blocking connection for a high-frequency function like editOvleray --- interface/src/ui/overlays/Overlays.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 0c73f1fa70..48d75bf6e1 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -231,9 +231,12 @@ OverlayID Overlays::cloneOverlay(OverlayID id) { bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { if (QThread::currentThread() != thread()) { - bool result; - BLOCKING_INVOKE_METHOD(this, "editOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id), Q_ARG(QVariant, properties)); - return result; + // NOTE editOverlay can be called very frequently in scripts and can't afford to + // block waiting on the main thread. Additionally, no script actually + // examines the return value and does something useful with it, so use a non-blocking + // invoke and just always return true + QMetaObject::invokeMethod(this, "editOverlay", Q_ARG(OverlayID, id), Q_ARG(QVariant, properties)); + return true; } Overlay::Pointer thisOverlay = getOverlay(id); @@ -246,9 +249,9 @@ bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { bool Overlays::editOverlays(const QVariant& propertiesById) { if (QThread::currentThread() != thread()) { - bool result; - BLOCKING_INVOKE_METHOD(this, "editOverlays", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, propertiesById)); - return result; + // NOTE see comment on editOverlay for why this is not a blocking call + QMetaObject::invokeMethod(this, "editOverlays", Q_ARG(QVariant, propertiesById)); + return true; } QVariantMap map = propertiesById.toMap(); From 97edbb7f374da3f9a41c39afecaaee627b1fb5db Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Jul 2017 14:43:44 -0700 Subject: [PATCH 24/24] Restore mutex in overlay interface --- interface/src/ui/overlays/Overlays.cpp | 98 +++++++++++++++++++------- interface/src/ui/overlays/Overlays.h | 1 + 2 files changed, 74 insertions(+), 25 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 0c73f1fa70..1495bc2d77 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -40,19 +40,23 @@ Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") void Overlays::cleanupAllOverlays() { + QMap overlaysHUD; + QMap overlaysWorld; { - foreach(Overlay::Pointer overlay, _overlaysHUD) { - _overlaysToDelete.push_back(overlay); - } - foreach(Overlay::Pointer overlay, _overlaysWorld) { - _overlaysToDelete.push_back(overlay); - } - _overlaysHUD.clear(); - _overlaysWorld.clear(); -#if OVERLAY_PANELS - _panels.clear(); -#endif + QMutexLocker locker(&_mutex); + overlaysHUD.swap(_overlaysHUD); + overlaysWorld.swap(_overlaysWorld); } + + foreach(Overlay::Pointer overlay, overlaysHUD) { + _overlaysToDelete.push_back(overlay); + } + foreach(Overlay::Pointer overlay, overlaysWorld) { + _overlaysToDelete.push_back(overlay); + } +#if OVERLAY_PANELS + _panels.clear(); +#endif cleanupOverlaysToDelete(); } @@ -63,14 +67,19 @@ void Overlays::init() { } void Overlays::update(float deltatime) { - + QMap overlaysHUD; + QMap overlaysWorld; { - foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { - thisOverlay->update(deltatime); - } - foreach(Overlay::Pointer thisOverlay, _overlaysWorld) { - thisOverlay->update(deltatime); - } + QMutexLocker locker(&_mutex); + overlaysHUD = _overlaysHUD; + overlaysWorld = _overlaysWorld; + } + + foreach(const auto& thisOverlay, overlaysHUD) { + thisOverlay->update(deltatime); + } + foreach(const auto& thisOverlay, overlaysWorld) { + thisOverlay->update(deltatime); } cleanupOverlaysToDelete(); @@ -110,8 +119,14 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { int height = size.y; mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); + QMap overlaysHUD; + { + QMutexLocker locker(&_mutex); + overlaysHUD = _overlaysHUD; + } - foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { + + foreach(Overlay::Pointer thisOverlay, overlaysHUD) { // Reset all batch pipeline settings between overlay geometryCache->useSimpleDrawPipeline(batch); @@ -132,7 +147,10 @@ void Overlays::enable() { _enabled = true; } +// Note, can't be invoked by scripts, but can be called by the InterfaceParentFinder +// class on packet processing threads Overlay::Pointer Overlays::getOverlay(OverlayID id) const { + QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { return _overlaysHUD[id]; } @@ -193,13 +211,17 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { overlay->setOverlayID(thisID); overlay->setStackOrder(_stackOrder++); if (overlay->is3D()) { - _overlaysWorld[thisID] = overlay; + { + QMutexLocker locker(&_mutex); + _overlaysWorld[thisID] = overlay; + } render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; overlay->addToScene(overlay, scene, transaction); scene->enqueueTransaction(transaction); } else { + QMutexLocker locker(&_mutex); _overlaysHUD[thisID] = overlay; } @@ -275,6 +297,7 @@ void Overlays::deleteOverlay(OverlayID id) { Overlay::Pointer overlayToDelete; { + QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { overlayToDelete = _overlaysHUD.take(id); } else if (_overlaysWorld.contains(id)) { @@ -378,7 +401,13 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { if (!_enabled) { return UNKNOWN_OVERLAY_ID; } - QMapIterator i(_overlaysHUD); + + QMap overlaysHUD; + { + QMutexLocker locker(&_mutex); + overlaysHUD = _overlaysHUD; + } + QMapIterator i(overlaysHUD); const float LARGE_NEGATIVE_FLOAT = -9999999; glm::vec3 origin(pointCopy.x, pointCopy.y, LARGE_NEGATIVE_FLOAT); @@ -466,8 +495,14 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; + QMap overlaysWorld; + { + QMutexLocker locker(&_mutex); + overlaysWorld = _overlaysWorld; + } + RayToOverlayIntersectionResult result; - QMapIterator i(_overlaysWorld); + QMapIterator i(overlaysWorld); while (i.hasNext()) { i.next(); OverlayID thisID = i.key(); @@ -598,13 +633,20 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) { return result; } - Overlay::Pointer thisOverlay = _overlaysHUD[id]; + Overlay::Pointer thisOverlay; + { + QMutexLocker locker(&_mutex); + thisOverlay = _overlaysHUD[id]; + } if (thisOverlay) { if (auto textOverlay = std::dynamic_pointer_cast(thisOverlay)) { return textOverlay->textSize(text); } } else { - thisOverlay = _overlaysWorld[id]; + { + QMutexLocker locker(&_mutex); + thisOverlay = _overlaysWorld[id]; + } if (auto text3dOverlay = std::dynamic_pointer_cast(thisOverlay)) { return text3dOverlay->textSize(text); } @@ -675,6 +717,7 @@ bool Overlays::isAddedOverlay(OverlayID id) { return result; } + QMutexLocker locker(&_mutex); return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); } @@ -949,8 +992,13 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { return result; } + QMap overlaysWorld; + { + QMutexLocker locker(&_mutex); + overlaysWorld = _overlaysWorld; + } - QMapIterator i(_overlaysWorld); + QMapIterator i(overlaysWorld); int checked = 0; while (i.hasNext()) { checked++; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index d3fa70225e..bfb775b041 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -319,6 +319,7 @@ signals: private: void cleanupOverlaysToDelete(); + mutable QMutex _mutex; QMap _overlaysHUD; QMap _overlaysWorld; #if OVERLAY_PANELS