From b6cb1fcfe723a5f84ca4854665c1d2eeb8231f6a Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 22 Apr 2020 16:36:51 -0700 Subject: [PATCH 01/36] fix procedural applying to other things --- .../src/RenderableModelEntityItem.cpp | 29 +++++++++++++++++++ .../src/RenderableModelEntityItem.h | 1 + .../src/RenderableShapeEntityItem.cpp | 6 ++-- .../render-utils/src/MeshPartPayload.cpp | 3 +- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5fbbdfa0b8..c70220506e 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1442,6 +1442,31 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce emit requestRenderUpdate(); } + if (!_allProceduralMaterialsLoaded) { + std::lock_guard lock(_materialsLock); + bool allProceduralMaterialsLoaded = true; + for (auto& shapeMaterialPair : _materials) { + auto material = shapeMaterialPair.second; + while (!material.empty()) { + auto mat = material.top(); + if (mat.material && mat.material->isProcedural() && !mat.material->isReady()) { + allProceduralMaterialsLoaded = false; + break; + } + material.pop(); + } + if (!allProceduralMaterialsLoaded) { + break; + } + } + if (!allProceduralMaterialsLoaded) { + emit requestRenderUpdate(); + } else { + _allProceduralMaterialsLoaded = true; + model->setRenderItemsNeedUpdate(); + } + } + // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating // we will watch for that and ask the model to update it's render items if (model->getRenderItemsNeedUpdate()) { @@ -1559,6 +1584,10 @@ void ModelEntityRenderer::addMaterial(graphics::MaterialLayer material, const st if (_model && _model->fetchRenderItemIDs().size() > 0) { _model->addMaterial(material, parentMaterialName); } + if (material.material && material.material->isProcedural()) { + _allProceduralMaterialsLoaded = false; + emit requestRenderUpdate(); + } } void ModelEntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 0119c7bc26..7c219422a6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -198,6 +198,7 @@ private: bool _prevModelLoaded { false }; void processMaterials(); + bool _allProceduralMaterialsLoaded { false }; }; } } // namespace diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 222b833be2..38dd3b2160 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -32,7 +32,7 @@ bool ShapeEntityRenderer::needsRenderUpdate() const { if (resultWithReadLock([&] { auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && - mat->second.top().material->isEnabled()) { + mat->second.top().material->isReady()) { auto procedural = std::static_pointer_cast(mat->second.top().material); if (procedural->isFading()) { return true; @@ -88,7 +88,7 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { withReadLock([&] { auto mat = _materials.find("0"); - if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isEnabled()) { + if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) { auto procedural = std::static_pointer_cast(mat->second.top().material); if (procedural->isFading()) { procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f); @@ -136,7 +136,7 @@ bool ShapeEntityRenderer::isTransparent() const { auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.top().material) { - if (mat->second.top().material->isProcedural() && mat->second.top().material->isEnabled()) { + if (mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) { auto procedural = std::static_pointer_cast(mat->second.top().material); if (procedural->isFading()) { return true; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index e82af5395f..544947ab59 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -493,8 +493,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { batch.setDrawcallUniform(drawcallInfo); } - if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && - _drawMaterials.top().material->isReady()) { + if (_shapeKey.hasOwnPipeline()) { if (!(enableMaterialProceduralShaders)) { return; } From 61e6e8dfc9b39c85a4e2865012c1e47723717376 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Wed, 22 Apr 2020 23:16:51 -0700 Subject: [PATCH 02/36] Restructure ContextAwareProfile from a (thread-blocking) polling to a threadsafe-notification --- .../ui/src/ui/types/ContextAwareProfile.cpp | 65 +++++++++++++++---- .../ui/src/ui/types/ContextAwareProfile.h | 40 ++++++++++-- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index f74e8754c9..d5b8d958b6 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -20,20 +20,62 @@ static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; -ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : - ContextAwareProfileParent(context), _context(context) { - assert(context); +QMutex RestrictedContextMonitor::gl_monitorMapProtect; +RestrictedContextMonitor::TMonitorMap RestrictedContextMonitor::gl_monitorMap; + +RestrictedContextMonitor::~RestrictedContextMonitor() { + gl_monitorMapProtect.lock(); + TMonitorMap::iterator lookup = gl_monitorMap.find(context); + if (lookup != gl_monitorMap.end()) { + gl_monitorMap.erase(lookup); + } + gl_monitorMapProtect.unlock(); } +RestrictedContextMonitor::TSharedPtr RestrictedContextMonitor::getMonitor(QQmlContext* context, bool createIfMissing) { + TSharedPtr monitor; + + gl_monitorMapProtect.lock(); + TMonitorMap::const_iterator lookup = gl_monitorMap.find(context); + if (lookup != gl_monitorMap.end()) { + monitor = lookup->second.lock(); + assert(monitor); + } else if(createIfMissing) { + monitor = std::make_shared(context); + monitor->selfPtr = monitor; + gl_monitorMap.insert(TMonitorMap::value_type(context, monitor)); + } + gl_monitorMapProtect.unlock(); + return monitor; +} + +ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwareProfileParent(context), _context(context) { + assert(context); + + _monitor = RestrictedContextMonitor::getMonitor(context, true); + assert(_monitor); + connect(_monitor.get(), &RestrictedContextMonitor::onIsRestrictedChanged, this, &ContextAwareProfile::onIsRestrictedChanged); + if (_monitor->isUninitialized) { + _monitor->isRestricted = isRestrictedGetProperty(); + _monitor->isUninitialized = false; + } + _isRestricted.store(_monitor->isRestricted ? 1 : 0); +} void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { + RestrictedContextMonitor::TSharedPtr monitor = RestrictedContextMonitor::getMonitor(context, false); + context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); + if (monitor && monitor->isRestricted != restrict) { + monitor->isRestricted = restrict; + monitor->onIsRestrictedChanged(restrict); + } } -bool ContextAwareProfile::isRestrictedInternal() { +bool ContextAwareProfile::isRestrictedGetProperty() { if (QThread::currentThread() != thread()) { bool restrictedResult = false; - BLOCKING_INVOKE_METHOD(this, "isRestrictedInternal", Q_RETURN_ARG(bool, restrictedResult)); + BLOCKING_INVOKE_METHOD(this, "isRestrictedGetProperty", Q_RETURN_ARG(bool, restrictedResult)); return restrictedResult; } @@ -47,11 +89,10 @@ bool ContextAwareProfile::isRestrictedInternal() { return true; } -bool ContextAwareProfile::isRestricted() { - auto now = usecTimestampNow(); - if (now > _cacheExpiry) { - _cachedValue = isRestrictedInternal(); - _cacheExpiry = now + MAX_CACHE_AGE; - } - return _cachedValue; +void ContextAwareProfile::onIsRestrictedChanged(bool newValue) { + _isRestricted.store(newValue ? 1 : 0); +} + +bool ContextAwareProfile::isRestricted() { + return _isRestricted.load() != 0; } diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index 3192d2be54..30bdad4b78 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -12,6 +12,7 @@ #define hifi_ContextAwareProfile_h #include +#include #if !defined(Q_OS_ANDROID) #include @@ -30,12 +31,39 @@ using RequestInterceptorParent = QObject; class QQmlContext; +class RestrictedContextMonitor : public QObject { + Q_OBJECT +public: + typedef std::shared_ptr TSharedPtr; + typedef std::weak_ptr TWeakPtr; + + inline RestrictedContextMonitor(QQmlContext* c) : context(c) {} + ~RestrictedContextMonitor(); + + static TSharedPtr getMonitor(QQmlContext* context, bool createIfMissing); + +signals: + void onIsRestrictedChanged(bool newValue); + +public: + TWeakPtr selfPtr; + QQmlContext* context{ nullptr }; + bool isRestricted{ true }; + bool isUninitialized{ true }; + +private: + typedef std::map TMonitorMap; + + static QMutex gl_monitorMapProtect; + static TMonitorMap gl_monitorMap; +}; + class ContextAwareProfile : public ContextAwareProfileParent { Q_OBJECT public: static void restrictContext(QQmlContext* context, bool restrict = true); bool isRestricted(); - Q_INVOKABLE bool isRestrictedInternal(); + Q_INVOKABLE bool isRestrictedGetProperty(); protected: class RequestInterceptor : public RequestInterceptorParent { @@ -48,9 +76,13 @@ protected: ContextAwareProfile(QQmlContext* parent); QQmlContext* _context{ nullptr }; - bool _cachedValue{ false }; - quint64 _cacheExpiry{ 0 }; - constexpr static quint64 MAX_CACHE_AGE = MSECS_PER_SECOND; + QAtomicInt _isRestricted{ 0 }; + +private slots: + void onIsRestrictedChanged(bool newValue); + +private: + RestrictedContextMonitor::TSharedPtr _monitor; }; #endif // hifi_FileTypeProfile_h From 84a8c640e4f68fe9a9d7104a3acabdb53b5a22d8 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Fri, 15 May 2020 13:42:29 -0700 Subject: [PATCH 03/36] cleaned up variables names, replaced std::shared_ptr with QSharedPointer --- .../ui/src/ui/types/ContextAwareProfile.cpp | 24 +++++++++---------- .../ui/src/ui/types/ContextAwareProfile.h | 21 ++++++++-------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index d5b8d958b6..0374de87ff 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -25,15 +25,15 @@ RestrictedContextMonitor::TMonitorMap RestrictedContextMonitor::gl_monitorMap; RestrictedContextMonitor::~RestrictedContextMonitor() { gl_monitorMapProtect.lock(); - TMonitorMap::iterator lookup = gl_monitorMap.find(context); + TMonitorMap::iterator lookup = gl_monitorMap.find(_context); if (lookup != gl_monitorMap.end()) { gl_monitorMap.erase(lookup); } gl_monitorMapProtect.unlock(); } -RestrictedContextMonitor::TSharedPtr RestrictedContextMonitor::getMonitor(QQmlContext* context, bool createIfMissing) { - TSharedPtr monitor; +RestrictedContextMonitor::TSharedPointer RestrictedContextMonitor::getMonitor(QQmlContext* context, bool createIfMissing) { + TSharedPointer monitor; gl_monitorMapProtect.lock(); TMonitorMap::const_iterator lookup = gl_monitorMap.find(context); @@ -41,8 +41,8 @@ RestrictedContextMonitor::TSharedPtr RestrictedContextMonitor::getMonitor(QQmlCo monitor = lookup->second.lock(); assert(monitor); } else if(createIfMissing) { - monitor = std::make_shared(context); - monitor->selfPtr = monitor; + monitor = TSharedPointer::create(context); + monitor->_selfPointer = monitor; gl_monitorMap.insert(TMonitorMap::value_type(context, monitor)); } gl_monitorMapProtect.unlock(); @@ -55,19 +55,19 @@ ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwarePro _monitor = RestrictedContextMonitor::getMonitor(context, true); assert(_monitor); connect(_monitor.get(), &RestrictedContextMonitor::onIsRestrictedChanged, this, &ContextAwareProfile::onIsRestrictedChanged); - if (_monitor->isUninitialized) { - _monitor->isRestricted = isRestrictedGetProperty(); - _monitor->isUninitialized = false; + if (_monitor->_isUninitialized) { + _monitor->_isRestricted = isRestrictedGetProperty(); + _monitor->_isUninitialized = false; } - _isRestricted.store(_monitor->isRestricted ? 1 : 0); + _isRestricted.store(_monitor->_isRestricted ? 1 : 0); } void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { - RestrictedContextMonitor::TSharedPtr monitor = RestrictedContextMonitor::getMonitor(context, false); + RestrictedContextMonitor::TSharedPointer monitor = RestrictedContextMonitor::getMonitor(context, false); context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); - if (monitor && monitor->isRestricted != restrict) { - monitor->isRestricted = restrict; + if (monitor && monitor->_isRestricted != restrict) { + monitor->_isRestricted = restrict; monitor->onIsRestrictedChanged(restrict); } } diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index 30bdad4b78..ec0590eda5 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -13,6 +13,7 @@ #include #include +#include #if !defined(Q_OS_ANDROID) #include @@ -34,25 +35,25 @@ class QQmlContext; class RestrictedContextMonitor : public QObject { Q_OBJECT public: - typedef std::shared_ptr TSharedPtr; - typedef std::weak_ptr TWeakPtr; + typedef QSharedPointer TSharedPointer; + typedef QWeakPointer TWeakPointer; - inline RestrictedContextMonitor(QQmlContext* c) : context(c) {} + inline RestrictedContextMonitor(QQmlContext* c) : _context(c) {} ~RestrictedContextMonitor(); - static TSharedPtr getMonitor(QQmlContext* context, bool createIfMissing); + static TSharedPointer getMonitor(QQmlContext* context, bool createIfMissing); signals: void onIsRestrictedChanged(bool newValue); public: - TWeakPtr selfPtr; - QQmlContext* context{ nullptr }; - bool isRestricted{ true }; - bool isUninitialized{ true }; + TWeakPointer _selfPointer; + QQmlContext* _context{ nullptr }; + bool _isRestricted{ true }; + bool _isUninitialized{ true }; private: - typedef std::map TMonitorMap; + typedef std::map TMonitorMap; static QMutex gl_monitorMapProtect; static TMonitorMap gl_monitorMap; @@ -82,7 +83,7 @@ private slots: void onIsRestrictedChanged(bool newValue); private: - RestrictedContextMonitor::TSharedPtr _monitor; + RestrictedContextMonitor::TSharedPointer _monitor; }; #endif // hifi_FileTypeProfile_h From 3cff3f8b5deaba040c519adb8e43b619f5b55906 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Mon, 25 May 2020 15:51:48 -0700 Subject: [PATCH 04/36] found and removed another STL-ism --- libraries/ui/src/ui/types/ContextAwareProfile.cpp | 4 ++-- libraries/ui/src/ui/types/ContextAwareProfile.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index 0374de87ff..ef17ad7229 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -38,12 +38,12 @@ RestrictedContextMonitor::TSharedPointer RestrictedContextMonitor::getMonitor(QQ gl_monitorMapProtect.lock(); TMonitorMap::const_iterator lookup = gl_monitorMap.find(context); if (lookup != gl_monitorMap.end()) { - monitor = lookup->second.lock(); + monitor = lookup.value().lock(); assert(monitor); } else if(createIfMissing) { monitor = TSharedPointer::create(context); monitor->_selfPointer = monitor; - gl_monitorMap.insert(TMonitorMap::value_type(context, monitor)); + gl_monitorMap.insert(context, monitor); } gl_monitorMapProtect.unlock(); return monitor; diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index ec0590eda5..99fee8112d 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -12,6 +12,7 @@ #define hifi_ContextAwareProfile_h #include +#include #include #include @@ -53,7 +54,7 @@ public: bool _isUninitialized{ true }; private: - typedef std::map TMonitorMap; + typedef QMap TMonitorMap; static QMutex gl_monitorMapProtect; static TMonitorMap gl_monitorMap; From 47c96fcff56218275cf9145fe962140200b14373 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Thu, 28 May 2020 00:03:39 -0700 Subject: [PATCH 05/36] (re-)discovered QMutexLocker, good for tightening up the code a bit --- libraries/ui/src/ui/types/ContextAwareProfile.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index ef17ad7229..2399471e29 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -12,6 +12,7 @@ #include "ContextAwareProfile.h" #include +#include #include #include @@ -24,18 +25,17 @@ QMutex RestrictedContextMonitor::gl_monitorMapProtect; RestrictedContextMonitor::TMonitorMap RestrictedContextMonitor::gl_monitorMap; RestrictedContextMonitor::~RestrictedContextMonitor() { - gl_monitorMapProtect.lock(); + QMutexLocker locker(&gl_monitorMapProtect); TMonitorMap::iterator lookup = gl_monitorMap.find(_context); if (lookup != gl_monitorMap.end()) { gl_monitorMap.erase(lookup); } - gl_monitorMapProtect.unlock(); } RestrictedContextMonitor::TSharedPointer RestrictedContextMonitor::getMonitor(QQmlContext* context, bool createIfMissing) { TSharedPointer monitor; - gl_monitorMapProtect.lock(); + QMutexLocker locker(&gl_monitorMapProtect); TMonitorMap::const_iterator lookup = gl_monitorMap.find(context); if (lookup != gl_monitorMap.end()) { monitor = lookup.value().lock(); @@ -45,7 +45,6 @@ RestrictedContextMonitor::TSharedPointer RestrictedContextMonitor::getMonitor(QQ monitor->_selfPointer = monitor; gl_monitorMap.insert(context, monitor); } - gl_monitorMapProtect.unlock(); return monitor; } From 4f5f46a6237a693e0c7eb81154b58f11f870e159 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Thu, 30 Jul 2020 22:49:54 -0700 Subject: [PATCH 06/36] restructured the code to using a set of ContextAwareProfile objects rather than subscribing to an intermediate object changed _isRestricted from QAtomicInt to std::atomic --- .../ui/src/ui/types/ContextAwareProfile.cpp | 87 ++++++++++--------- .../ui/src/ui/types/ContextAwareProfile.h | 48 +++------- 2 files changed, 59 insertions(+), 76 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index 2399471e29..5df2d34dfa 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -12,8 +12,9 @@ #include "ContextAwareProfile.h" #include -#include +#include #include +#include #include #include @@ -21,53 +22,59 @@ static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; -QMutex RestrictedContextMonitor::gl_monitorMapProtect; -RestrictedContextMonitor::TMonitorMap RestrictedContextMonitor::gl_monitorMap; - -RestrictedContextMonitor::~RestrictedContextMonitor() { - QMutexLocker locker(&gl_monitorMapProtect); - TMonitorMap::iterator lookup = gl_monitorMap.find(_context); - if (lookup != gl_monitorMap.end()) { - gl_monitorMap.erase(lookup); - } -} - -RestrictedContextMonitor::TSharedPointer RestrictedContextMonitor::getMonitor(QQmlContext* context, bool createIfMissing) { - TSharedPointer monitor; - - QMutexLocker locker(&gl_monitorMapProtect); - TMonitorMap::const_iterator lookup = gl_monitorMap.find(context); - if (lookup != gl_monitorMap.end()) { - monitor = lookup.value().lock(); - assert(monitor); - } else if(createIfMissing) { - monitor = TSharedPointer::create(context); - monitor->_selfPointer = monitor; - gl_monitorMap.insert(context, monitor); - } - return monitor; -} +QReadWriteLock ContextAwareProfile::gl_contextMapProtect; +ContextAwareProfile::ContextMap ContextAwareProfile::gl_contextMap; ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwareProfileParent(context), _context(context) { assert(context); - _monitor = RestrictedContextMonitor::getMonitor(context, true); - assert(_monitor); - connect(_monitor.get(), &RestrictedContextMonitor::onIsRestrictedChanged, this, &ContextAwareProfile::onIsRestrictedChanged); - if (_monitor->_isUninitialized) { - _monitor->_isRestricted = isRestrictedGetProperty(); - _monitor->_isUninitialized = false; + { // register our object for future updates + QWriteLocker guard(&gl_contextMapProtect); + ContextMap::iterator setLookup = gl_contextMap.find(_context); + if (setLookup == gl_contextMap.end()) { + setLookup = gl_contextMap.insert(_context, ContextAwareProfileSet()); + } + assert(setLookup != gl_contextMap.end()); + ContextAwareProfileSet& profileSet = setLookup.value(); + assert(profileSet.find(this) == profileSet.end()); + profileSet.insert(this); + } + + _isRestricted.store(isRestrictedGetProperty()); +} + +ContextAwareProfile::~ContextAwareProfile() { + { // deregister our object + QWriteLocker guard(&gl_contextMapProtect); + ContextMap::iterator setLookup = gl_contextMap.find(_context); + assert(setLookup != gl_contextMap.end()); + if (setLookup != gl_contextMap.end()) { + ContextAwareProfileSet& profileSet = setLookup.value(); + assert(profileSet.find(this) != profileSet.end()); + profileSet.remove(this); + if (profileSet.isEmpty()) { + gl_contextMap.erase(setLookup); + } + } } - _isRestricted.store(_monitor->_isRestricted ? 1 : 0); } void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { - RestrictedContextMonitor::TSharedPointer monitor = RestrictedContextMonitor::getMonitor(context, false); + // set the QML property context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); - if (monitor && monitor->_isRestricted != restrict) { - monitor->_isRestricted = restrict; - monitor->onIsRestrictedChanged(restrict); + + // broadcast the new value to any registered ContextAwareProfile objects + { // deregister our object + QReadLocker guard(&gl_contextMapProtect); + ContextMap::const_iterator setLookup = gl_contextMap.find(context); + if (setLookup != gl_contextMap.end()) { + const ContextAwareProfileSet& profileSet = setLookup.value(); + for (ContextAwareProfileSet::const_iterator profileIterator = profileSet.begin(); + profileIterator != profileSet.end(); profileIterator++) { + (*profileIterator)->onIsRestrictedChanged(restrict); + } + } } } @@ -89,9 +96,9 @@ bool ContextAwareProfile::isRestrictedGetProperty() { } void ContextAwareProfile::onIsRestrictedChanged(bool newValue) { - _isRestricted.store(newValue ? 1 : 0); + _isRestricted.store(newValue); } bool ContextAwareProfile::isRestricted() { - return _isRestricted.load() != 0; + return _isRestricted.load(); } diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index 99fee8112d..d8ec762858 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -11,9 +11,10 @@ #ifndef hifi_ContextAwareProfile_h #define hifi_ContextAwareProfile_h -#include +#include #include -#include +#include +#include #include #if !defined(Q_OS_ANDROID) @@ -29,37 +30,8 @@ using ContextAwareProfileParent = QObject; using RequestInterceptorParent = QObject; #endif -#include - class QQmlContext; -class RestrictedContextMonitor : public QObject { - Q_OBJECT -public: - typedef QSharedPointer TSharedPointer; - typedef QWeakPointer TWeakPointer; - - inline RestrictedContextMonitor(QQmlContext* c) : _context(c) {} - ~RestrictedContextMonitor(); - - static TSharedPointer getMonitor(QQmlContext* context, bool createIfMissing); - -signals: - void onIsRestrictedChanged(bool newValue); - -public: - TWeakPointer _selfPointer; - QQmlContext* _context{ nullptr }; - bool _isRestricted{ true }; - bool _isUninitialized{ true }; - -private: - typedef QMap TMonitorMap; - - static QMutex gl_monitorMapProtect; - static TMonitorMap gl_monitorMap; -}; - class ContextAwareProfile : public ContextAwareProfileParent { Q_OBJECT public: @@ -77,14 +49,18 @@ protected: }; ContextAwareProfile(QQmlContext* parent); - QQmlContext* _context{ nullptr }; - QAtomicInt _isRestricted{ 0 }; - -private slots: + ~ContextAwareProfile(); void onIsRestrictedChanged(bool newValue); + QQmlContext* _context{ nullptr }; + std::atomic _isRestricted{ false }; + private: - RestrictedContextMonitor::TSharedPointer _monitor; + typedef QSet ContextAwareProfileSet; + typedef QMap ContextMap; + + static QReadWriteLock gl_contextMapProtect; + static ContextMap gl_contextMap; }; #endif // hifi_FileTypeProfile_h From 0c7aab1556e1e2a9186787fd251c23245e993a8f Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Sun, 2 Aug 2020 14:38:55 -0700 Subject: [PATCH 07/36] minor code review --- .../ui/src/ui/types/ContextAwareProfile.cpp | 40 +++++++++---------- .../ui/src/ui/types/ContextAwareProfile.h | 15 +++---- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index 5df2d34dfa..ee823ec784 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -22,19 +22,19 @@ static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; -QReadWriteLock ContextAwareProfile::gl_contextMapProtect; -ContextAwareProfile::ContextMap ContextAwareProfile::gl_contextMap; +QReadWriteLock ContextAwareProfile::_global_contextMapProtect; +ContextAwareProfile::ContextMap ContextAwareProfile::_global_contextMap; ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwareProfileParent(context), _context(context) { assert(context); { // register our object for future updates - QWriteLocker guard(&gl_contextMapProtect); - ContextMap::iterator setLookup = gl_contextMap.find(_context); - if (setLookup == gl_contextMap.end()) { - setLookup = gl_contextMap.insert(_context, ContextAwareProfileSet()); + QWriteLocker guard(&_global_contextMapProtect); + ContextMap::iterator setLookup = _global_contextMap.find(_context); + if (setLookup == _global_contextMap.end()) { + setLookup = _global_contextMap.insert(_context, ContextAwareProfileSet()); } - assert(setLookup != gl_contextMap.end()); + assert(setLookup != _global_contextMap.end()); ContextAwareProfileSet& profileSet = setLookup.value(); assert(profileSet.find(this) == profileSet.end()); profileSet.insert(this); @@ -45,15 +45,15 @@ ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwarePro ContextAwareProfile::~ContextAwareProfile() { { // deregister our object - QWriteLocker guard(&gl_contextMapProtect); - ContextMap::iterator setLookup = gl_contextMap.find(_context); - assert(setLookup != gl_contextMap.end()); - if (setLookup != gl_contextMap.end()) { + QWriteLocker guard(&_global_contextMapProtect); + ContextMap::iterator setLookup = _global_contextMap.find(_context); + assert(setLookup != _global_contextMap.end()); + if (setLookup != _global_contextMap.end()) { ContextAwareProfileSet& profileSet = setLookup.value(); assert(profileSet.find(this) != profileSet.end()); profileSet.remove(this); if (profileSet.isEmpty()) { - gl_contextMap.erase(setLookup); + _global_contextMap.erase(setLookup); } } } @@ -65,15 +65,13 @@ void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); // broadcast the new value to any registered ContextAwareProfile objects - { // deregister our object - QReadLocker guard(&gl_contextMapProtect); - ContextMap::const_iterator setLookup = gl_contextMap.find(context); - if (setLookup != gl_contextMap.end()) { - const ContextAwareProfileSet& profileSet = setLookup.value(); - for (ContextAwareProfileSet::const_iterator profileIterator = profileSet.begin(); - profileIterator != profileSet.end(); profileIterator++) { - (*profileIterator)->onIsRestrictedChanged(restrict); - } + QReadLocker guard(&_global_contextMapProtect); + ContextMap::const_iterator setLookup = _global_contextMap.find(context); + if (setLookup != _global_contextMap.end()) { + const ContextAwareProfileSet& profileSet = setLookup.value(); + for (ContextAwareProfileSet::const_iterator profileIterator = profileSet.begin(); + profileIterator != profileSet.end(); profileIterator++) { + (*profileIterator)->onIsRestrictedChanged(restrict); } } } diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index d8ec762858..c6f3020c4f 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -12,7 +12,7 @@ #define hifi_ContextAwareProfile_h #include -#include +#include #include #include #include @@ -50,17 +50,18 @@ protected: ContextAwareProfile(QQmlContext* parent); ~ContextAwareProfile(); - void onIsRestrictedChanged(bool newValue); + +private: + typedef QSet ContextAwareProfileSet; + typedef QHash ContextMap; QQmlContext* _context{ nullptr }; std::atomic _isRestricted{ false }; -private: - typedef QSet ContextAwareProfileSet; - typedef QMap ContextMap; + static QReadWriteLock _global_contextMapProtect; + static ContextMap _global_contextMap; - static QReadWriteLock gl_contextMapProtect; - static ContextMap gl_contextMap; + void onIsRestrictedChanged(bool newValue); }; #endif // hifi_FileTypeProfile_h From 37c613c3d440a7e2a80fa0b4133a35fc89661462 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Mon, 3 Aug 2020 20:50:10 -0700 Subject: [PATCH 08/36] more changes from code review --- .../ui/src/ui/types/ContextAwareProfile.cpp | 47 +++++++++---------- .../ui/src/ui/types/ContextAwareProfile.h | 6 +-- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.cpp b/libraries/ui/src/ui/types/ContextAwareProfile.cpp index ee823ec784..210e1f36b1 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.cpp +++ b/libraries/ui/src/ui/types/ContextAwareProfile.cpp @@ -22,19 +22,19 @@ static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess"; -QReadWriteLock ContextAwareProfile::_global_contextMapProtect; -ContextAwareProfile::ContextMap ContextAwareProfile::_global_contextMap; +QReadWriteLock ContextAwareProfile::_contextMapProtect; +ContextAwareProfile::ContextMap ContextAwareProfile::_contextMap; ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwareProfileParent(context), _context(context) { assert(context); { // register our object for future updates - QWriteLocker guard(&_global_contextMapProtect); - ContextMap::iterator setLookup = _global_contextMap.find(_context); - if (setLookup == _global_contextMap.end()) { - setLookup = _global_contextMap.insert(_context, ContextAwareProfileSet()); + QWriteLocker guard(&_contextMapProtect); + ContextMap::iterator setLookup = _contextMap.find(_context); + if (setLookup == _contextMap.end()) { + setLookup = _contextMap.insert(_context, ContextAwareProfileSet()); } - assert(setLookup != _global_contextMap.end()); + assert(setLookup != _contextMap.end()); ContextAwareProfileSet& profileSet = setLookup.value(); assert(profileSet.find(this) == profileSet.end()); profileSet.insert(this); @@ -44,17 +44,16 @@ ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwarePro } ContextAwareProfile::~ContextAwareProfile() { - { // deregister our object - QWriteLocker guard(&_global_contextMapProtect); - ContextMap::iterator setLookup = _global_contextMap.find(_context); - assert(setLookup != _global_contextMap.end()); - if (setLookup != _global_contextMap.end()) { - ContextAwareProfileSet& profileSet = setLookup.value(); - assert(profileSet.find(this) != profileSet.end()); - profileSet.remove(this); - if (profileSet.isEmpty()) { - _global_contextMap.erase(setLookup); - } + // deregister our object + QWriteLocker guard(&_contextMapProtect); + ContextMap::iterator setLookup = _contextMap.find(_context); + assert(setLookup != _contextMap.end()); + if (setLookup != _contextMap.end()) { + ContextAwareProfileSet& profileSet = setLookup.value(); + assert(profileSet.find(this) != profileSet.end()); + profileSet.remove(this); + if (profileSet.isEmpty()) { + _contextMap.erase(setLookup); } } } @@ -65,13 +64,13 @@ void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) { context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict); // broadcast the new value to any registered ContextAwareProfile objects - QReadLocker guard(&_global_contextMapProtect); - ContextMap::const_iterator setLookup = _global_contextMap.find(context); - if (setLookup != _global_contextMap.end()) { + QReadLocker guard(&_contextMapProtect); + ContextMap::const_iterator setLookup = _contextMap.find(context); + if (setLookup != _contextMap.end()) { const ContextAwareProfileSet& profileSet = setLookup.value(); for (ContextAwareProfileSet::const_iterator profileIterator = profileSet.begin(); profileIterator != profileSet.end(); profileIterator++) { - (*profileIterator)->onIsRestrictedChanged(restrict); + (*profileIterator)->_isRestricted.store(restrict); } } } @@ -93,10 +92,6 @@ bool ContextAwareProfile::isRestrictedGetProperty() { return true; } -void ContextAwareProfile::onIsRestrictedChanged(bool newValue) { - _isRestricted.store(newValue); -} - bool ContextAwareProfile::isRestricted() { return _isRestricted.load(); } diff --git a/libraries/ui/src/ui/types/ContextAwareProfile.h b/libraries/ui/src/ui/types/ContextAwareProfile.h index c6f3020c4f..486ac5481a 100644 --- a/libraries/ui/src/ui/types/ContextAwareProfile.h +++ b/libraries/ui/src/ui/types/ContextAwareProfile.h @@ -58,10 +58,8 @@ private: QQmlContext* _context{ nullptr }; std::atomic _isRestricted{ false }; - static QReadWriteLock _global_contextMapProtect; - static ContextMap _global_contextMap; - - void onIsRestrictedChanged(bool newValue); + static QReadWriteLock _contextMapProtect; + static ContextMap _contextMap; }; #endif // hifi_FileTypeProfile_h From a032ac66b191f32b288e3a67d857e9aac8473482 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sat, 22 Aug 2020 20:03:57 -0400 Subject: [PATCH 09/36] Update AddressManager links to NetworkingConstants. --- libraries/networking/src/AddressManager.cpp | 9 +++++---- libraries/networking/src/AddressManager.h | 4 ++-- libraries/networking/src/NetworkingConstants.h | 5 ++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 5f08f19d2b..a46b779546 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -27,16 +27,17 @@ #include "NodeList.h" #include "NetworkLogging.h" +#include "NetworkingConstants.h" #include "UserActivityLogger.h" #include "udt/PacketHeaders.h" -const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json"; -const QString DEFAULT_HOME_ADDRESS = "file:///~/serverless/tutorial.json"; -const QString REDIRECT_HIFI_ADDRESS = "file:///~/serverless/redirect.json"; +const QString DEFAULT_VIRCADIA_ADDRESS = NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; +const QString DEFAULT_HOME_ADDRESS = NetworkingConstants::DEFAULT_HOME_ADDRESS; +const QString REDIRECT_HIFI_ADDRESS = NetworkingConstants::REDIRECT_HIFI_ADDRESS; const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; -Setting::Handle currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_HIFI_ADDRESS); +Setting::Handle currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_VIRCADIA_ADDRESS); bool AddressManager::isConnected() { return DependencyManager::get()->getDomainHandler().isConnected(); diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 148c4f8580..fd173bfa9a 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -22,7 +22,7 @@ #include "AccountManager.h" -extern const QString DEFAULT_HIFI_ADDRESS; +extern const QString DEFAULT_VIRCADIA_ADDRESS; extern const QString REDIRECT_HIFI_ADDRESS; extern const QString DEFAULT_HOME_ADDRESS; @@ -300,7 +300,7 @@ public slots: * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's * location history is correctly maintained. */ - void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(DEFAULT_HIFI_ADDRESS, trigger); } + void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(DEFAULT_VIRCADIA_ADDRESS, trigger); } /**jsdoc * Takes you to the specified user's location. diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index edc1c1a1ef..c20753f8b7 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -56,7 +56,10 @@ namespace NetworkingConstants { const QUrl HELP_SCRIPTING_REFERENCE_URL{ "https://apidocs.vircadia.dev/" }; const QUrl HELP_RELEASE_NOTES_URL{ "https://docs.vircadia.dev/release-notes.html" }; const QUrl HELP_BUG_REPORT_URL{ "https://github.com/kasenvr/project-athena/issues" }; - + + const QString DEFAULT_VIRCADIA_ADDRESS = "file:///~/serverless/tutorial.json"; + const QString DEFAULT_HOME_ADDRESS = "file:///~/serverless/tutorial.json"; + const QString REDIRECT_HIFI_ADDRESS = "file:///~/serverless/redirect.json"; } const QString HIFI_URL_SCHEME_ABOUT = "about"; From a2bd06993fe7013918fc5d25e39b1af8c9c8d54e Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sun, 23 Aug 2020 01:49:32 -0400 Subject: [PATCH 10/36] Add option to build an Interface to go to specified address by default. --- cmake/macros/SetPackagingParameters.cmake | 1 + cmake/templates/BuildInfo.h.in | 3 ++- interface/src/Application.cpp | 5 +++++ interface/src/Menu.cpp | 20 ++++++++++++++------ libraries/networking/src/AddressManager.cpp | 9 +++++++-- libraries/networking/src/AddressManager.h | 9 ++++++--- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 1b7b3dbe8e..0f47a2fcb3 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -23,6 +23,7 @@ macro(SET_PACKAGING_PARAMETERS) set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV") set_from_env(RELEASE_NUMBER RELEASE_NUMBER "") set_from_env(STABLE_BUILD STABLE_BUILD 0) + set_from_env(INITIAL_STARTUP_LOCATION INITIAL_STARTUP_LOCATION "") message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}") diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 9fc9d9be81..02f6a50919 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -22,11 +22,12 @@ namespace BuildInfo { const QString DOMAIN_SERVER_NAME = "domain-server"; const QString AC_CLIENT_SERVER_NAME = "ac-client"; const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@"; - const QString ORGANIZATION_DOMAIN = "highfidelity.io"; + const QString ORGANIZATION_DOMAIN = "vircadia.com"; const QString VERSION = "@BUILD_VERSION@"; const QString BUILD_NUMBER = "@BUILD_NUMBER@"; const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@"; const QString BUILD_TIME = "@BUILD_TIME@"; + const QString INITIAL_STARTUP_LOCATION = "@INITIAL_STARTUP_LOCATION@"; enum BuildType { Dev, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc2aed7f53..281a2da6e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3974,6 +3974,11 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (_firstRun.get()) { + if (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) { + DependencyManager::get()->setHomeLocationToAddress(NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS); + Menu::getInstance()->triggerOption(MenuOption::HomeLocation); + } + if (!_overrideEntry) { DependencyManager::get()->goToEntry(); sentTo = SENT_TO_ENTRY; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 64cdf98239..9781470ed4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -232,12 +233,19 @@ Menu::Menu() { // Navigate > Start-up Location MenuWrapper* startupLocationMenu = navigateMenu->addMenu(MenuOption::StartUpLocation); - QActionGroup* startupLocatiopnGroup = new QActionGroup(startupLocationMenu); - startupLocatiopnGroup->setExclusive(true); - startupLocatiopnGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0, - false)); - startupLocatiopnGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0, - true)); + QActionGroup* startupLocationGroup = new QActionGroup(startupLocationMenu); + startupLocationGroup->setExclusive(true); + if (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) { + startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0, + true)); + startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0, + false)); + } else { + startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0, + false)); + startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0, + true)); + } // Settings menu ---------------------------------- MenuWrapper* settingsMenu = addMenu("Settings"); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index a46b779546..94bcb718d3 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -31,12 +31,17 @@ #include "UserActivityLogger.h" #include "udt/PacketHeaders.h" -const QString DEFAULT_VIRCADIA_ADDRESS = NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; -const QString DEFAULT_HOME_ADDRESS = NetworkingConstants::DEFAULT_HOME_ADDRESS; const QString REDIRECT_HIFI_ADDRESS = NetworkingConstants::REDIRECT_HIFI_ADDRESS; const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; +const QString DEFAULT_VIRCADIA_ADDRESS = (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) + ? BuildInfo::INITIAL_STARTUP_LOCATION + : NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; +const QString DEFAULT_HOME_ADDRESS = (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) + ? BuildInfo::INITIAL_STARTUP_LOCATION + : NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; + Setting::Handle currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_VIRCADIA_ADDRESS); bool AddressManager::isConnected() { diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index fd173bfa9a..daca6d3392 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -22,8 +22,8 @@ #include "AccountManager.h" -extern const QString DEFAULT_VIRCADIA_ADDRESS; extern const QString REDIRECT_HIFI_ADDRESS; +extern const QString DEFAULT_VIRCADIA_ADDRESS; extern const QString DEFAULT_HOME_ADDRESS; const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost"; @@ -292,7 +292,8 @@ public slots: * location history is correctly maintained. */ void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) { - handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); } + handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); + } /**jsdoc * Takes you to the default "welcome" metaverse address. @@ -300,7 +301,9 @@ public slots: * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's * location history is correctly maintained. */ - void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(DEFAULT_VIRCADIA_ADDRESS, trigger); } + void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { + handleUrl(DEFAULT_VIRCADIA_ADDRESS, trigger); + } /**jsdoc * Takes you to the specified user's location. From feac9683c42359e7f805f18227ebe0866b2ea99c Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sun, 23 Aug 2020 01:52:53 -0400 Subject: [PATCH 11/36] Remove unneeded if checks for INITIAL_STARTUP_LOCATION assignment. --- interface/src/Menu.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9781470ed4..491d4442a6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -235,17 +234,10 @@ Menu::Menu() { MenuWrapper* startupLocationMenu = navigateMenu->addMenu(MenuOption::StartUpLocation); QActionGroup* startupLocationGroup = new QActionGroup(startupLocationMenu); startupLocationGroup->setExclusive(true); - if (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) { - startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0, - true)); - startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0, - false)); - } else { - startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0, - false)); - startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0, - true)); - } + startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0, + false)); + startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0, + true)); // Settings menu ---------------------------------- MenuWrapper* settingsMenu = addMenu("Settings"); From b9a25905e2d931a545182ec465dd6ecfb9ad2293 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sun, 23 Aug 2020 14:49:21 -0400 Subject: [PATCH 12/36] Update build docs. --- BUILD.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index db81ecb30d..a1cbc5bcd6 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,6 +1,6 @@ # General Build Information -*Last Updated on June 27, 2020* +*Last Updated on August 23, 2020* ### OS Specific Build Guides @@ -80,6 +80,9 @@ Where /path/to/directory is the path to a directory where you wish the build fil // The type of release. RELEASE_TYPE=PRODUCTION|PR|DEV + // The Interface will have a custom default home and startup location. + INITIAL_STARTUP_LOCATION=Location/IP/URL + // TODO: What do these do? PRODUCTION_BUILD=0|1 PR_BUILD=0|1 From be46e3d8f2daee75865b7c60ff265808c9a70be5 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Mon, 24 Aug 2020 15:23:13 -0400 Subject: [PATCH 13/36] Code signing variables updated. --- BUILD.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index a1cbc5bcd6..c79dfc18f9 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,6 +1,6 @@ # General Build Information -*Last Updated on August 23, 2020* +*Last Updated on August 24, 2020* ### OS Specific Build Guides @@ -83,6 +83,10 @@ Where /path/to/directory is the path to a directory where you wish the build fil // The Interface will have a custom default home and startup location. INITIAL_STARTUP_LOCATION=Location/IP/URL + // Code-signing environment variables must be set at runtime AND globally when the signing takes place. + HF_PFX_FILE=Path to certificate + HF_PFX_PASSPHRASE=Passphrase for certificate + // TODO: What do these do? PRODUCTION_BUILD=0|1 PR_BUILD=0|1 From d41cb0a5cda2b0bcdd1fc59af97d5d11f11fe4d9 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Mon, 24 Aug 2020 15:27:56 -0400 Subject: [PATCH 14/36] Update Install.md instructions for code signing. --- INSTALL.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/INSTALL.md b/INSTALL.md index af398ee6b3..4307ddc79e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,5 +1,7 @@ # Creating an Installer +*Last Updated on August 24, 2020* + Follow the [build guide](BUILD.md) to figure out how to build Vircadia for your platform. During generation, CMake should produce an `install` target and a `package` target. @@ -13,6 +15,8 @@ To produce an installer, run the `package` target. However you will want to foll #### Windows +##### Prerequisites + To produce an executable installer on Windows, the following are required: 1. [7-zip]() @@ -59,6 +63,12 @@ To produce an executable installer on Windows, the following are required: 1. [Node.JS and NPM]() 1. Install version 10.15.0 LTS +##### Code Signing (optional) + +For code signing to work, you will need to set the `HF_PFX_FILE` and `HF_PFX_PASSPHRASE` environment variables globally. + +##### Creating the Installer + 1. Perform a clean cmake from a new terminal. 1. Open the `vircadia.sln` solution with elevated (administrator) permissions on Visual Studio and select the **Release** configuration. 1. Build the solution. From 3615ca70b112576b19a812b0c79a036375956a4e Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Wed, 26 Aug 2020 00:40:20 +0200 Subject: [PATCH 15/36] Fix build of hifiSdl2 on GCC 10 GCC 10 and above sets -fno-common by default, and causes a linking problem here: ultiple definition of `WAYLAND_wl_proxy_marshal' Work around it per https://medium.com/@clentfort/using-esy-sdl2-with-gcc-10-91b4fa0c5aa9 --- plugins/hifiSdl2/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/hifiSdl2/CMakeLists.txt b/plugins/hifiSdl2/CMakeLists.txt index c68723a10a..e1f0ee28d8 100644 --- a/plugins/hifiSdl2/CMakeLists.txt +++ b/plugins/hifiSdl2/CMakeLists.txt @@ -8,7 +8,14 @@ if (NOT APPLE) set(TARGET_NAME hifiSdl2) + if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 10.0) + # GCC 10 and above sets -fno-common by default, and causes a linking problem here: + # multiple definition of `WAYLAND_wl_proxy_marshal' + # + # Work around it per https://medium.com/@clentfort/using-esy-sdl2-with-gcc-10-91b4fa0c5aa9 + link_libraries("-Wl,--allow-multiple-definition") + endif() setup_hifi_plugin(Qml) link_hifi_libraries(shared controllers ui plugins input-plugins script-engine) target_sdl2() -endif() \ No newline at end of file +endif() From 2067a438c230a530256d9a7f945dbbdf3ce50485 Mon Sep 17 00:00:00 2001 From: Heather Anderson Date: Sun, 30 Aug 2020 17:20:39 -0700 Subject: [PATCH 16/36] fixed apparent typo preventing the CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION or CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION options from being reachable --- assignment-client/src/AssignmentClientApp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index c5b228bd16..1dd050fcb9 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -183,7 +183,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : } QString assignmentServerHostname; - if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { + if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) { assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); } if (parser.isSet(assignmentServerHostnameOption)) { @@ -192,7 +192,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : // check for an overriden assignment server port quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; - if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { + if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) { assignmentServerPort = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toUInt(); } From 75fa55baf7ade93939ef2de1ce87b8e9143c5a93 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 1 Sep 2020 09:34:11 -0700 Subject: [PATCH 17/36] tabs.css issue? --- scripts/system/html/css/tabs.css | 154 +++++++++++++++---------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/scripts/system/html/css/tabs.css b/scripts/system/html/css/tabs.css index 87e1c11ee8..349bd363de 100644 --- a/scripts/system/html/css/tabs.css +++ b/scripts/system/html/css/tabs.css @@ -1,77 +1,77 @@ -/* -// tabs.css -// -// Created by Alezia Kurdis on 27 Feb 2020 -// Copyright 2020 Project Athena contributors. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -*/ - -div.tabsContainer { - float: left; - width: 32px; - padding: 0px; -} - -.tabsContainer button { - padding: 4px; - text-align: center; - cursor: pointer; - transition: 0.4s; - font-size: 14px; - background-color: #404040; - border-color: #404040; - border-width: 1px 0px 1px 1px; - border-radius: 5px 0px 0px 5px; - outline: none; -} - -.tabsContainer button:hover { - background-color: #575757; -} - -.tabsContainer button.active { - background-color: #2E2E2E; -} - -div.labelTabHeader { - font-size: 20px; - font-weight: 700; - height: 40px; - color: #ffffff; -} - -div.tab-section-header { - width: 100%; - padding: 5px; -} - -table.tabsTableFrame { - width: 100%; - min-height: 352px; - display: block; -} - -tr.tabsTrFrame { - width: 100%; -} - -td.tabsFrame { - width: 32px; - vertical-align: top; - background-color: #575757; - padding: 0px; - border: 0px; -} - -td.tabsPropertiesFrame { - width: 100%; - vertical-align: top; - border:0px; -} - -div.tabsPropertiesPage { - min-height: 352px; - display: block; -} +/* +// tabs.css +// +// Created by Alezia Kurdis on 27 Feb 2020 +// Copyright 2020 Project Athena contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +div.tabsContainer { + float: left; + width: 32px; + padding: 0px; +} + +.tabsContainer button { + padding: 4px; + text-align: center; + cursor: pointer; + transition: 0.4s; + font-size: 14px; + background-color: #404040; + border-color: #404040; + border-width: 1px 0px 1px 1px; + border-radius: 5px 0px 0px 5px; + outline: none; +} + +.tabsContainer button:hover { + background-color: #575757; +} + +.tabsContainer button.active { + background-color: #2E2E2E; +} + +div.labelTabHeader { + font-size: 20px; + font-weight: 700; + height: 40px; + color: #ffffff; +} + +div.tab-section-header { + width: 100%; + padding: 5px; +} + +table.tabsTableFrame { + width: 100%; + min-height: 352px; + display: block; +} + +tr.tabsTrFrame { + width: 100%; +} + +td.tabsFrame { + width: 32px; + vertical-align: top; + background-color: #575757; + padding: 0px; + border: 0px; +} + +td.tabsPropertiesFrame { + width: 100%; + vertical-align: top; + border:0px; +} + +div.tabsPropertiesPage { + min-height: 352px; + display: block; +} From 9b47d924b33f526da28c36a8536722e13a623f1e Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 1 Sep 2020 09:37:59 -0700 Subject: [PATCH 18/36] fix merge conflict --- scripts/system/html/css/tabs.css | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/scripts/system/html/css/tabs.css b/scripts/system/html/css/tabs.css index 9806651953..6abd910300 100644 --- a/scripts/system/html/css/tabs.css +++ b/scripts/system/html/css/tabs.css @@ -2,11 +2,7 @@ // tabs.css // // Created by Alezia Kurdis on 27 Feb 2020 -<<<<<<< HEAD -// Copyright 2020 Project Athena contributors. -======= // Copyright 2020 Vircadia contributors. ->>>>>>> upstream/master // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -35,15 +31,9 @@ div.tabsContainer { background-color: #575757; } -<<<<<<< HEAD -.tabsContainer button.active { - background-color: #2E2E2E; -} -======= .tabsContainer button.active { background-color: #2E2E2E; } ->>>>>>> upstream/master div.labelTabHeader { font-size: 20px; @@ -59,11 +49,7 @@ div.tab-section-header { table.tabsTableFrame { width: 100%; -<<<<<<< HEAD - min-height: 352px; -======= min-height: 352px; ->>>>>>> upstream/master display: block; } @@ -82,11 +68,7 @@ td.tabsFrame { td.tabsPropertiesFrame { width: 100%; vertical-align: top; -<<<<<<< HEAD - border:0px; -======= border: 0px; ->>>>>>> upstream/master } div.tabsPropertiesPage { From fd2535ecaf2978d4815e86fd3cf85f18e018b2ea Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 6 Sep 2020 20:40:07 +1200 Subject: [PATCH 19/36] Fix browser window buttons and Web page favicon display --- interface/resources/qml/Browser.qml | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 496209a2a8..d2b93f45c9 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -63,29 +63,38 @@ ScrollingWindow { anchors.leftMargin: 8 HiFiGlyphs { id: back; - enabled: webview.canGoBack; + enabled: webview.canGoBack text: hifi.glyphs.backward - color: enabled ? hifi.colors.text : hifi.colors.disabledText + color: enabled ? hifi.colors.faintGray : hifi.colors.lightGray size: 48 - MouseArea { anchors.fill: parent; onClicked: webview.goBack() } + MouseArea { + anchors.fill: parent + onClicked: webview.goBack(); + } } HiFiGlyphs { id: forward; - enabled: webview.canGoForward; + enabled: webview.canGoForward text: hifi.glyphs.forward - color: enabled ? hifi.colors.text : hifi.colors.disabledText + color: enabled ? hifi.colors.faintGray : hifi.colors.lightGray size: 48 - MouseArea { anchors.fill: parent; onClicked: webview.goForward() } + MouseArea { + anchors.fill: parent + onClicked: webview.goForward(); + } } HiFiGlyphs { id: reload; - enabled: webview.canGoForward; + enabled: url !== "" text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload - color: enabled ? hifi.colors.text : hifi.colors.disabledText + color: enabled ? hifi.colors.faintGray : hifi.colors.lightGray size: 48 - MouseArea { anchors.fill: parent; onClicked: webview.goForward() } + MouseArea { + anchors.fill: parent + onClicked: webview.loading ? webview.stop() : webview.reload(); + } } } @@ -105,11 +114,12 @@ ScrollingWindow { width: parent.height height: parent.height Image { - source: webview.icon; + source: webview.icon x: (parent.height - height) / 2 y: (parent.width - width) / 2 - sourceSize: Qt.size(width, height); - verticalAlignment: Image.AlignVCenter; + width: 28 + height: 28 + verticalAlignment: Image.AlignVCenter horizontalAlignment: Image.AlignHCenter } } From 9d3b763256847dc833538c4f8dfc74fd07134b90 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 6 Sep 2020 20:49:29 +1200 Subject: [PATCH 20/36] Add hover state to browser window buttons --- interface/resources/qml/Browser.qml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index d2b93f45c9..b477ac0cbb 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -62,37 +62,43 @@ ScrollingWindow { anchors.left: parent.left anchors.leftMargin: 8 HiFiGlyphs { - id: back; + id: back enabled: webview.canGoBack text: hifi.glyphs.backward - color: enabled ? hifi.colors.faintGray : hifi.colors.lightGray + color: enabled ? (backMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray size: 48 MouseArea { + id: backMouseArea anchors.fill: parent + hoverEnabled: true onClicked: webview.goBack(); } } HiFiGlyphs { - id: forward; + id: forward enabled: webview.canGoForward text: hifi.glyphs.forward - color: enabled ? hifi.colors.faintGray : hifi.colors.lightGray + color: enabled ? (forwardMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray size: 48 MouseArea { + id: forwardMouseArea anchors.fill: parent + hoverEnabled: true onClicked: webview.goForward(); } } HiFiGlyphs { - id: reload; + id: reload enabled: url !== "" text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload - color: enabled ? hifi.colors.faintGray : hifi.colors.lightGray + color: enabled ? (reloadMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray size: 48 MouseArea { + id: reloadMouseArea anchors.fill: parent + hoverEnabled: true onClicked: webview.loading ? webview.stop() : webview.reload(); } } From 7da2fa1315e68213e871e30c398bea3bdd6133b9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 6 Sep 2020 20:56:44 +1200 Subject: [PATCH 21/36] Add open-in-externa-window button --- interface/resources/qml/Browser.qml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index b477ac0cbb..018f333ff3 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -49,6 +49,12 @@ ScrollingWindow { desktop.setAutoAdd(auto); } + function openExternalBrowser() { + Qt.openUrlExternally(addressBar.text); + root.shown = false; + root.windowClosed(); + } + Item { id:item width: pane.contentWidth @@ -115,6 +121,25 @@ ScrollingWindow { anchors.left: buttons.right anchors.leftMargin: 8 + HiFiGlyphs { + id: externalBrowser + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: 4 + enabled: !HMD.active && url !== "" + font.family: "FontAwesome" + text: "\uf24d" + rotation: -90 + color: enabled ? (externalBrowserMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray + size: 32 + MouseArea { + id: externalBrowserMouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: openExternalBrowser(); + } + } + Item { id: barIcon width: parent.height @@ -132,7 +157,7 @@ ScrollingWindow { TextField { id: addressBar - anchors.right: parent.right + anchors.right: externalBrowser.left anchors.rightMargin: 8 anchors.left: barIcon.right anchors.leftMargin: 0 From 1d27c0138c41818ce9122568a4ad99c39dfed697 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 6 Sep 2020 21:00:45 +1200 Subject: [PATCH 22/36] Fix browsing history --- interface/resources/qml/Browser.qml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 018f333ff3..44c544de97 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -165,22 +165,32 @@ ScrollingWindow { focus: true colorScheme: hifi.colorSchemes.dark placeholderText: "Enter URL" + inputMethodHints: Qt.ImhUrlCharactersOnly Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i") Keys.onPressed: { switch(event.key) { case Qt.Key_Enter: case Qt.Key_Return: event.accepted = true - if (text.indexOf("http") != 0) { + if (text.indexOf("http") !== 0) { text = "http://" + text; } + + // Setting webiew.url directly doesn't add the URL to the navigation history. + //webview.url = text; + // The following works around this bug. + text = encodeURI(text); + text = text.replace(/;/g, "%3b"); // Prevent script injection. + text = text.replace(/'/g, "%25"); // "" + webview.runJavaScript("window.location='" + text + "'"); + root.hidePermissionsBar(); root.keyboardRaised = false; - webview.url = text; break; } } } + } Rectangle { @@ -257,7 +267,7 @@ ScrollingWindow { Keys.onPressed: { switch(event.key) { case Qt.Key_L: - if (event.modifiers == Qt.ControlModifier) { + if (event.modifiers === Qt.ControlModifier) { event.accepted = true addressBar.selectAll() addressBar.forceActiveFocus() @@ -265,4 +275,5 @@ ScrollingWindow { break; } } + } // dialog From 29b96432bc533b3ad7bbf1634e5596a3521a9e03 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 6 Sep 2020 21:04:13 +1200 Subject: [PATCH 23/36] Clear favicon image when page is changed --- interface/resources/qml/Browser.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 44c544de97..6d5b9b7ae1 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -145,7 +145,7 @@ ScrollingWindow { width: parent.height height: parent.height Image { - source: webview.icon + source: webview.loading ? "" : webview.icon x: (parent.height - height) / 2 y: (parent.width - width) / 2 width: 28 From 84cb3b251554603198a8c1ee640e9a3021b49516 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 10 Sep 2020 08:58:35 +1200 Subject: [PATCH 24/36] Fix pick rays not intersecting glTF models --- libraries/fbx/src/GLTFSerializer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 3d2a7edca8..3a0271945b 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1019,7 +1019,9 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& hfmModel.meshes.append(HFMMesh()); HFMMesh& mesh = hfmModel.meshes[hfmModel.meshes.size() - 1]; - if (!hfmModel.hasSkeletonJoints) { + mesh.modelTransform = globalTransforms[nodeIndex]; + + if (!hfmModel.hasSkeletonJoints) { HFMCluster cluster; cluster.jointIndex = nodecount; cluster.inverseBindMatrix = glm::mat4(); From 2985ac2262383f3cf638e6bd139cc4456675a943 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 10 Sep 2020 13:15:56 +1200 Subject: [PATCH 25/36] Twek browser bar layout --- interface/resources/qml/Browser.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 6d5b9b7ae1..2fefb6bff4 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -64,7 +64,7 @@ ScrollingWindow { id: buttons spacing: 4 anchors.top: parent.top - anchors.topMargin: 8 + anchors.topMargin: 4 anchors.left: parent.left anchors.leftMargin: 8 HiFiGlyphs { @@ -115,7 +115,7 @@ ScrollingWindow { id: border height: 48 anchors.top: parent.top - anchors.topMargin: 8 + anchors.topMargin: 4 anchors.right: parent.right anchors.rightMargin: 8 anchors.left: buttons.right @@ -158,7 +158,7 @@ ScrollingWindow { TextField { id: addressBar anchors.right: externalBrowser.left - anchors.rightMargin: 8 + anchors.rightMargin: 32 anchors.left: barIcon.right anchors.leftMargin: 0 anchors.verticalCenter: parent.verticalCenter @@ -255,7 +255,7 @@ ScrollingWindow { parentRoot: root anchors.top: buttons.bottom - anchors.topMargin: 8 + anchors.topMargin: 4 anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right From 6337e84894e079e203288aa2a49e83ab75b6cde3 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 9 Sep 2020 22:41:05 -0400 Subject: [PATCH 26/36] Fix for Issue #696 This fixes a refresh of the FILE value in the Create App Entity list when updating the imageURL of an Image Entity. (It was missing in the condition that checks to add to the refresh of the list.) This solves the issue #696. --- scripts/system/create/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index 0de87e563c..15fd513ec2 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -2443,8 +2443,8 @@ var PropertiesTool = function (opts) { Entities.editEntity(entityID, properties); }); - if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined || - properties.visible !== undefined || properties.locked !== undefined) { + if (properties.name !== undefined || properties.modelURL !== undefined || properties.imageURL !== undefined || + properties.materialURL !== undefined || properties.visible !== undefined || properties.locked !== undefined) { sendListUpdate = true; } From da6a86b4117c827cb9a66f1a5e44825f6f1d14a0 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Thu, 10 Sep 2020 00:11:50 -0400 Subject: [PATCH 27/36] Create Material without url This enhancement changes the behavior when a Material Entity is created using the Create App. Previously, if we left the URL null, no entity was created. With this fix, if we left the URL null, then the entity is created with "materialData" already set in materialURL (ready to use Material Data). --- scripts/system/create/edit.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index 0de87e563c..ba410735e8 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -736,6 +736,9 @@ var toolBar = (function () { function handleNewMaterialDialogResult(result) { if (result) { var materialURL = result.textInput; + if (materialURL === "") { + materialURL = "materialData"; + } //var materialMappingMode; //switch (result.comboBox) { // case MATERIAL_MODE_PROJECTED: From 180742f790e53615fe69c7d62bfb4a898fb40242 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Thu, 10 Sep 2020 00:15:07 -0400 Subject: [PATCH 28/36] Clarify the "materialURL" tooltip Clarify the "materialURL" tooltip that was a bit obscure. New value: "The URL to an external JSON file or "materialData". Append "?" to select a single material if multiple are defined." --- scripts/system/create/assets/data/createAppTooltips.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index c247bc7cae..8e53823cd8 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -402,7 +402,7 @@ "tooltip": "Affects the size of the spotlight beam; the higher the value, the larger the beam." }, "materialURL": { - "tooltip": "The URL to an external JSON file or \"materialData\", \"materialData? to use Material Data." + "tooltip": "The URL to an external JSON file or \"materialData\". Append \"?\" to select a single material if multiple are defined." }, "materialData": { "tooltip": "Can be used instead of a JSON file when material set to materialData." From 8705873be56907df28f030774ffb089d784966bd Mon Sep 17 00:00:00 2001 From: kasenvr <52365539+kasenvr@users.noreply.github.com> Date: Thu, 10 Sep 2020 04:15:07 -0400 Subject: [PATCH 29/36] Update BUILD.md --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 61bc1cdd04..2d94d1b5b1 100644 --- a/BUILD.md +++ b/BUILD.md @@ -83,7 +83,7 @@ Where /path/to/directory is the path to a directory where you wish the build fil // The Interface will have a custom default home and startup location. INITIAL_STARTUP_LOCATION=Location/IP/URL - // Code-signing environment variables must be set at runtime AND globally when the signing takes place. + // Code-signing environment variables must be set during runtime of CMake AND globally when the signing takes place. HF_PFX_FILE=Path to certificate HF_PFX_PASSPHRASE=Passphrase for certificate From 8943032df8eb35b32ca240e71c4959dd9d86418f Mon Sep 17 00:00:00 2001 From: kasenvr <52365539+kasenvr@users.noreply.github.com> Date: Thu, 10 Sep 2020 04:16:03 -0400 Subject: [PATCH 30/36] Update INSTALL.md --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 4307ddc79e..994725ac28 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -65,7 +65,7 @@ To produce an executable installer on Windows, the following are required: ##### Code Signing (optional) -For code signing to work, you will need to set the `HF_PFX_FILE` and `HF_PFX_PASSPHRASE` environment variables globally. +For code signing to work, you will need to set the `HF_PFX_FILE` and `HF_PFX_PASSPHRASE` environment variables to be present during CMake runtime and globally as we proceed to package the installer. ##### Creating the Installer From 432090e2e9970d6c9eca33c83b5c5600f4b96c79 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 10 Sep 2020 21:01:04 +1200 Subject: [PATCH 31/36] Quiet warning for unused blendshapeCoefficients property --- libraries/entities/src/ModelEntityItem.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 38e7ad9c3a..cd27c1cf36 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -746,6 +746,10 @@ QString ModelEntityItem::getBlendshapeCoefficients() const { } void ModelEntityItem::setBlendshapeCoefficients(const QString& blendshapeCoefficients) { + if (blendshapeCoefficients.isEmpty()) { + return; + } + QJsonParseError error; QJsonDocument newCoefficientsJSON = QJsonDocument::fromJson(blendshapeCoefficients.toUtf8(), &error); if (error.error != QJsonParseError::NoError) { From 932a3b9e915341e581bb1a04a7236ae46e52ce74 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Mon, 14 Sep 2020 02:58:36 -0400 Subject: [PATCH 32/36] Update AudioClient.cpp Fix double locking attempt if waitForFinished causes prepareLocalAudioInjectors to be called on this thread. Co-Authored-By: Heather Anderson <1115056+odysseus654@users.noreply.github.com> --- libraries/audio-client/src/AudioClient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 4e8c88560b..8d96a2e6b5 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -2072,7 +2072,6 @@ bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDevi // NOTE: device start() uses the Qt internal device list Lock lock(_deviceMutex); - Lock localAudioLock(_localAudioMutex); _localSamplesAvailable.exchange(0, std::memory_order_release); //wait on local injectors prep to finish running @@ -2080,6 +2079,8 @@ bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDevi _localPrepInjectorFuture.waitForFinished(); } + Lock localAudioLock(_localAudioMutex); + // cleanup any previously initialized device if (_audioOutput) { _audioOutputIODevice.close(); From d6a49439b8efc2b2ad3163ed6a1fc2a6832f4623 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 15 Sep 2020 15:57:34 +1200 Subject: [PATCH 33/36] Fix "Serverless" capitalization in title bar --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d86745a8b9..c02ac4ceb3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7110,9 +7110,9 @@ void Application::updateWindowTitle() const { QString currentPlaceName; if (isServerlessMode()) { if (isInErrorState) { - currentPlaceName = "serverless: " + nodeList->getDomainHandler().getErrorDomainURL().toString(); + currentPlaceName = "Serverless: " + nodeList->getDomainHandler().getErrorDomainURL().toString(); } else { - currentPlaceName = "serverless: " + DependencyManager::get()->getDomainURL().toString(); + currentPlaceName = "Serverless: " + DependencyManager::get()->getDomainURL().toString(); } } else { currentPlaceName = DependencyManager::get()->getDomainURL().host(); From ec4d559055507d3ab616b6bb7e4004f757d374bd Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Tue, 15 Sep 2020 22:24:08 -0400 Subject: [PATCH 34/36] Added (Optional) to the label "Material URL" Added "(Optional)" to the label "Material URL" "Material URL (Optional)" --- scripts/system/create/qml/NewMaterialDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/qml/NewMaterialDialog.qml b/scripts/system/create/qml/NewMaterialDialog.qml index 1631632fb4..d3435fdade 100644 --- a/scripts/system/create/qml/NewMaterialDialog.qml +++ b/scripts/system/create/qml/NewMaterialDialog.qml @@ -54,7 +54,7 @@ Rectangle { Text { id: text1 - text: qsTr("Material URL") + text: qsTr("Material URL (Optional)") color: "#ffffff" font.pixelSize: 12 } From 1a0e69ed6ea11a03b90d9684072349b102fad964 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 16 Sep 2020 23:07:41 -0400 Subject: [PATCH 35/36] Change "Add" button for "Create" Change "Add" button for "Create" --- scripts/system/create/qml/NewMaterialDialog.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/create/qml/NewMaterialDialog.qml b/scripts/system/create/qml/NewMaterialDialog.qml index d3435fdade..3cc619e176 100644 --- a/scripts/system/create/qml/NewMaterialDialog.qml +++ b/scripts/system/create/qml/NewMaterialDialog.qml @@ -4,6 +4,7 @@ // // Created by Sam Gondelman on 1/17/18 // Copyright 2018 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -139,7 +140,7 @@ Rectangle { Button { id: button1 - text: qsTr("Add") + text: qsTr("Create") z: -1 onClicked: { newMaterialDialog.sendToScript({ From 6ca176335e9e6a54157185b2fa2213b3f1429c07 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 16 Sep 2020 23:15:07 -0400 Subject: [PATCH 36/36] Change "Add" button for "Create" Change "Add" button for "Create" --- scripts/system/create/qml/NewModelDialog.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/create/qml/NewModelDialog.qml b/scripts/system/create/qml/NewModelDialog.qml index 741902fa7f..dd4ef3c8ad 100644 --- a/scripts/system/create/qml/NewModelDialog.qml +++ b/scripts/system/create/qml/NewModelDialog.qml @@ -4,6 +4,7 @@ // // Created by Seth Alves on 2017-2-10 // Copyright 2017 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -208,7 +209,7 @@ Rectangle { Button { id: button1 - text: qsTr("Add") + text: qsTr("Create") z: -1 enabled: false onClicked: {