From cabe9eab81e2a2d5dba1295d65bfcab0d49d3ca0 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 30 May 2019 08:59:45 -0700 Subject: [PATCH 01/25] Allow local echo when audio input and output devices have different sample rates --- libraries/audio-client/src/AudioClient.cpp | 43 +++++++++++++++------- libraries/audio-client/src/AudioClient.h | 1 + 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index ef0e70a31d..ea84d54ecc 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -291,6 +291,7 @@ AudioClient::AudioClient() : _inputToNetworkResampler(NULL), _networkToOutputResampler(NULL), _localToOutputResampler(NULL), + _loopbackResampler(NULL), _audioLimiter(AudioConstants::SAMPLE_RATE, OUTPUT_CHANNEL_COUNT), _outgoingAvatarAudioSequenceNumber(0), _audioOutputIODevice(_localInjectorsStream, _receivedAudioStream, this), @@ -762,6 +763,11 @@ void AudioClient::stop() { qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down"; switchOutputToAudioDevice(QAudioDeviceInfo(), true); + if (_loopbackResampler) { + delete _loopbackResampler; + _loopbackResampler = NULL; + } + // Stop triggering the checks QObject::disconnect(_checkPeakValuesTimer, &QTimer::timeout, nullptr, nullptr); QObject::disconnect(_checkDevicesTimer, &QTimer::timeout, nullptr, nullptr); @@ -1085,13 +1091,6 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) { return; } - // NOTE: we assume the inputFormat and the outputFormat are the same, since on any modern - // multimedia OS they should be. If there is a device that this is not true for, we can - // add back support to do resampling. - if (_inputFormat.sampleRate() != _outputFormat.sampleRate()) { - return; - } - // if this person wants local loopback add that to the locally injected audio // if there is reverb apply it to local audio and substract the origin samples @@ -1108,21 +1107,30 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) { } } + // if required, create loopback resampler + if (_inputFormat.sampleRate() != _outputFormat.sampleRate() && !_loopbackResampler) { + qCDebug(audioclient) << "Resampling" << _inputFormat.sampleRate() << "to" << _outputFormat.sampleRate() << "for audio loopback."; + + int channelCount = (_inputFormat.channelCount() == 2 && _outputFormat.channelCount() == 2) ? 2 : 1; + _loopbackResampler = new AudioSRC(_inputFormat.sampleRate(), _outputFormat.sampleRate(), channelCount); + } + static QByteArray loopBackByteArray; int numInputSamples = inputByteArray.size() / AudioConstants::SAMPLE_SIZE; - int numLoopbackSamples = (numInputSamples * OUTPUT_CHANNEL_COUNT) / _inputFormat.channelCount(); + int numInputFrames = numInputSamples / _inputFormat.channelCount(); + int numLoopbackFrames = (numInputFrames * _outputFormat.sampleRate() + _inputFormat.sampleRate() - 1) / _inputFormat.sampleRate(); + int numLoopbackSamples = numLoopbackFrames * OUTPUT_CHANNEL_COUNT; loopBackByteArray.resize(numLoopbackSamples * AudioConstants::SAMPLE_SIZE); int16_t* inputSamples = reinterpret_cast(inputByteArray.data()); int16_t* loopbackSamples = reinterpret_cast(loopBackByteArray.data()); - // upmix mono to stereo - if (!sampleChannelConversion(inputSamples, loopbackSamples, numInputSamples, _inputFormat.channelCount(), OUTPUT_CHANNEL_COUNT)) { - // no conversion, just copy the samples - memcpy(loopbackSamples, inputSamples, numInputSamples * AudioConstants::SAMPLE_SIZE); - } + possibleResampling(_loopbackResampler, + inputSamples, loopbackSamples, + numInputSamples, numLoopbackSamples, + _inputFormat.channelCount(), OUTPUT_CHANNEL_COUNT); // apply stereo reverb at the source, to the loopback audio if (!_shouldEchoLocally && hasReverb) { @@ -1892,15 +1900,22 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI _outputDeviceInfo = QAudioDeviceInfo(); } + // cleanup any resamplers if (_networkToOutputResampler) { - // if we were using an input to network resampler, delete it here delete _networkToOutputResampler; _networkToOutputResampler = NULL; + } + if (_localToOutputResampler) { delete _localToOutputResampler; _localToOutputResampler = NULL; } + if (_loopbackResampler) { + delete _loopbackResampler; + _loopbackResampler = NULL; + } + if (isShutdownRequest) { qCDebug(audioclient) << "The audio output device has shut down."; return true; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index e209628689..decf0f7751 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -390,6 +390,7 @@ private: AudioSRC* _inputToNetworkResampler; AudioSRC* _networkToOutputResampler; AudioSRC* _localToOutputResampler; + AudioSRC* _loopbackResampler; // for network audio (used by network audio thread) int16_t _networkScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC]; From 0c916e0c03a9bead84bc74a0f949b98a12a05275 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 30 May 2019 16:08:47 -0700 Subject: [PATCH 02/25] guard MyAvatar::_scriptEngine with mutex --- interface/src/avatar/MyAvatar.cpp | 18 +++++++++++++----- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7ac2103543..b8042f1ce7 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1598,6 +1598,7 @@ void MyAvatar::handleChangedAvatarEntityData() { blobFailed = true; // blob doesn't exist return; } + std::lock_guard guard(_myScriptEngineLock); if (!EntityItemProperties::blobToProperties(*_myScriptEngine, itr.value(), properties)) { blobFailed = true; // blob is corrupt } @@ -1630,6 +1631,7 @@ void MyAvatar::handleChangedAvatarEntityData() { skip = true; return; } + std::lock_guard guard(_myScriptEngineLock); if (!EntityItemProperties::blobToProperties(*_myScriptEngine, itr.value(), properties)) { skip = true; } @@ -1737,7 +1739,10 @@ bool MyAvatar::updateStaleAvatarEntityBlobs() const { if (found) { ++numFound; QByteArray blob; - EntityItemProperties::propertiesToBlob(*_myScriptEngine, getID(), properties, blob); + { + std::lock_guard guard(_myScriptEngineLock); + EntityItemProperties::propertiesToBlob(*_myScriptEngine, getID(), properties, blob); + } _avatarEntitiesLock.withWriteLock([&] { _cachedAvatarEntityBlobs[id] = blob; }); @@ -2476,15 +2481,18 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() { if (!entity) { continue; } - QVariantMap avatarEntityData; EncodeBitstreamParams params; auto desiredProperties = entity->getEntityProperties(params); desiredProperties += PROP_LOCAL_POSITION; desiredProperties += PROP_LOCAL_ROTATION; - EntityItemProperties entityProperties = entity->getProperties(desiredProperties); - QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_myScriptEngine, entityProperties); + QVariantMap avatarEntityData; avatarEntityData["id"] = entityID; - avatarEntityData["properties"] = scriptProperties.toVariant(); + { + std::lock_guard guard(_myScriptEngineLock); + EntityItemProperties entityProperties = entity->getProperties(desiredProperties); + QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_myScriptEngine, entityProperties); + avatarEntityData["properties"] = scriptProperties.toVariant(); + } avatarEntitiesData.append(QVariant(avatarEntityData)); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 5b12885d1f..ee14ad1fda 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -2741,6 +2741,7 @@ private: mutable std::set _staleCachedAvatarEntityBlobs; // // keep a ScriptEngine around so we don't have to instantiate on the fly (these are very slow to create/delete) + mutable std::mutex _myScriptEngineLock; QScriptEngine* _myScriptEngine { nullptr }; bool _needToSaveAvatarEntitySettings { false }; }; From 4bcc81b49ba3c6ef30812068bfeceeb2cb3d4369 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 30 May 2019 17:56:40 -0700 Subject: [PATCH 03/25] Add logging for silent node kills --- libraries/networking/src/LimitedNodeList.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 563d6e7ad1..0eda2ee2e0 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -869,6 +869,8 @@ void LimitedNodeList::removeSilentNodes() { QSet killedNodes; + auto startedAt = usecTimestampNow(); + eachNodeHashIterator([&](NodeHash::iterator& it){ SharedNodePointer node = it->second; node->getMutex().lock(); @@ -889,7 +891,15 @@ void LimitedNodeList::removeSilentNodes() { }); foreach(const SharedNodePointer& killedNode, killedNodes) { - qCDebug(networking_ice) << "Removing silent node" << killedNode; + auto now = usecTimestampNow(); + qCDebug(networking_ice) << "Removing silent node" << *killedNode << "\n" + << " Now: " << now << "\n" + << " Started at: " << startedAt << " (" << (now - startedAt) << "us ago)\n" + << " Last Heard Microstamp: " << killedNode->getLastHeardMicrostamp() << " (" << (now - killedNode->getLastHeardMicrostamp()) << "us ago)\n" + << " Forced Never Silent: " << killedNode->isForcedNeverSilent() << "\n" + << " Inbound PPS: " << killedNode->getInboundPPS() << "\n" + << " Inbound Kbps: " << killedNode->getInboundKbps() << "\n" + << " Ping: " << killedNode->getPingMs(); handleNodeKill(killedNode); } } From 5f9262cf5e7263b2412b3b7d96aae21cf8731228 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 31 May 2019 11:03:11 -0700 Subject: [PATCH 04/25] change data member names to not poke other devs in the eye --- interface/src/avatar/MyAvatar.cpp | 24 ++++++++++++------------ interface/src/avatar/MyAvatar.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b8042f1ce7..613d7f81ef 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -325,8 +325,8 @@ MyAvatar::MyAvatar(QThread* thread) : MyAvatar::~MyAvatar() { _lookAtTargetAvatar.reset(); - delete _myScriptEngine; - _myScriptEngine = nullptr; + delete _scriptEngine; + _scriptEngine = nullptr; } QString MyAvatar::getDominantHand() const { @@ -1598,8 +1598,8 @@ void MyAvatar::handleChangedAvatarEntityData() { blobFailed = true; // blob doesn't exist return; } - std::lock_guard guard(_myScriptEngineLock); - if (!EntityItemProperties::blobToProperties(*_myScriptEngine, itr.value(), properties)) { + std::lock_guard guard(_scriptEngineLock); + if (!EntityItemProperties::blobToProperties(*_scriptEngine, itr.value(), properties)) { blobFailed = true; // blob is corrupt } }); @@ -1631,8 +1631,8 @@ void MyAvatar::handleChangedAvatarEntityData() { skip = true; return; } - std::lock_guard guard(_myScriptEngineLock); - if (!EntityItemProperties::blobToProperties(*_myScriptEngine, itr.value(), properties)) { + std::lock_guard guard(_scriptEngineLock); + if (!EntityItemProperties::blobToProperties(*_scriptEngine, itr.value(), properties)) { skip = true; } }); @@ -1740,8 +1740,8 @@ bool MyAvatar::updateStaleAvatarEntityBlobs() const { ++numFound; QByteArray blob; { - std::lock_guard guard(_myScriptEngineLock); - EntityItemProperties::propertiesToBlob(*_myScriptEngine, getID(), properties, blob); + std::lock_guard guard(_scriptEngineLock); + EntityItemProperties::propertiesToBlob(*_scriptEngine, getID(), properties, blob); } _avatarEntitiesLock.withWriteLock([&] { _cachedAvatarEntityBlobs[id] = blob; @@ -1888,8 +1888,8 @@ void MyAvatar::avatarEntityDataToJson(QJsonObject& root) const { } void MyAvatar::loadData() { - if (!_myScriptEngine) { - _myScriptEngine = new QScriptEngine(); + if (!_scriptEngine) { + _scriptEngine = new QScriptEngine(); } getHead()->setBasePitch(_headPitchSetting.get()); @@ -2488,9 +2488,9 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() { QVariantMap avatarEntityData; avatarEntityData["id"] = entityID; { - std::lock_guard guard(_myScriptEngineLock); + std::lock_guard guard(_scriptEngineLock); EntityItemProperties entityProperties = entity->getProperties(desiredProperties); - QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_myScriptEngine, entityProperties); + QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine, entityProperties); avatarEntityData["properties"] = scriptProperties.toVariant(); } avatarEntitiesData.append(QVariant(avatarEntityData)); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ee14ad1fda..058603f320 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -2741,8 +2741,8 @@ private: mutable std::set _staleCachedAvatarEntityBlobs; // // keep a ScriptEngine around so we don't have to instantiate on the fly (these are very slow to create/delete) - mutable std::mutex _myScriptEngineLock; - QScriptEngine* _myScriptEngine { nullptr }; + mutable std::mutex _scriptEngineLock; + QScriptEngine* _scriptEngine { nullptr }; bool _needToSaveAvatarEntitySettings { false }; }; From 297517c85d256041834a68aa56f430ac02703f94 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 31 May 2019 11:06:16 -0700 Subject: [PATCH 05/25] minimize lock duration --- interface/src/avatar/MyAvatar.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 613d7f81ef..ad39b6663a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2487,12 +2487,13 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() { desiredProperties += PROP_LOCAL_ROTATION; QVariantMap avatarEntityData; avatarEntityData["id"] = entityID; + EntityItemProperties entityProperties = entity->getProperties(desiredProperties); + QScriptValue scriptProperties; { std::lock_guard guard(_scriptEngineLock); - EntityItemProperties entityProperties = entity->getProperties(desiredProperties); - QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine, entityProperties); - avatarEntityData["properties"] = scriptProperties.toVariant(); + scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine, entityProperties); } + avatarEntityData["properties"] = scriptProperties.toVariant(); avatarEntitiesData.append(QVariant(avatarEntityData)); } } From 8e5c94abb0f17215753c0415f359d063789561fb Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 May 2019 11:08:51 -0700 Subject: [PATCH 06/25] BUGZ-447: New performance preset API --- .../settingsApp/general/General.qml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml index e32890a2dd..76aa35d4ea 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml @@ -101,7 +101,7 @@ Flickable { HifiStylesUit.GraphikRegular { id: performanceTitle - text: "Performance" + text: "Graphics Preset" Layout.maximumWidth: parent.width height: paintedHeight size: 22 @@ -115,28 +115,28 @@ Flickable { SimplifiedControls.RadioButton { id: performanceLow - text: "Eco" - checked: Performance.getRefreshRateProfile() === RefreshRate.ECO + text: "Low" + checked: Performance.getPerformancePreset() === PerformacePreset.LOW onClicked: { - Performance.setRefreshRateProfile(RefreshRate.ECO); + Performance.setPerformancePreset(PerformacePreset.LOW); } } SimplifiedControls.RadioButton { id: performanceMedium - text: "Interactive" - checked: Performance.getRefreshRateProfile() === RefreshRate.INTERACTIVE + text: "Medium" + checked: Performance.getPerformancePreset() === PerformacePreset.MID onClicked: { - Performance.setRefreshRateProfile(RefreshRate.INTERACTIVE); + Performance.setPerformancePreset(PerformacePreset.MID); } } SimplifiedControls.RadioButton { id: performanceHigh - text: "Realtime" - checked: Performance.getRefreshRateProfile() === RefreshRate.REALTIME + text: "High" + checked: Performance.getPerformancePreset() === PerformacePreset.HIGH onClicked: { - Performance.setRefreshRateProfile(RefreshRate.REALTIME); + Performance.setPerformancePreset(PerformacePreset.HIGH); } } } From fa79d0ec18c198f52b03cfb18dd4724d699db79a Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Fri, 31 May 2019 11:36:26 -0700 Subject: [PATCH 07/25] Fix Application not checking window minimize state properly --- interface/src/Application.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae226598d1..6232821489 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4155,8 +4155,14 @@ bool Application::eventFilter(QObject* object, QEvent* event) { } if (event->type() == QEvent::WindowStateChange) { - if (getWindow()->windowState() == Qt::WindowMinimized) { + if (getWindow()->windowState() & Qt::WindowMinimized) { getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::MINIMIZED); + } else { + auto* windowStateChangeEvent = static_cast(event); + if (windowStateChangeEvent->oldState() & Qt::WindowMinimized) { + getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::FOCUS_ACTIVE); + getRefreshRateManager().resetInactiveTimer(); + } } } From b9b320d01c89ac2dca1726e0f95d0c8f74437b7f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 May 2019 11:43:13 -0700 Subject: [PATCH 08/25] DEV-92: Add a Home button to the Avatar app --- .../hifi/simplifiedUI/avatarApp/AvatarApp.qml | 21 +++++++++++++++++++ .../avatarApp/images/homeIcon.svg | 4 ++++ 2 files changed, 25 insertions(+) create mode 100644 interface/resources/qml/hifi/simplifiedUI/avatarApp/images/homeIcon.svg diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml index d6ee593edd..b7186b885c 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml @@ -99,6 +99,27 @@ Rectangle { } } + Image { + id: homeButton + source: "images/homeIcon.svg" + opacity: homeButtonMouseArea.containsMouse ? 1.0 : 0.7 + anchors.top: parent.top + anchors.topMargin: 15 + anchors.right: parent.right + anchors.rightMargin: 24 + width: 14 + height: 13 + + MouseArea { + id: homeButtonMouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: { + Window.location = LocationBookmarks.getHomeLocationAddress(); + } + } + } + AvatarAppComponents.DisplayNameHeader { id: displayNameHeader previewUrl: root.avatarPreviewUrl diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/images/homeIcon.svg b/interface/resources/qml/hifi/simplifiedUI/avatarApp/images/homeIcon.svg new file mode 100644 index 0000000000..1aae14e2dd --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/images/homeIcon.svg @@ -0,0 +1,4 @@ + + + + From 25725bb91e6dd64101a9f533a48029dc2855e27d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 May 2019 11:46:13 -0700 Subject: [PATCH 09/25] Change 'your avatars' to 'your profile' --- scripts/simplifiedUI/ui/simplifiedUI.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index a6183c5ab9..38d1059da7 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -98,7 +98,7 @@ function onAvatarAppClosed() { var AVATAR_APP_QML_PATH = Script.resourcesPath() + "qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml"; -var AVATAR_APP_WINDOW_TITLE = "Your Avatars"; +var AVATAR_APP_WINDOW_TITLE = "Your Profile"; var AVATAR_APP_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE; var AVATAR_APP_WIDTH_PX = 480; var AVATAR_APP_HEIGHT_PX = 615; From f4a7b2704295a608c2c91bfd094f49a808e60768 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 30 May 2019 17:26:06 -0700 Subject: [PATCH 10/25] cleaning up name lookups --- .../entities/src/EntityItemProperties.cpp | 475 +++++++----------- libraries/entities/src/EntityItemProperties.h | 9 - libraries/shared/src/ComponentMode.cpp | 37 ++ libraries/shared/src/ComponentMode.h | 20 + 4 files changed, 244 insertions(+), 297 deletions(-) create mode 100644 libraries/shared/src/ComponentMode.cpp diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ce4387a006..e5205e86e8 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -104,41 +104,199 @@ bool EntityItemProperties::constructFromBuffer(const unsigned char* data, int da return true; } -QHash stringToShapeTypeLookup; - -void addShapeType(ShapeType type) { - stringToShapeTypeLookup[ShapeInfo::getNameForShapeType(type)] = type; +inline void addShapeType(QHash& lookup, ShapeType type) { lookup[ShapeInfo::getNameForShapeType(type)] = type; } +QHash stringToShapeTypeLookup = [] { + QHash toReturn; + addShapeType(toReturn, SHAPE_TYPE_NONE); + addShapeType(toReturn, SHAPE_TYPE_BOX); + addShapeType(toReturn, SHAPE_TYPE_SPHERE); + addShapeType(toReturn, SHAPE_TYPE_CAPSULE_X); + addShapeType(toReturn, SHAPE_TYPE_CAPSULE_Y); + addShapeType(toReturn, SHAPE_TYPE_CAPSULE_Z); + addShapeType(toReturn, SHAPE_TYPE_CYLINDER_X); + addShapeType(toReturn, SHAPE_TYPE_CYLINDER_Y); + addShapeType(toReturn, SHAPE_TYPE_CYLINDER_Z); + addShapeType(toReturn, SHAPE_TYPE_HULL); + addShapeType(toReturn, SHAPE_TYPE_PLANE); + addShapeType(toReturn, SHAPE_TYPE_COMPOUND); + addShapeType(toReturn, SHAPE_TYPE_SIMPLE_HULL); + addShapeType(toReturn, SHAPE_TYPE_SIMPLE_COMPOUND); + addShapeType(toReturn, SHAPE_TYPE_STATIC_MESH); + addShapeType(toReturn, SHAPE_TYPE_ELLIPSOID); + addShapeType(toReturn, SHAPE_TYPE_CIRCLE); + return toReturn; +}(); +QString EntityItemProperties::getShapeTypeAsString() const { return ShapeInfo::getNameForShapeType(_shapeType); } +void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) { + auto shapeTypeItr = stringToShapeTypeLookup.find(shapeName.toLower()); + if (shapeTypeItr != stringToShapeTypeLookup.end()) { + _shapeType = shapeTypeItr.value(); + _shapeTypeChanged = true; + } } -void buildStringToShapeTypeLookup() { - addShapeType(SHAPE_TYPE_NONE); - addShapeType(SHAPE_TYPE_BOX); - addShapeType(SHAPE_TYPE_SPHERE); - addShapeType(SHAPE_TYPE_CAPSULE_X); - addShapeType(SHAPE_TYPE_CAPSULE_Y); - addShapeType(SHAPE_TYPE_CAPSULE_Z); - addShapeType(SHAPE_TYPE_CYLINDER_X); - addShapeType(SHAPE_TYPE_CYLINDER_Y); - addShapeType(SHAPE_TYPE_CYLINDER_Z); - addShapeType(SHAPE_TYPE_HULL); - addShapeType(SHAPE_TYPE_PLANE); - addShapeType(SHAPE_TYPE_COMPOUND); - addShapeType(SHAPE_TYPE_SIMPLE_HULL); - addShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); - addShapeType(SHAPE_TYPE_STATIC_MESH); - addShapeType(SHAPE_TYPE_ELLIPSOID); - addShapeType(SHAPE_TYPE_CIRCLE); +inline void addMaterialMappingMode(QHash& lookup, MaterialMappingMode mode) { lookup[MaterialMappingModeHelpers::getNameForMaterialMappingMode(mode)] = mode; } +const QHash stringToMaterialMappingModeLookup = [] { + QHash toReturn; + addMaterialMappingMode(toReturn, UV); + addMaterialMappingMode(toReturn, PROJECTED); + return toReturn; +}(); +QString EntityItemProperties::getMaterialMappingModeAsString() const { return MaterialMappingModeHelpers::getNameForMaterialMappingMode(_materialMappingMode); } +void EntityItemProperties::setMaterialMappingModeFromString(const QString& materialMappingMode) { + auto materialMappingModeItr = stringToMaterialMappingModeLookup.find(materialMappingMode.toLower()); + if (materialMappingModeItr != stringToMaterialMappingModeLookup.end()) { + _materialMappingMode = materialMappingModeItr.value(); + _materialMappingModeChanged = true; + } } -QHash stringToMaterialMappingModeLookup; - -void addMaterialMappingMode(MaterialMappingMode mode) { - stringToMaterialMappingModeLookup[MaterialMappingModeHelpers::getNameForMaterialMappingMode(mode)] = mode; +inline void addBillboardMode(QHash& lookup, BillboardMode mode) { lookup[BillboardModeHelpers::getNameForBillboardMode(mode)] = mode; } +const QHash stringToBillboardModeLookup = [] { + QHash toReturn; + addBillboardMode(toReturn, BillboardMode::NONE); + addBillboardMode(toReturn, BillboardMode::YAW); + addBillboardMode(toReturn, BillboardMode::FULL); + return toReturn; +}(); +QString EntityItemProperties::getBillboardModeAsString() const { return BillboardModeHelpers::getNameForBillboardMode(_billboardMode); } +void EntityItemProperties::setBillboardModeFromString(const QString& billboardMode) { + auto billboardModeItr = stringToBillboardModeLookup.find(billboardMode.toLower()); + if (billboardModeItr != stringToBillboardModeLookup.end()) { + _billboardMode = billboardModeItr.value(); + _billboardModeChanged = true; + } } -void buildStringToMaterialMappingModeLookup() { - addMaterialMappingMode(UV); - addMaterialMappingMode(PROJECTED); +inline void addRenderLayer(QHash& lookup, RenderLayer mode) { lookup[RenderLayerHelpers::getNameForRenderLayer(mode)] = mode; } +const QHash stringToRenderLayerLookup = [] { + QHash toReturn; + addRenderLayer(toReturn, RenderLayer::WORLD); + addRenderLayer(toReturn, RenderLayer::FRONT); + addRenderLayer(toReturn, RenderLayer::HUD); + return toReturn; +}(); +QString EntityItemProperties::getRenderLayerAsString() const { return RenderLayerHelpers::getNameForRenderLayer(_renderLayer); } +void EntityItemProperties::setRenderLayerFromString(const QString& renderLayer) { + auto renderLayerItr = stringToRenderLayerLookup.find(renderLayer.toLower()); + if (renderLayerItr != stringToRenderLayerLookup.end()) { + _renderLayer = renderLayerItr.value(); + _renderLayerChanged = true; + } +} + +inline void addPrimitiveMode(QHash& lookup, PrimitiveMode mode) { lookup[PrimitiveModeHelpers::getNameForPrimitiveMode(mode)] = mode; } +const QHash stringToPrimitiveModeLookup = [] { + QHash toReturn; + addPrimitiveMode(toReturn, PrimitiveMode::SOLID); + addPrimitiveMode(toReturn, PrimitiveMode::LINES); + return toReturn; +}(); +QString EntityItemProperties::getPrimitiveModeAsString() const { return PrimitiveModeHelpers::getNameForPrimitiveMode(_primitiveMode); } +void EntityItemProperties::setPrimitiveModeFromString(const QString& primitiveMode) { + auto primitiveModeItr = stringToPrimitiveModeLookup.find(primitiveMode.toLower()); + if (primitiveModeItr != stringToPrimitiveModeLookup.end()) { + _primitiveMode = primitiveModeItr.value(); + _primitiveModeChanged = true; + } +} + +inline void addWebInputMode(QHash& lookup, WebInputMode mode) { lookup[WebInputModeHelpers::getNameForWebInputMode(mode)] = mode; } +const QHash stringToWebInputModeLookup = [] { + QHash toReturn; + addWebInputMode(toReturn, WebInputMode::TOUCH); + addWebInputMode(toReturn, WebInputMode::MOUSE); + return toReturn; +}(); +QString EntityItemProperties::getInputModeAsString() const { return WebInputModeHelpers::getNameForWebInputMode(_inputMode); } +void EntityItemProperties::setInputModeFromString(const QString& webInputMode) { + auto webInputModeItr = stringToWebInputModeLookup.find(webInputMode.toLower()); + if (webInputModeItr != stringToWebInputModeLookup.end()) { + _inputMode = webInputModeItr.value(); + _inputModeChanged = true; + } +} + +inline void addGizmoType(QHash& lookup, GizmoType mode) { lookup[GizmoTypeHelpers::getNameForGizmoType(mode)] = mode; } +const QHash stringToGizmoTypeLookup = [] { + QHash toReturn; + addGizmoType(toReturn, GizmoType::RING); + return toReturn; +}(); +QString EntityItemProperties::getGizmoTypeAsString() const { return GizmoTypeHelpers::getNameForGizmoType(_gizmoType); } +void EntityItemProperties::setGizmoTypeFromString(const QString& gizmoType) { + auto gizmoTypeItr = stringToGizmoTypeLookup.find(gizmoType.toLower()); + if (gizmoTypeItr != stringToGizmoTypeLookup.end()) { + _gizmoType = gizmoTypeItr.value(); + _gizmoTypeChanged = true; + } +} + +inline void addComponentMode(QHash& lookup, ComponentMode mode) { lookup[ComponentModeHelpers::getNameForComponentMode(mode)] = mode; } +const QHash stringToComponentMode = [] { + QHash toReturn; + addComponentMode(toReturn, ComponentMode::COMPONENT_MODE_INHERIT); + addComponentMode(toReturn, ComponentMode::COMPONENT_MODE_DISABLED); + addComponentMode(toReturn, ComponentMode::COMPONENT_MODE_ENABLED); + return toReturn; +}(); +QString EntityItemProperties::getComponentModeAsString(uint32_t mode) { return ComponentModeHelpers::getNameForComponentMode((ComponentMode)mode); } +QString EntityItemProperties::getSkyboxModeAsString() const { return getComponentModeAsString(_skyboxMode); } +QString EntityItemProperties::getKeyLightModeAsString() const { return getComponentModeAsString(_keyLightMode); } +QString EntityItemProperties::getAmbientLightModeAsString() const { return getComponentModeAsString(_ambientLightMode); } +QString EntityItemProperties::getHazeModeAsString() const { return getComponentModeAsString(_hazeMode); } +QString EntityItemProperties::getBloomModeAsString() const { return getComponentModeAsString(_bloomMode); } +void EntityItemProperties::setSkyboxModeFromString(const QString& mode) { + auto modeItr = stringToComponentMode.find(mode.toLower()); + if (modeItr != stringToComponentMode.end()) { + _skyboxMode = modeItr.value(); + _skyboxModeChanged = true; + } +} +void EntityItemProperties::setKeyLightModeFromString(const QString& mode) { + auto modeItr = stringToComponentMode.find(mode.toLower()); + if (modeItr != stringToComponentMode.end()) { + _keyLightMode = modeItr.value(); + _keyLightModeChanged = true; + } +} +void EntityItemProperties::setAmbientLightModeFromString(const QString& mode) { + auto modeItr = stringToComponentMode.find(mode.toLower()); + if (modeItr != stringToComponentMode.end()) { + _ambientLightMode = modeItr.value(); + _ambientLightModeChanged = true; + } +} +void EntityItemProperties::setHazeModeFromString(const QString& mode) { + auto modeItr = stringToComponentMode.find(mode.toLower()); + if (modeItr != stringToComponentMode.end()) { + _hazeMode = modeItr.value(); + _hazeModeChanged = true; + } +} +void EntityItemProperties::setBloomModeFromString(const QString& mode) { + auto modeItr = stringToComponentMode.find(mode.toLower()); + if (modeItr != stringToComponentMode.end()) { + _bloomMode = modeItr.value(); + _bloomModeChanged = true; + } +} + +inline void addAvatarPriorityMode(QHash& lookup, AvatarPriorityMode mode) { lookup[AvatarPriorityModeHelpers::getNameForAvatarPriorityMode(mode)] = mode; } +const QHash stringToAvatarPriority = [] { + QHash toReturn; + addAvatarPriorityMode(toReturn, AvatarPriorityMode::AVATAR_PRIORITY_INHERIT); + addAvatarPriorityMode(toReturn, AvatarPriorityMode::AVATAR_PRIORITY_CROWD); + addAvatarPriorityMode(toReturn, AvatarPriorityMode::AVATAR_PRIORITY_HERO); + return toReturn; +}(); +QString EntityItemProperties::getAvatarPriorityAsString() const { return AvatarPriorityModeHelpers::getNameForAvatarPriorityMode((AvatarPriorityMode)_avatarPriority); } +void EntityItemProperties::setAvatarPriorityFromString(const QString& mode) { + auto modeItr = stringToAvatarPriority.find(mode.toLower()); + if (modeItr != stringToAvatarPriority.end()) { + _avatarPriority = modeItr.value(); + _avatarPriorityChanged = true; + } } QString getCollisionGroupAsString(uint16_t group) { @@ -194,134 +352,6 @@ void EntityItemProperties::setCollisionMaskFromString(const QString& maskString) _collisionMaskChanged = true; } -QString EntityItemProperties::getShapeTypeAsString() const { - return ShapeInfo::getNameForShapeType(_shapeType); -} - -void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) { - if (stringToShapeTypeLookup.empty()) { - buildStringToShapeTypeLookup(); - } - auto shapeTypeItr = stringToShapeTypeLookup.find(shapeName.toLower()); - if (shapeTypeItr != stringToShapeTypeLookup.end()) { - _shapeType = shapeTypeItr.value(); - _shapeTypeChanged = true; - } -} - -QString EntityItemProperties::getComponentModeAsString(uint32_t mode) { - // return "inherit" if mode is not valid - if (mode < COMPONENT_MODE_ITEM_COUNT) { - return COMPONENT_MODES[mode].second; - } else { - return COMPONENT_MODES[COMPONENT_MODE_INHERIT].second; - } -} - -QString EntityItemProperties::getHazeModeAsString() const { - return getComponentModeAsString(_hazeMode); -} - -QString EntityItemProperties::getBloomModeAsString() const { - return getComponentModeAsString(_bloomMode); -} - -namespace { - const QStringList AVATAR_PRIORITIES_AS_STRING - { "inherit", "crowd", "hero" }; -} - -QString EntityItemProperties::getAvatarPriorityAsString() const { - return AVATAR_PRIORITIES_AS_STRING.value(_avatarPriority); -} - -std::array::const_iterator EntityItemProperties::findComponent(const QString& mode) { - return std::find_if(COMPONENT_MODES.begin(), COMPONENT_MODES.end(), [&](const ComponentPair& pair) { - return (pair.second == mode); - }); -} - -void EntityItemProperties::setHazeModeFromString(const QString& hazeMode) { - auto result = findComponent(hazeMode); - - if (result != COMPONENT_MODES.end()) { - _hazeMode = result->first; - _hazeModeChanged = true; - } -} - -void EntityItemProperties::setBloomModeFromString(const QString& bloomMode) { - auto result = findComponent(bloomMode); - - if (result != COMPONENT_MODES.end()) { - _bloomMode = result->first; - _bloomModeChanged = true; - } -} - -void EntityItemProperties::setAvatarPriorityFromString(QString const& avatarPriority) { - auto result = AVATAR_PRIORITIES_AS_STRING.indexOf(avatarPriority); - - if (result != -1) { - _avatarPriority = result; - _avatarPriorityChanged = true; - } -} - -QString EntityItemProperties::getKeyLightModeAsString() const { - return getComponentModeAsString(_keyLightMode); -} - -void EntityItemProperties::setKeyLightModeFromString(const QString& keyLightMode) { - auto result = findComponent(keyLightMode); - - if (result != COMPONENT_MODES.end()) { - _keyLightMode = result->first; - _keyLightModeChanged = true; - } -} - -QString EntityItemProperties::getAmbientLightModeAsString() const { - return getComponentModeAsString(_ambientLightMode); -} - -void EntityItemProperties::setAmbientLightModeFromString(const QString& ambientLightMode) { - auto result = findComponent(ambientLightMode); - - if (result != COMPONENT_MODES.end()) { - _ambientLightMode = result->first; - _ambientLightModeChanged = true; - } -} - -QString EntityItemProperties::getSkyboxModeAsString() const { - return getComponentModeAsString(_skyboxMode); -} - -void EntityItemProperties::setSkyboxModeFromString(const QString& skyboxMode) { - auto result = findComponent(skyboxMode); - - if (result != COMPONENT_MODES.end()) { - _skyboxMode = result->first; - _skyboxModeChanged = true; - } -} - -QString EntityItemProperties::getMaterialMappingModeAsString() const { - return MaterialMappingModeHelpers::getNameForMaterialMappingMode(_materialMappingMode); -} - -void EntityItemProperties::setMaterialMappingModeFromString(const QString& materialMappingMode) { - if (stringToMaterialMappingModeLookup.empty()) { - buildStringToMaterialMappingModeLookup(); - } - auto materialMappingModeItr = stringToMaterialMappingModeLookup.find(materialMappingMode.toLower()); - if (materialMappingModeItr != stringToMaterialMappingModeLookup.end()) { - _materialMappingMode = materialMappingModeItr.value(); - _materialMappingModeChanged = true; - } -} - QString EntityItemProperties::getEntityHostTypeAsString() const { switch (_entityHostType) { case entity::HostType::DOMAIN: @@ -345,137 +375,6 @@ void EntityItemProperties::setEntityHostTypeFromString(const QString& entityHost } } -QHash stringToBillboardModeLookup; - -void addBillboardMode(BillboardMode mode) { - stringToBillboardModeLookup[BillboardModeHelpers::getNameForBillboardMode(mode)] = mode; -} - -void buildStringToBillboardModeLookup() { - addBillboardMode(BillboardMode::NONE); - addBillboardMode(BillboardMode::YAW); - addBillboardMode(BillboardMode::FULL); -} - -QString EntityItemProperties::getBillboardModeAsString() const { - return BillboardModeHelpers::getNameForBillboardMode(_billboardMode); -} - -void EntityItemProperties::setBillboardModeFromString(const QString& billboardMode) { - if (stringToBillboardModeLookup.empty()) { - buildStringToBillboardModeLookup(); - } - auto billboardModeItr = stringToBillboardModeLookup.find(billboardMode.toLower()); - if (billboardModeItr != stringToBillboardModeLookup.end()) { - _billboardMode = billboardModeItr.value(); - _billboardModeChanged = true; - } -} - -QHash stringToRenderLayerLookup; - -void addRenderLayer(RenderLayer mode) { - stringToRenderLayerLookup[RenderLayerHelpers::getNameForRenderLayer(mode)] = mode; -} - -void buildStringToRenderLayerLookup() { - addRenderLayer(RenderLayer::WORLD); - addRenderLayer(RenderLayer::FRONT); - addRenderLayer(RenderLayer::HUD); -} - -QString EntityItemProperties::getRenderLayerAsString() const { - return RenderLayerHelpers::getNameForRenderLayer(_renderLayer); -} - -void EntityItemProperties::setRenderLayerFromString(const QString& renderLayer) { - if (stringToRenderLayerLookup.empty()) { - buildStringToRenderLayerLookup(); - } - auto renderLayerItr = stringToRenderLayerLookup.find(renderLayer.toLower()); - if (renderLayerItr != stringToRenderLayerLookup.end()) { - _renderLayer = renderLayerItr.value(); - _renderLayerChanged = true; - } -} - -QHash stringToPrimitiveModeLookup; - -void addPrimitiveMode(PrimitiveMode mode) { - stringToPrimitiveModeLookup[PrimitiveModeHelpers::getNameForPrimitiveMode(mode)] = mode; -} - -void buildStringToPrimitiveModeLookup() { - addPrimitiveMode(PrimitiveMode::SOLID); - addPrimitiveMode(PrimitiveMode::LINES); -} - -QString EntityItemProperties::getPrimitiveModeAsString() const { - return PrimitiveModeHelpers::getNameForPrimitiveMode(_primitiveMode); -} - -void EntityItemProperties::setPrimitiveModeFromString(const QString& primitiveMode) { - if (stringToPrimitiveModeLookup.empty()) { - buildStringToPrimitiveModeLookup(); - } - auto primitiveModeItr = stringToPrimitiveModeLookup.find(primitiveMode.toLower()); - if (primitiveModeItr != stringToPrimitiveModeLookup.end()) { - _primitiveMode = primitiveModeItr.value(); - _primitiveModeChanged = true; - } -} - -QHash stringToWebInputModeLookup; - -void addWebInputMode(WebInputMode mode) { - stringToWebInputModeLookup[WebInputModeHelpers::getNameForWebInputMode(mode)] = mode; -} - -void buildStringToWebInputModeLookup() { - addWebInputMode(WebInputMode::TOUCH); - addWebInputMode(WebInputMode::MOUSE); -} - -QString EntityItemProperties::getInputModeAsString() const { - return WebInputModeHelpers::getNameForWebInputMode(_inputMode); -} - -void EntityItemProperties::setInputModeFromString(const QString& webInputMode) { - if (stringToWebInputModeLookup.empty()) { - buildStringToWebInputModeLookup(); - } - auto webInputModeItr = stringToWebInputModeLookup.find(webInputMode.toLower()); - if (webInputModeItr != stringToWebInputModeLookup.end()) { - _inputMode = webInputModeItr.value(); - _inputModeChanged = true; - } -} - -QHash stringToGizmoTypeLookup; - -void addGizmoType(GizmoType mode) { - stringToGizmoTypeLookup[GizmoTypeHelpers::getNameForGizmoType(mode)] = mode; -} - -void buildStringToGizmoTypeLookup() { - addGizmoType(GizmoType::RING); -} - -QString EntityItemProperties::getGizmoTypeAsString() const { - return GizmoTypeHelpers::getNameForGizmoType(_gizmoType); -} - -void EntityItemProperties::setGizmoTypeFromString(const QString& gizmoType) { - if (stringToGizmoTypeLookup.empty()) { - buildStringToGizmoTypeLookup(); - } - auto gizmoTypeItr = stringToGizmoTypeLookup.find(gizmoType.toLower()); - if (gizmoTypeItr != stringToGizmoTypeLookup.end()) { - _gizmoType = gizmoTypeItr.value(); - _gizmoTypeChanged = true; - } -} - EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index af945a89de..619af97ee5 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -67,13 +67,6 @@ const quint64 UNKNOWN_CREATED_TIME = 0; -using ComponentPair = std::pair; -const std::array COMPONENT_MODES = { { - ComponentPair { COMPONENT_MODE_INHERIT, { "inherit" } }, - ComponentPair { COMPONENT_MODE_DISABLED, { "disabled" } }, - ComponentPair { COMPONENT_MODE_ENABLED, { "enabled" } } -} }; - using vec3Color = glm::vec3; using u8vec3Color = glm::u8vec3; @@ -400,8 +393,6 @@ public: static QString getComponentModeAsString(uint32_t mode); - std::array::const_iterator findComponent(const QString& mode); - public: float getMaxDimension() const { return glm::compMax(_dimensions); } diff --git a/libraries/shared/src/ComponentMode.cpp b/libraries/shared/src/ComponentMode.cpp new file mode 100644 index 0000000000..5b3a42e9ae --- /dev/null +++ b/libraries/shared/src/ComponentMode.cpp @@ -0,0 +1,37 @@ +// +// Created by Sam Gondelman on 5/31/19 +// Copyright 2019 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 "ComponentMode.h" + +const char* componentModeNames[] = { + "inherit", + "disabled", + "enabled" +}; + +QString ComponentModeHelpers::getNameForComponentMode(ComponentMode mode) { + if (((int)mode <= 0) || ((int)mode >= (int)COMPONENT_MODE_ITEM_COUNT)) { + mode = (ComponentMode)0; + } + + return componentModeNames[(int)mode]; +} + +const char* avatarPriorityModeNames[] = { + "inherit", + "crowd", + "hero" +}; + +QString AvatarPriorityModeHelpers::getNameForAvatarPriorityMode(AvatarPriorityMode mode) { + if (((int)mode <= 0) || ((int)mode >= (int)AVATAR_PRIORITY_ITEM_COUNT)) { + mode = (AvatarPriorityMode)0; + } + + return avatarPriorityModeNames[(int)mode]; +} \ No newline at end of file diff --git a/libraries/shared/src/ComponentMode.h b/libraries/shared/src/ComponentMode.h index 03721c6a45..f1d030cefd 100644 --- a/libraries/shared/src/ComponentMode.h +++ b/libraries/shared/src/ComponentMode.h @@ -12,6 +12,8 @@ #ifndef hifi_ComponentMode_h #define hifi_ComponentMode_h +#include + enum ComponentMode { COMPONENT_MODE_INHERIT, COMPONENT_MODE_DISABLED, @@ -20,5 +22,23 @@ enum ComponentMode { COMPONENT_MODE_ITEM_COUNT }; +enum AvatarPriorityMode { + AVATAR_PRIORITY_INHERIT, + AVATAR_PRIORITY_CROWD, + AVATAR_PRIORITY_HERO, + + AVATAR_PRIORITY_ITEM_COUNT +}; + +class ComponentModeHelpers { +public: + static QString getNameForComponentMode(ComponentMode mode); +}; + +class AvatarPriorityModeHelpers { +public: + static QString getNameForAvatarPriorityMode(AvatarPriorityMode mode); +}; + #endif // hifi_ComponentMode_h From 8b085c79addbf051e78600df137a676b14716c4a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 May 2019 12:36:28 -0700 Subject: [PATCH 11/25] Can't use window.location in QML --- .../resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml index b7186b885c..66bbc99ad4 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml @@ -115,7 +115,9 @@ Rectangle { anchors.fill: parent hoverEnabled: true onClicked: { - Window.location = LocationBookmarks.getHomeLocationAddress(); + // Can't use `Window.location` in QML, so just use what setting `Window.location` actually calls under the hood: + // AddressManager.handleLookupString(). + AddressManager.handleLookupString(LocationBookmarks.getHomeLocationAddress()); } } } From 7b04a6d361e78f0f0b27eb509f84db7fd555d03b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 May 2019 12:37:35 -0700 Subject: [PATCH 12/25] Sounds --- .../resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml index 66bbc99ad4..4c6615ebdc 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/AvatarApp.qml @@ -12,6 +12,7 @@ import QtQuick 2.10 import "../simplifiedConstants" as SimplifiedConstants import "./components" as AvatarAppComponents import stylesUit 1.0 as HifiStylesUit +import TabletScriptingInterface 1.0 import "qrc:////qml//hifi//models" as HifiModels // Absolute path so the same code works everywhere. Rectangle { @@ -114,7 +115,11 @@ Rectangle { id: homeButtonMouseArea anchors.fill: parent hoverEnabled: true + onEntered: { + Tablet.playSound(TabletEnums.ButtonHover); + } onClicked: { + Tablet.playSound(TabletEnums.ButtonClick); // Can't use `Window.location` in QML, so just use what setting `Window.location` actually calls under the hood: // AddressManager.handleLookupString(). AddressManager.handleLookupString(LocationBookmarks.getHomeLocationAddress()); From 97bd0d5413ad57e3393e6a1d8f2a06b7bb07d41e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 May 2019 12:50:32 -0700 Subject: [PATCH 13/25] Make this work! --- .../simplifiedUI/settingsApp/general/General.qml | 12 ++++++------ .../src/scripting/PerformanceScriptingInterface.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml index 76aa35d4ea..9c3a33412e 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml @@ -116,27 +116,27 @@ Flickable { SimplifiedControls.RadioButton { id: performanceLow text: "Low" - checked: Performance.getPerformancePreset() === PerformacePreset.LOW + checked: Performance.getPerformancePreset() === PerformanceEnums.LOW onClicked: { - Performance.setPerformancePreset(PerformacePreset.LOW); + Performance.setPerformancePreset(PerformanceEnums.LOW); } } SimplifiedControls.RadioButton { id: performanceMedium text: "Medium" - checked: Performance.getPerformancePreset() === PerformacePreset.MID + checked: Performance.getPerformancePreset() === PerformanceEnums.MID onClicked: { - Performance.setPerformancePreset(PerformacePreset.MID); + Performance.setPerformancePreset(PerformanceEnums.MID); } } SimplifiedControls.RadioButton { id: performanceHigh text: "High" - checked: Performance.getPerformancePreset() === PerformacePreset.HIGH + checked: Performance.getPerformancePreset() === PerformanceEnums.HIGH onClicked: { - Performance.setPerformancePreset(PerformacePreset.HIGH); + Performance.setPerformancePreset(PerformanceEnums.HIGH); } } } diff --git a/interface/src/scripting/PerformanceScriptingInterface.cpp b/interface/src/scripting/PerformanceScriptingInterface.cpp index 4f7c2b0fda..d47404a601 100644 --- a/interface/src/scripting/PerformanceScriptingInterface.cpp +++ b/interface/src/scripting/PerformanceScriptingInterface.cpp @@ -15,7 +15,7 @@ std::once_flag PerformanceScriptingInterface::registry_flag; PerformanceScriptingInterface::PerformanceScriptingInterface() { std::call_once(registry_flag, [] { - qmlRegisterType("PerformanceEnums", 1, 0, "RefreshRate"); + qmlRegisterType("PerformanceEnums", 1, 0, "PerformanceEnums"); }); } From e29bf376a488606063180be902b0dbcbc83c7d88 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 31 May 2019 14:01:58 -0700 Subject: [PATCH 14/25] fix address manager crash --- interface/src/Application.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae226598d1..ad29906889 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1311,8 +1311,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); // use our MyAvatar position and quat for address manager path - addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldFeetPosition(); }); - addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); }); + addressManager->setPositionGetter([this] { + auto avatarManager = DependencyManager::get(); + auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr; + return myAvatar ? myAvatar->getWorldFeetPosition() : Vectors::ZERO; + }); + addressManager->setOrientationGetter([this] { + auto avatarManager = DependencyManager::get(); + auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr; + return myAvatar ? myAvatar->getWorldOrientation() : glm::quat(); + }); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); From 1572c9362482464c816fc890e1b5617ed92f6b60 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 1 Jun 2019 09:05:06 -0700 Subject: [PATCH 15/25] Fix longstanding bug where resampler called with samples instead of frames, resulting in buffer overflow --- libraries/audio-client/src/AudioClient.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index ea84d54ecc..d75a4960ed 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -693,28 +693,20 @@ void possibleResampling(AudioSRC* resampler, } } else { + int numSourceFrames = numSourceSamples / sourceChannelCount; + if (sourceChannelCount != destinationChannelCount) { - int numChannelCoversionSamples = (numSourceSamples * destinationChannelCount) / sourceChannelCount; - int16_t* channelConversionSamples = new int16_t[numChannelCoversionSamples]; + int16_t* channelConversionSamples = new int16_t[numSourceFrames * destinationChannelCount]; sampleChannelConversion(sourceSamples, channelConversionSamples, numSourceSamples, sourceChannelCount, destinationChannelCount); - resampler->render(channelConversionSamples, destinationSamples, numChannelCoversionSamples); + resampler->render(channelConversionSamples, destinationSamples, numSourceFrames); delete[] channelConversionSamples; } else { - - unsigned int numAdjustedSourceSamples = numSourceSamples; - unsigned int numAdjustedDestinationSamples = numDestinationSamples; - - if (sourceChannelCount == 2 && destinationChannelCount == 2) { - numAdjustedSourceSamples /= 2; - numAdjustedDestinationSamples /= 2; - } - - resampler->render(sourceSamples, destinationSamples, numAdjustedSourceSamples); + resampler->render(sourceSamples, destinationSamples, numSourceFrames); } } } From f7236f0498e66685457564b3393639d604cb63dc Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 1 Jun 2019 10:43:34 -0700 Subject: [PATCH 16/25] Fix bug in local echo when output is multichannel --- libraries/audio-client/src/AudioClient.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index d75a4960ed..4f4c5bc586 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1101,10 +1101,8 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) { // if required, create loopback resampler if (_inputFormat.sampleRate() != _outputFormat.sampleRate() && !_loopbackResampler) { - qCDebug(audioclient) << "Resampling" << _inputFormat.sampleRate() << "to" << _outputFormat.sampleRate() << "for audio loopback."; - - int channelCount = (_inputFormat.channelCount() == 2 && _outputFormat.channelCount() == 2) ? 2 : 1; - _loopbackResampler = new AudioSRC(_inputFormat.sampleRate(), _outputFormat.sampleRate(), channelCount); + qCDebug(audioclient) << "Resampling from" << _inputFormat.sampleRate() << "to" << _outputFormat.sampleRate() << "for audio loopback."; + _loopbackResampler = new AudioSRC(_inputFormat.sampleRate(), _outputFormat.sampleRate(), OUTPUT_CHANNEL_COUNT); } static QByteArray loopBackByteArray; From 451cf60e54be6fb7b54bd53947eb2e613f48992d Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 1 Jun 2019 11:04:52 -0700 Subject: [PATCH 17/25] Reset loopback resampler when input device is changed --- libraries/audio-client/src/AudioClient.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 4f4c5bc586..7c84211c41 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -755,11 +755,6 @@ void AudioClient::stop() { qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down"; switchOutputToAudioDevice(QAudioDeviceInfo(), true); - if (_loopbackResampler) { - delete _loopbackResampler; - _loopbackResampler = NULL; - } - // Stop triggering the checks QObject::disconnect(_checkPeakValuesTimer, &QTimer::timeout, nullptr, nullptr); QObject::disconnect(_checkDevicesTimer, &QTimer::timeout, nullptr, nullptr); @@ -1663,12 +1658,17 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf _dummyAudioInput = NULL; } + // cleanup any resamplers if (_inputToNetworkResampler) { - // if we were using an input to network resampler, delete it here delete _inputToNetworkResampler; _inputToNetworkResampler = NULL; } + if (_loopbackResampler) { + delete _loopbackResampler; + _loopbackResampler = NULL; + } + if (_audioGate) { delete _audioGate; _audioGate = nullptr; From a56942e494355042a4700b7ec3bd91ece3e26bc8 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 1 Jun 2019 14:27:32 -0700 Subject: [PATCH 18/25] Correctly handle time-varying buffer size due to loopback resampling --- libraries/audio-client/src/AudioClient.cpp | 44 ++++++++++++---------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 7c84211c41..cb8fbbdb0b 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -657,11 +657,11 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, return false; // a supported format could not be found } -bool sampleChannelConversion(const int16_t* sourceSamples, int16_t* destinationSamples, unsigned int numSourceSamples, +bool sampleChannelConversion(const int16_t* sourceSamples, int16_t* destinationSamples, int numSourceSamples, const int sourceChannelCount, const int destinationChannelCount) { if (sourceChannelCount == 2 && destinationChannelCount == 1) { // loop through the stereo input audio samples and average every two samples - for (uint i = 0; i < numSourceSamples; i += 2) { + for (int i = 0; i < numSourceSamples; i += 2) { destinationSamples[i / 2] = (sourceSamples[i] / 2) + (sourceSamples[i + 1] / 2); } @@ -669,7 +669,7 @@ bool sampleChannelConversion(const int16_t* sourceSamples, int16_t* destinationS } else if (sourceChannelCount == 1 && destinationChannelCount == 2) { // loop through the mono input audio and repeat each sample twice - for (uint i = 0; i < numSourceSamples; ++i) { + for (int i = 0; i < numSourceSamples; ++i) { destinationSamples[i * 2] = destinationSamples[(i * 2) + 1] = sourceSamples[i]; } @@ -679,10 +679,13 @@ bool sampleChannelConversion(const int16_t* sourceSamples, int16_t* destinationS return false; } -void possibleResampling(AudioSRC* resampler, - const int16_t* sourceSamples, int16_t* destinationSamples, - unsigned int numSourceSamples, unsigned int numDestinationSamples, - const int sourceChannelCount, const int destinationChannelCount) { +int possibleResampling(AudioSRC* resampler, + const int16_t* sourceSamples, int16_t* destinationSamples, + int numSourceSamples, int maxDestinationSamples, + const int sourceChannelCount, const int destinationChannelCount) { + + int numSourceFrames = numSourceSamples / sourceChannelCount; + int numDestinationFrames = 0; if (numSourceSamples > 0) { if (!resampler) { @@ -691,10 +694,8 @@ void possibleResampling(AudioSRC* resampler, // no conversion, we can copy the samples directly across memcpy(destinationSamples, sourceSamples, numSourceSamples * AudioConstants::SAMPLE_SIZE); } + numDestinationFrames = numSourceFrames; } else { - - int numSourceFrames = numSourceSamples / sourceChannelCount; - if (sourceChannelCount != destinationChannelCount) { int16_t* channelConversionSamples = new int16_t[numSourceFrames * destinationChannelCount]; @@ -702,14 +703,17 @@ void possibleResampling(AudioSRC* resampler, sampleChannelConversion(sourceSamples, channelConversionSamples, numSourceSamples, sourceChannelCount, destinationChannelCount); - resampler->render(channelConversionSamples, destinationSamples, numSourceFrames); + numDestinationFrames = resampler->render(channelConversionSamples, destinationSamples, numSourceFrames); delete[] channelConversionSamples; } else { - resampler->render(sourceSamples, destinationSamples, numSourceFrames); + numDestinationFrames = resampler->render(sourceSamples, destinationSamples, numSourceFrames); } } } + + int numDestinationSamples = numDestinationFrames * destinationChannelCount; + return numDestinationSamples; } void AudioClient::start() { @@ -1104,18 +1108,20 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) { int numInputSamples = inputByteArray.size() / AudioConstants::SAMPLE_SIZE; int numInputFrames = numInputSamples / _inputFormat.channelCount(); - int numLoopbackFrames = (numInputFrames * _outputFormat.sampleRate() + _inputFormat.sampleRate() - 1) / _inputFormat.sampleRate(); - int numLoopbackSamples = numLoopbackFrames * OUTPUT_CHANNEL_COUNT; + int maxLoopbackFrames = _loopbackResampler ? _loopbackResampler->getMaxOutput(numInputFrames) : numInputFrames; + int maxLoopbackSamples = maxLoopbackFrames * OUTPUT_CHANNEL_COUNT; - loopBackByteArray.resize(numLoopbackSamples * AudioConstants::SAMPLE_SIZE); + loopBackByteArray.resize(maxLoopbackSamples * AudioConstants::SAMPLE_SIZE); int16_t* inputSamples = reinterpret_cast(inputByteArray.data()); int16_t* loopbackSamples = reinterpret_cast(loopBackByteArray.data()); - possibleResampling(_loopbackResampler, - inputSamples, loopbackSamples, - numInputSamples, numLoopbackSamples, - _inputFormat.channelCount(), OUTPUT_CHANNEL_COUNT); + int numLoopbackSamples = possibleResampling(_loopbackResampler, + inputSamples, loopbackSamples, + numInputSamples, maxLoopbackSamples, + _inputFormat.channelCount(), OUTPUT_CHANNEL_COUNT); + + loopBackByteArray.resize(numLoopbackSamples * AudioConstants::SAMPLE_SIZE); // apply stereo reverb at the source, to the loopback audio if (!_shouldEchoLocally && hasReverb) { From 4a294b389945937643d58c525c91de6d355825ce Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 1 Jun 2019 14:31:14 -0700 Subject: [PATCH 19/25] Add sanity check for buffer overflow due to resampling --- libraries/audio-client/src/AudioClient.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index cb8fbbdb0b..8797b90860 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -713,6 +713,10 @@ int possibleResampling(AudioSRC* resampler, } int numDestinationSamples = numDestinationFrames * destinationChannelCount; + if (numDestinationSamples > maxDestinationSamples) { + qCWarning(audioclient) << "Resampler overflow! numDestinationSamples =" << numDestinationSamples + << "but maxDestinationSamples =" << maxDestinationSamples; + } return numDestinationSamples; } From dfab91e50a75c80493e3994df0792740dcc538a1 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 1 Jun 2019 19:53:18 -0700 Subject: [PATCH 20/25] Reduce the performance impact of loopback resampler (AVX2 optimizations) --- libraries/audio/src/avx2/AudioSRC_avx2.cpp | 36 +++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/libraries/audio/src/avx2/AudioSRC_avx2.cpp b/libraries/audio/src/avx2/AudioSRC_avx2.cpp index 0e31a58ce7..e5ac08746c 100644 --- a/libraries/audio/src/avx2/AudioSRC_avx2.cpp +++ b/libraries/audio/src/avx2/AudioSRC_avx2.cpp @@ -34,15 +34,26 @@ int AudioSRC::multirateFilter1_AVX2(const float* input0, float* output0, int inp const float* c0 = &_polyphaseFilter[_numTaps * _phase]; __m256 acc0 = _mm256_setzero_ps(); + __m256 acc1 = _mm256_setzero_ps(); - for (int j = 0; j < _numTaps; j += 8) { + int j = 0; + for (; j < _numTaps - 15; j += 16) { // unrolled x 2 //float coef = c0[j]; - __m256 coef0 = _mm256_loadu_ps(&c0[j]); + __m256 coef0 = _mm256_loadu_ps(&c0[j + 0]); + __m256 coef1 = _mm256_loadu_ps(&c0[j + 8]); //acc += input[i + j] * coef; + acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j + 0]), coef0, acc0); + acc1 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j + 8]), coef1, acc1); + } + if (j < _numTaps) { + + __m256 coef0 = _mm256_loadu_ps(&c0[j]); + acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j]), coef0, acc0); } + acc0 = _mm256_add_ps(acc0, acc1); // horizontal sum acc0 = _mm256_hadd_ps(acc0, acc0); @@ -73,19 +84,36 @@ int AudioSRC::multirateFilter1_AVX2(const float* input0, float* output0, int inp const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; __m256 acc0 = _mm256_setzero_ps(); + __m256 acc1 = _mm256_setzero_ps(); __m256 frac = _mm256_broadcast_ss(&ftmp); - for (int j = 0; j < _numTaps; j += 8) { + int j = 0; + for (; j < _numTaps - 15; j += 16) { // unrolled x 2 //float coef = c0[j] + frac * (c1[j] - c0[j]); + __m256 coef0 = _mm256_loadu_ps(&c0[j + 0]); + __m256 coef1 = _mm256_loadu_ps(&c1[j + 0]); + __m256 coef2 = _mm256_loadu_ps(&c0[j + 8]); + __m256 coef3 = _mm256_loadu_ps(&c1[j + 8]); + coef1 = _mm256_sub_ps(coef1, coef0); + coef3 = _mm256_sub_ps(coef3, coef2); + coef0 = _mm256_fmadd_ps(coef1, frac, coef0); + coef2 = _mm256_fmadd_ps(coef3, frac, coef2); + + //acc += input[i + j] * coef; + acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j + 0]), coef0, acc0); + acc1 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j + 8]), coef2, acc1); + } + if (j < _numTaps) { + __m256 coef0 = _mm256_loadu_ps(&c0[j]); __m256 coef1 = _mm256_loadu_ps(&c1[j]); coef1 = _mm256_sub_ps(coef1, coef0); coef0 = _mm256_fmadd_ps(coef1, frac, coef0); - //acc += input[i + j] * coef; acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j]), coef0, acc0); } + acc0 = _mm256_add_ps(acc0, acc1); // horizontal sum acc0 = _mm256_hadd_ps(acc0, acc0); From 4ea67ad2120ea2dc5df1e14463fd81ef90556e6c Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sun, 2 Jun 2019 13:52:49 -0700 Subject: [PATCH 21/25] Updated build of WASAPI audio plugin using Qt 5.12.3, includes Debug/Release symbols --- cmake/externals/wasapi/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt index 8b3408e3fa..9e22e28f58 100644 --- a/cmake/externals/wasapi/CMakeLists.txt +++ b/cmake/externals/wasapi/CMakeLists.txt @@ -6,8 +6,8 @@ if (WIN32) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://public.highfidelity.com/dependencies/qtaudio_wasapi10.zip - URL_MD5 4f40e49715a420fb67b45b9cee19052c + URL https://public.highfidelity.com/dependencies/qtaudio_wasapi11.zip + URL_MD5 d0eb8489455e7f79d59155535a2c8861 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 27ced8a217ef050739761f19117088f0fb0a2bbd Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 3 Jun 2019 12:32:00 -0700 Subject: [PATCH 22/25] Add NSMicrophoneUsageDescription to Info.plist to allow microphone when debugging on Mac --- cmake/modules/MacOSXBundleInfo.plist.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/modules/MacOSXBundleInfo.plist.in b/cmake/modules/MacOSXBundleInfo.plist.in index b9558cf361..2cea158814 100644 --- a/cmake/modules/MacOSXBundleInfo.plist.in +++ b/cmake/modules/MacOSXBundleInfo.plist.in @@ -53,5 +53,7 @@ NSHighResolutionCapable + NSMicrophoneUsageDescription + From 3f42d083f5335721479b06d17d3f2a29b5caf174 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 3 Jun 2019 16:14:09 -0700 Subject: [PATCH 23/25] fix some transparency issues on amd --- libraries/entities-renderer/src/RenderableImageEntityItem.cpp | 4 ++-- libraries/entities-renderer/src/RenderableShapeEntityItem.cpp | 4 ++++ libraries/render-utils/src/ShadingModel.slh | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 6638bc0687..20d10c6fd4 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -163,7 +163,7 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { transform = _renderTransform; }); - if (!_visible || !texture || !texture->isLoaded()) { + if (!_visible || !texture || !texture->isLoaded() || color.a == 0.0f) { return; } @@ -214,4 +214,4 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { ); batch->setResourceTexture(0, nullptr); -} \ No newline at end of file +} diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 6a0d7b001c..fbc24cb4a5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -270,6 +270,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } }); + if (outColor.a == 0.0f) { + return; + } + if (proceduralRender) { if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShape(batch, geometryShape, outColor); diff --git a/libraries/render-utils/src/ShadingModel.slh b/libraries/render-utils/src/ShadingModel.slh index 99aa01cc5e..5af986bd9d 100644 --- a/libraries/render-utils/src/ShadingModel.slh +++ b/libraries/render-utils/src/ShadingModel.slh @@ -222,7 +222,7 @@ void evalFragShadingGloss(out vec3 diffuse, out vec3 specular, } vec3 evalSpecularWithOpacity(vec3 specular, float opacity) { - return specular / opacity; + return specular / mix(1.0, opacity, float(opacity > 0.0)); } <@if not GETFRESNEL0@> From 154fd393bac6d3880be9e777ec62304429dc29a3 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 3 Jun 2019 16:08:16 -0700 Subject: [PATCH 24/25] Bug fix for crash in QScriptEngine::reportAdditionalMemoryCost() This fix requires a patch to qt. This build includs a new pre-built Qt 5.12.3 with the patch applied. See tools/qt5-builder/qtscript-crash-fix.patch to see actual patch applied. * Touched bullet3 portfile to create new vckpg hash * New urls for qt assets which include qscript patch hifi_vcpkg.py * Updated tools/qt5-builder/ with qscript patch and README.md directions. https://highfidelity.atlassian.net/browse/BUGZ-46 A qt bug was filed to hopefully get this bug fixed upstream. https://bugreports.qt.io/browse/QTBUG-76176 --- cmake/ports/bullet3/portfile.cmake | 4 +++- hifi_vcpkg.py | 4 ++-- tools/qt-builder/README.md | 16 ++++++++++------ .../qt-builder/patches/qtscript-crash-fix.patch | 16 ++++++++++++++++ .../prepare-windows-symbols-for-backtrace.py | 2 +- 5 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 tools/qt-builder/patches/qtscript-crash-fix.patch diff --git a/cmake/ports/bullet3/portfile.cmake b/cmake/ports/bullet3/portfile.cmake index 1faf7d983b..32713f5a46 100644 --- a/cmake/ports/bullet3/portfile.cmake +++ b/cmake/ports/bullet3/portfile.cmake @@ -1,4 +1,7 @@ +# Updated June 6th, 2019, to force new vckpg hash +# # Common Ambient Variables: +# # CURRENT_BUILDTREES_DIR = ${VCPKG_ROOT_DIR}\buildtrees\${PORT} # CURRENT_PACKAGES_DIR = ${VCPKG_ROOT_DIR}\packages\${PORT}_${TARGET_TRIPLET} # CURRENT_PORT_DIR = ${VCPKG_ROOT_DIR}\ports\${PORT} @@ -9,7 +12,6 @@ # VCPKG_ROOT_DIR = # VCPKG_TARGET_ARCHITECTURE = target architecture (x64, x86, arm) # -# include(vcpkg_common_functions) diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 3ae3a926b5..686ccfcfc7 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -254,9 +254,9 @@ endif() url = 'NOT DEFINED' if platform.system() == 'Windows': - url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows2.tar.gz' + url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz' elif platform.system() == 'Darwin': - url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos2.tar.gz' + url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz' elif platform.system() == 'Linux': if platform.linux_distribution()[1][:3] == '16.': url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04.tar.gz' diff --git a/tools/qt-builder/README.md b/tools/qt-builder/README.md index 5b4084e61e..956dda4534 100644 --- a/tools/qt-builder/README.md +++ b/tools/qt-builder/README.md @@ -1,7 +1,8 @@ # General This document describes the process to build Qt 5.12.3. -Note that there are two patches. The first (to qfloat16.h) is needed to compile QT 5.12.3 on Visual Studio 2017 due to a bug in Visual Studio (*bitset* will not compile. Note that there is a change in CMakeLists.txt to support this. +Note that there are three patches. The first (to qfloat16.h) is needed to compile QT 5.12.3 on Visual Studio 2017 due to a bug in Visual Studio (*bitset* will not compile. Note that there is a change in CMakeLists.txt to support this. The second patch is to OpenSL ES audio. +The third is a patch to QScriptEngine to prevent crashes in QScriptEnginePrivate::reportAdditionalMemoryCost, during garbage collection. See https://bugreports.qt.io/browse/QTBUG-76176 ## Requirements ### Windows 1. Visual Studio 2017 @@ -125,11 +126,12 @@ Also, make sure the directory that you are using to build qt is not deeply neste * Copy the **patches** folder to qt5 * Copy the **qt5vars.bat** file to qt5 -* Apply the two patches to Qt +* Apply the patches to Qt `cd qt5` `git apply --ignore-space-change --ignore-whitespace patches/qfloat16.patch` `git apply --ignore-space-change --ignore-whitespace patches/aec.patch` +`git apply --ignore-space-change --ignore-whitespace patches/qtscript-crash-fix.patch` `cd ..` #### Configuring `mkdir qt5-install` @@ -151,8 +153,8 @@ The *.prl* files have an absolute path that needs to be removed (see http://www. `find . -name \*.prl -exec sed -i -e '/^QMAKE_PRL_BUILD_DIR/d' {} \;` 1. Copy *qt.conf* to *qt5-install\bin* #### Uploading -Create a tar file called qt5-install-5.12.3-windows.tar.gz from the qt5-install folder -Upload qt5-install-5.12.3-windows.tar.gz to our Amazon S3 hifi-public bucket, under the dependencies/vckpg directory +Create a tar file called qt5-install-5.12.3-windows.tar.gz from the qt5-install folder. +Upload qt5-install-5.12.3-windows.tar.gz to our Amazon S3 hifi-public bucket, under the dependencies/vckpg directory. Update hifi_vcpkg.py to use this new URL. Additionally, you should make a small change to any file in the hifi/cmake/ports directory to force the re-download of the qt-install.tar.gz during the build process for hifi. #### Preparing Symbols Run `python3 prepare-windows-symbols-for-backtrace.py qt5-install` to scan the qt5-install directory for any dlls and pdbs. After running this command the backtrace directory will be created. Zip this directory up, but make sure that all dlls and pdbs are in the root of the zip file, not under a sub-directory. This file can then be uploaded to backtrace here: https://highfidelity.sp.backtrace.io/p/Interface/settings/symbol/upload @@ -161,9 +163,10 @@ Run `python3 prepare-windows-symbols-for-backtrace.py qt5-install` to scan the q `git clone --recursive git://code.qt.io/qt/qt5.git -b 5.12.3 --single-branch` * Copy the **patches** folder to qt5 -* Apply one patch to Qt +* Apply patches to Qt `cd qt5` `git apply --ignore-space-change --ignore-whitespace patches/aec.patch` +`git apply --ignore-space-change --ignore-whitespace patches/qtscript-crash-fix.patch` `cd ..` #### Configuring `mkdir qt5-install` @@ -215,9 +218,10 @@ Run `python3 prepare-windows-symbols-for-backtrace.py qt5-install` to scan the q git clone --recursive git://code.qt.io/qt/qt5.git -b 5.12.3 --single-branch * Copy the **patches** folder to qt5 -* Apply one patch to Qt +* Apply the patches to Qt `cd qt5` `git apply --ignore-space-change --ignore-whitespace patches/aec.patch` +`git apply --ignore-space-change --ignore-whitespace patches/qtscript-crash-fix.patch` `cd ..` #### Configuring `mkdir qt5-install` diff --git a/tools/qt-builder/patches/qtscript-crash-fix.patch b/tools/qt-builder/patches/qtscript-crash-fix.patch new file mode 100644 index 0000000000..0a659fe9e3 --- /dev/null +++ b/tools/qt-builder/patches/qtscript-crash-fix.patch @@ -0,0 +1,16 @@ +diff --git a/qtscript/src/script/api/qscriptengine.cpp b/qtscript/src/script/api/qscriptengine.cpp +index c5f437b..942833e 100644 +--- a/qtscript/src/script/api/qscriptengine.cpp ++++ b/qtscript/src/script/api/qscriptengine.cpp +@@ -1332,8 +1332,10 @@ void QScriptEnginePrivate::collectGarbage() + + void QScriptEnginePrivate::reportAdditionalMemoryCost(int size) + { +- if (size > 0) ++ if (size > 0) { ++ QScript::APIShim shim(this); + globalData->heap.reportExtraMemoryCost(size); ++ } + } + + QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const diff --git a/tools/qt-builder/prepare-windows-symbols-for-backtrace.py b/tools/qt-builder/prepare-windows-symbols-for-backtrace.py index 5738907a2d..9028c50e4f 100644 --- a/tools/qt-builder/prepare-windows-symbols-for-backtrace.py +++ b/tools/qt-builder/prepare-windows-symbols-for-backtrace.py @@ -4,7 +4,7 @@ # usage # python prepare-windows-symbols-for-backrace.py QT_INSTALL_DIR # -# QT_BUILD_DIR should be the directory where qt is installed after running `jom install` or `nmake install` +# QT_INSTALL_DIR should be the directory where qt is installed after running `jom install` or `nmake install` # see hifi/tools/qt-builder/README.md for more info # From e1534b34b4baffe3954fcce6814d20dbeeb48578 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 4 Jun 2019 08:56:07 -0700 Subject: [PATCH 25/25] Workaround crash in reportAdditionalMemoryCost other platforms --- libraries/script-engine/src/ArrayBufferClass.cpp | 4 +++- libraries/script-engine/src/ScriptEngine.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ArrayBufferClass.cpp b/libraries/script-engine/src/ArrayBufferClass.cpp index f64dbeffd6..6734114932 100644 --- a/libraries/script-engine/src/ArrayBufferClass.cpp +++ b/libraries/script-engine/src/ArrayBufferClass.cpp @@ -76,8 +76,10 @@ QScriptValue ArrayBufferClass::newInstance(qint32 size) { engine()->evaluate("throw \"ArgumentError: absurd length\""); return QScriptValue(); } - + // We've patched qt to fix https://highfidelity.atlassian.net/browse/BUGZ-46 on mac and windows only. +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) engine()->reportAdditionalMemoryCost(size); +#endif QScriptEngine* eng = engine(); QVariant variant = QVariant::fromValue(QByteArray(size, 0)); QScriptValue data = eng->newVariant(variant); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 309161206c..9d29f32931 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1346,7 +1346,10 @@ void ScriptEngine::callAnimationStateHandler(QScriptValue callback, AnimVariantM void ScriptEngine::updateMemoryCost(const qint64& deltaSize) { if (deltaSize > 0) { + // We've patched qt to fix https://highfidelity.atlassian.net/browse/BUGZ-46 on mac and windows only. +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) reportAdditionalMemoryCost(deltaSize); +#endif } }