From e9ab2b8f27db38a81f114c89fd0d66308c76d1c9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 20 Jul 2018 16:48:15 -0700 Subject: [PATCH 01/20] enable LOD manager on android --- interface/src/Application.cpp | 2 -- interface/src/LODManager.h | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 311c08b858..0da3d9445e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5803,9 +5803,7 @@ void Application::update(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); -#if !defined(Q_OS_ANDROID) updateLOD(deltaTime); -#endif // TODO: break these out into distinct perfTimers when they prove interesting { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 8f88da63a8..8cae179f1e 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -19,7 +19,11 @@ #include #include +#ifdef Q_OS_ANDROID +const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 10.0f; +#else const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0f; +#endif const float DEFAULT_HMD_LOD_DOWN_FPS = 34.0f; const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec From a76b50ce3308c1d5c5805c4b45f86aace2c83080 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 27 Aug 2018 15:07:19 -0700 Subject: [PATCH 02/20] fix teardown of recording and ScriptEngine(s) --- assignment-client/src/Agent.cpp | 291 ++++++++++-------- .../src/avatars-renderer/Head.cpp | 1 - 2 files changed, 157 insertions(+), 135 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 2f03f15da7..47a64413c0 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -96,7 +96,6 @@ Agent::Agent(ReceivedMessage& message) : DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -177,6 +176,8 @@ void Agent::run() { // Create ScriptEngines on threaded-assignment thread then move to main thread. DependencyManager::set(ScriptEngine::AGENT_SCRIPT)->moveToThread(qApp->thread()); + DependencyManager::set(); + // make sure we request our script once the agent connects to the domain auto nodeList = DependencyManager::get(); @@ -360,154 +361,168 @@ void Agent::scriptRequestFinished() { } void Agent::executeScript() { - _scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload); + // the following block is scoped so that any shared pointers we take here + // are cleared before we call setFinished at the end of the function + { + _scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload); - // setup an Avatar for the script to use - auto scriptedAvatar = DependencyManager::get(); + // setup an Avatar for the script to use + auto scriptedAvatar = DependencyManager::get(); - scriptedAvatar->setID(getSessionUUID()); + scriptedAvatar->setID(getSessionUUID()); - connect(_scriptEngine.data(), SIGNAL(update(float)), - scriptedAvatar.data(), SLOT(update(float)), Qt::ConnectionType::QueuedConnection); - scriptedAvatar->setForceFaceTrackerConnected(true); + connect(_scriptEngine.data(), SIGNAL(update(float)), + scriptedAvatar.data(), SLOT(update(float)), Qt::ConnectionType::QueuedConnection); + scriptedAvatar->setForceFaceTrackerConnected(true); - // call model URL setters with empty URLs so our avatar, if user, will have the default models - scriptedAvatar->setSkeletonModelURL(QUrl()); + // call model URL setters with empty URLs so our avatar, if user, will have the default models + scriptedAvatar->setSkeletonModelURL(QUrl()); - // force lazy initialization of the head data for the scripted avatar - // since it is referenced below by computeLoudness and getAudioLoudness - scriptedAvatar->getHeadOrientation(); + // force lazy initialization of the head data for the scripted avatar + // since it is referenced below by computeLoudness and getAudioLoudness + scriptedAvatar->getHeadOrientation(); - // give this AvatarData object to the script engine - _scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data()); + // give this AvatarData object to the script engine + _scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data()); - // give scripts access to the Users object - _scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); + // give scripts access to the Users object + _scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); - auto player = DependencyManager::get(); - connect(player.data(), &recording::Deck::playbackStateChanged, [=] { - if (player->isPlaying()) { - auto recordingInterface = DependencyManager::get(); - if (recordingInterface->getPlayFromCurrentLocation()) { - scriptedAvatar->setRecordingBasis(); + auto player = DependencyManager::get(); + connect(player.data(), &recording::Deck::playbackStateChanged, [&player, &scriptedAvatar] { + if (player->isPlaying()) { + auto recordingInterface = DependencyManager::get(); + if (recordingInterface->getPlayFromCurrentLocation()) { + scriptedAvatar->setRecordingBasis(); + } + } else { + scriptedAvatar->clearRecordingBasis(); } - } else { - scriptedAvatar->clearRecordingBasis(); - } - }); + }); - using namespace recording; - static const FrameType AVATAR_FRAME_TYPE = Frame::registerFrameType(AvatarData::FRAME_NAME); - Frame::registerFrameHandler(AVATAR_FRAME_TYPE, [scriptedAvatar](Frame::ConstPointer frame) { + using namespace recording; + static const FrameType AVATAR_FRAME_TYPE = Frame::registerFrameType(AvatarData::FRAME_NAME); + Frame::registerFrameHandler(AVATAR_FRAME_TYPE, [scriptedAvatar](Frame::ConstPointer frame) { + + auto recordingInterface = DependencyManager::get(); + bool useFrameSkeleton = recordingInterface->getPlayerUseSkeletonModel(); + + // FIXME - the ability to switch the avatar URL is not actually supported when playing back from a recording + if (!useFrameSkeleton) { + static std::once_flag warning; + std::call_once(warning, [] { + qWarning() << "Recording.setPlayerUseSkeletonModel(false) is not currently supported."; + }); + } + + AvatarData::fromFrame(frame->data, *scriptedAvatar); + }); + + using namespace recording; + static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::getAudioFrameName()); + Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) { + static quint16 audioSequenceNumber{ 0 }; + + QByteArray audio(frame->data); + + if (_isNoiseGateEnabled) { + int16_t* samples = reinterpret_cast(audio.data()); + int numSamples = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; + _audioGate.render(samples, samples, numSamples); + } + + computeLoudness(&audio, scriptedAvatar); + + // state machine to detect gate opening and closing + bool audioGateOpen = (scriptedAvatar->getAudioLoudness() != 0.0f); + bool openedInLastBlock = !_audioGateOpen && audioGateOpen; // the gate just opened + bool closedInLastBlock = _audioGateOpen && !audioGateOpen; // the gate just closed + _audioGateOpen = audioGateOpen; + Q_UNUSED(openedInLastBlock); + + // the codec must be flushed to silence before sending silent packets, + // so delay the transition to silent packets by one packet after becoming silent. + auto packetType = PacketType::MicrophoneAudioNoEcho; + if (!audioGateOpen && !closedInLastBlock) { + packetType = PacketType::SilentAudioFrame; + } + + Transform audioTransform; + auto headOrientation = scriptedAvatar->getHeadOrientation(); + audioTransform.setTranslation(scriptedAvatar->getWorldPosition()); + audioTransform.setRotation(headOrientation); + + QByteArray encodedBuffer; + if (_encoder) { + _encoder->encode(audio, encodedBuffer); + } else { + encodedBuffer = audio; + } + + AbstractAudioInterface::emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), audioSequenceNumber, false, + audioTransform, scriptedAvatar->getWorldPosition(), glm::vec3(0), + packetType, _selectedCodecName); + }); + + auto avatarHashMap = DependencyManager::set(); + _scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data()); + + // register ourselves to the script engine + _scriptEngine->registerGlobalObject("Agent", new AgentScriptingInterface(this)); + + _scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); + _scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); + + QScriptValue webSocketServerConstructorValue = _scriptEngine->newFunction(WebSocketServerClass::constructor); + _scriptEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); + + auto entityScriptingInterface = DependencyManager::get(); + + _scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer); + + _scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, + LocationScriptingInterface::locationSetter); auto recordingInterface = DependencyManager::get(); - bool useFrameSkeleton = recordingInterface->getPlayerUseSkeletonModel(); + _scriptEngine->registerGlobalObject("Recording", recordingInterface.data()); - // FIXME - the ability to switch the avatar URL is not actually supported when playing back from a recording - if (!useFrameSkeleton) { - static std::once_flag warning; - std::call_once(warning, [] { - qWarning() << "Recording.setPlayerUseSkeletonModel(false) is not currently supported."; - }); + entityScriptingInterface->init(); + + _entityViewer.init(); + + entityScriptingInterface->setEntityTree(_entityViewer.getTree()); + + DependencyManager::set(_entityViewer.getTree()); + + _avatarAudioTimer.start(); + + // Agents should run at 45hz + static const int AVATAR_DATA_HZ = 45; + static const int AVATAR_DATA_IN_MSECS = MSECS_PER_SECOND / AVATAR_DATA_HZ; + QTimer* avatarDataTimer = new QTimer(this); + connect(avatarDataTimer, &QTimer::timeout, this, &Agent::processAgentAvatar); + avatarDataTimer->setSingleShot(false); + avatarDataTimer->setInterval(AVATAR_DATA_IN_MSECS); + avatarDataTimer->setTimerType(Qt::PreciseTimer); + avatarDataTimer->start(); + + _scriptEngine->run(); + + Frame::clearFrameHandler(AUDIO_FRAME_TYPE); + Frame::clearFrameHandler(AVATAR_FRAME_TYPE); + + if (recordingInterface->isPlaying()) { + recordingInterface->stopPlaying(); } - AvatarData::fromFrame(frame->data, *scriptedAvatar); - }); - - using namespace recording; - static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::getAudioFrameName()); - Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) { - static quint16 audioSequenceNumber{ 0 }; - - QByteArray audio(frame->data); - - if (_isNoiseGateEnabled) { - int16_t* samples = reinterpret_cast(audio.data()); - int numSamples = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; - _audioGate.render(samples, samples, numSamples); + if (recordingInterface->isRecording()) { + recordingInterface->stopRecording(); } - computeLoudness(&audio, scriptedAvatar); + avatarDataTimer->stop(); + _avatarAudioTimer.stop(); + } - // state machine to detect gate opening and closing - bool audioGateOpen = (scriptedAvatar->getAudioLoudness() != 0.0f); - bool openedInLastBlock = !_audioGateOpen && audioGateOpen; // the gate just opened - bool closedInLastBlock = _audioGateOpen && !audioGateOpen; // the gate just closed - _audioGateOpen = audioGateOpen; - Q_UNUSED(openedInLastBlock); - - // the codec must be flushed to silence before sending silent packets, - // so delay the transition to silent packets by one packet after becoming silent. - auto packetType = PacketType::MicrophoneAudioNoEcho; - if (!audioGateOpen && !closedInLastBlock) { - packetType = PacketType::SilentAudioFrame; - } - - Transform audioTransform; - auto headOrientation = scriptedAvatar->getHeadOrientation(); - audioTransform.setTranslation(scriptedAvatar->getWorldPosition()); - audioTransform.setRotation(headOrientation); - - QByteArray encodedBuffer; - if (_encoder) { - _encoder->encode(audio, encodedBuffer); - } else { - encodedBuffer = audio; - } - - AbstractAudioInterface::emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), audioSequenceNumber, false, - audioTransform, scriptedAvatar->getWorldPosition(), glm::vec3(0), - packetType, _selectedCodecName); - }); - - auto avatarHashMap = DependencyManager::set(); - _scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data()); - - // register ourselves to the script engine - _scriptEngine->registerGlobalObject("Agent", new AgentScriptingInterface(this)); - - _scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); - _scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); - - QScriptValue webSocketServerConstructorValue = _scriptEngine->newFunction(WebSocketServerClass::constructor); - _scriptEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); - - auto entityScriptingInterface = DependencyManager::get(); - - _scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer); - - _scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, - LocationScriptingInterface::locationSetter); - - auto recordingInterface = DependencyManager::get(); - _scriptEngine->registerGlobalObject("Recording", recordingInterface.data()); - - entityScriptingInterface->init(); - - _entityViewer.init(); - - entityScriptingInterface->setEntityTree(_entityViewer.getTree()); - - DependencyManager::set(_entityViewer.getTree()); - - QMetaObject::invokeMethod(&_avatarAudioTimer, "start"); - - // Agents should run at 45hz - static const int AVATAR_DATA_HZ = 45; - static const int AVATAR_DATA_IN_MSECS = MSECS_PER_SECOND / AVATAR_DATA_HZ; - QTimer* avatarDataTimer = new QTimer(this); - connect(avatarDataTimer, &QTimer::timeout, this, &Agent::processAgentAvatar); - avatarDataTimer->setSingleShot(false); - avatarDataTimer->setInterval(AVATAR_DATA_IN_MSECS); - avatarDataTimer->setTimerType(Qt::PreciseTimer); - avatarDataTimer->start(); - - _scriptEngine->run(); - - Frame::clearFrameHandler(AUDIO_FRAME_TYPE); - Frame::clearFrameHandler(AVATAR_FRAME_TYPE); - - DependencyManager::destroy(); setFinished(true); } @@ -859,17 +874,25 @@ void Agent::aboutToFinish() { DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - DependencyManager::destroy(); + + // drop our shared pointer to the script engine, then ask ScriptEngines to shutdown scripting + // this ensures that the ScriptEngine goes down before ScriptEngines + _scriptEngine.clear(); + + { + DependencyManager::get()->shutdownScripting(); + } + + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - QMetaObject::invokeMethod(&_avatarAudioTimer, "stop"); - // cleanup codec & encoder if (_codec && _encoder) { _codec->releaseEncoder(_encoder); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index bdee6d9147..9cf034863e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include From c29c9f98c1d46a3665aa5dd3ba3b097333cc9d6b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Aug 2018 11:15:57 +1200 Subject: [PATCH 03/20] Make Cancel in HMD settings dialogs return to Settings dialog --- .../hifi/tablet/tabletWindows/TabletPreferencesDialog.qml | 6 +++++- interface/src/Menu.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index 05f45dc61e..31d246be2d 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -50,7 +50,11 @@ Item { section.restoreAll(); } - closeDialog(); + if (HMD.active) { + tablet.popFromStack(); + } else { + closeDialog(); + } } function closeDialog() { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a7d7dcf8b3..72191de994 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -254,7 +254,7 @@ Menu::Menu() { connect(action, &QAction::triggered, [] { auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); auto hmd = DependencyManager::get(); - tablet->loadQMLSource("hifi/tablet/ControllerSettings.qml"); + tablet->pushOntoStack("hifi/tablet/ControllerSettings.qml"); if (!hmd->getShouldShowTablet()) { hmd->toggleShouldShowTablet(); From 07b24b47688763d1cab3979264713837ee54b38c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 30 Aug 2018 17:22:27 -0700 Subject: [PATCH 04/20] send kill packet to ignored node for ignorer --- assignment-client/src/avatars/AvatarMixer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index edbba20dc7..0289a8aa3f 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -654,6 +654,12 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer if (addToIgnore) { senderNode->addIgnoredNode(ignoredUUID); + + // send a reliable kill packet to remove the sending avatar for the ignored avatar + auto killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); + killPacket->write(senderNode->getUUID().toRfc4122()); + killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected); + nodeList->sendPacket(std::move(killPacket), *ignoredNode); } else { senderNode->removeIgnoredNode(ignoredUUID); } From f1443083341336c9aff7dcb06e45f30f94d84d86 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 31 Aug 2018 16:58:59 +1200 Subject: [PATCH 05/20] Make tablet menu page title navigation go back a level --- .../resources/qml/hifi/tablet/TabletMenu.qml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletMenu.qml b/interface/resources/qml/hifi/tablet/TabletMenu.qml index 57c1163eb8..bfbd2d8813 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenu.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenu.qml @@ -23,6 +23,8 @@ FocusScope { property string subMenu: "" signal sendToScript(var message); + HifiConstants { id: hifi } + Rectangle { id: bgNavBar height: 90 @@ -45,24 +47,22 @@ FocusScope { anchors.topMargin: 0 anchors.top: parent.top - Image { + HiFiGlyphs { id: menuRootIcon - width: 40 - height: 40 - source: "../../../icons/tablet-icons/menu-i.svg" + text: hifi.glyphs.backward + size: 72 anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 15 + width: breadcrumbText.text === "Menu" ? 15 : 50 + visible: breadcrumbText.text !== "Menu" MouseArea { anchors.fill: parent hoverEnabled: true onEntered: iconColorOverlay.color = "#1fc6a6"; onExited: iconColorOverlay.color = "#34a2c7"; - // navigate back to root level menu onClicked: { - buildMenu(); - breadcrumbText.text = "Menu"; + menuPopperUpper.closeLastMenu(); tabletRoot.playButtonClickSound(); } } @@ -103,7 +103,6 @@ FocusScope { menuPopperUpper.closeLastMenu(); } - function setRootMenu(rootMenu, subMenu) { tabletMenu.subMenu = subMenu; tabletMenu.rootMenu = rootMenu; From fff6a10bcd4ecc7a272ec8ac481fdc6b9a3b3586 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 4 Sep 2018 10:58:40 -0700 Subject: [PATCH 06/20] Remove some debug logging from safe landing additions --- interface/src/octree/SafeLanding.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 60b660f66a..cfb0a2c753 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -75,7 +75,6 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) { // Only track entities with downloaded collision bodies. _trackedEntities.emplace(entityID, entity); - qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName(); } } } @@ -110,7 +109,6 @@ bool SafeLanding::isLoadSequenceComplete() { _initialEnd = INVALID_SEQUENCE; _entityTree = nullptr; EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority); - qCDebug(interfaceapp) << "Safe Landing: load sequence complete"; } return !_trackingEntities; From 7af69b54501f5989de5bab6d606d69021a9bdf56 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 4 Sep 2018 13:53:25 -0700 Subject: [PATCH 07/20] Check that a requested listened port is used in NodeList --- libraries/networking/src/LimitedNodeList.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b6b2369703..db6ed15792 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -56,13 +56,20 @@ LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) : qRegisterMetaType("ConnectionStep"); auto port = (socketListenPort != INVALID_PORT) ? socketListenPort : LIMITED_NODELIST_LOCAL_PORT.get(); _nodeSocket.bind(QHostAddress::AnyIPv4, port); - qCDebug(networking) << "NodeList socket is listening on" << _nodeSocket.localPort(); + quint16 assignedPort = _nodeSocket.localPort(); + if (socketListenPort != INVALID_PORT && socketListenPort != 0 && socketListenPort != assignedPort) { + qCCritical(networking) << "NodeList is unable to assign requested port of" << socketListenPort; + } + qCDebug(networking) << "NodeList socket is listening on" << assignedPort; if (dtlsListenPort != INVALID_PORT) { // only create the DTLS socket during constructor if a custom port is passed _dtlsSocket = new QUdpSocket(this); _dtlsSocket->bind(QHostAddress::AnyIPv4, dtlsListenPort); + if (dtlsListenPort != 0 && _dtlsSocket->localPort() != dtlsListenPort) { + qCDebug(networking) << "NodeList is unable to assign requested DTLS port of" << dtlsListenPort; + } qCDebug(networking) << "NodeList DTLS socket is listening on" << _dtlsSocket->localPort(); } From 398724de73698da6dc8c7cbea0acae317f60a625 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 6 Sep 2018 10:23:45 +1200 Subject: [PATCH 08/20] Make Save in HMD settings dialogs return to previous dialog Same as Cancel key does. --- .../hifi/tablet/tabletWindows/TabletPreferencesDialog.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index 31d246be2d..5a0dc24dbc 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -41,7 +41,11 @@ Item { section.saveAll(); } - closeDialog(); + if (HMD.active) { + tablet.popFromStack(); + } else { + closeDialog(); + } } function restoreAll() { From 960bf00e1200492920bee9336749514c72339750 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 6 Sep 2018 11:02:24 +1200 Subject: [PATCH 09/20] Modify look of HMD mode Settings dialogs' titles --- .../resources/qml/hifi/tablet/TabletMenu.qml | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletMenu.qml b/interface/resources/qml/hifi/tablet/TabletMenu.qml index bfbd2d8813..6540d53fca 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenu.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenu.qml @@ -49,11 +49,11 @@ FocusScope { HiFiGlyphs { id: menuRootIcon - text: hifi.glyphs.backward + text: breadcrumbText.text !== "Menu" ? hifi.glyphs.backward : "" size: 72 anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - width: breadcrumbText.text === "Menu" ? 15 : 50 + width: breadcrumbText.text === "Menu" ? 32 : 50 visible: breadcrumbText.text !== "Menu" MouseArea { @@ -79,23 +79,10 @@ FocusScope { id: breadcrumbText text: "Menu" size: 26 - color: "#34a2c7" + color: "#e3e3e3" anchors.verticalCenter: parent.verticalCenter anchors.left: menuRootIcon.right anchors.leftMargin: 15 - MouseArea { - anchors.fill: parent - hoverEnabled: true - onEntered: breadcrumbText.color = "#1fc6a6"; - onExited: breadcrumbText.color = "#34a2c7"; - // navigate back to parent level menu if there is one - onClicked: { - if (breadcrumbText.text !== "Menu") { - menuPopperUpper.closeLastMenu(); - } - tabletRoot.playButtonClickSound(); - } - } } } From a7099025dcfee39fd8ccd4603e93390dc9f074d8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 6 Sep 2018 11:15:14 +1200 Subject: [PATCH 10/20] Fix up some Settings dialogs' titles --- interface/resources/qml/hifi/audio/Audio.qml | 2 +- interface/resources/qml/hifi/tablet/ControllerSettings.qml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index cc1ba49984..f4a708567a 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -26,7 +26,7 @@ Rectangle { HifiConstants { id: hifi; } property var eventBridge; - property string title: "Audio Settings - " + AudioScriptingInterface.context; + property string title: "Audio Settings" signal sendToScript(var message); color: hifi.colors.baseGray; diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 135c1379e2..6706830537 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -24,6 +24,8 @@ Item { height: parent.height width: parent.width + property string title: "Controls" + HifiConstants { id: hifi } TabBar { From 3a3ffcc98c792736ef7bfa0495606a11e3c99f7d Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 5 Sep 2018 18:14:06 -0700 Subject: [PATCH 11/20] First pass at improving anim stats. --- interface/resources/qml/Stats.qml | 61 ++++++++++-- interface/src/ui/Stats.cpp | 92 ++++++++++++++++++- interface/src/ui/Stats.h | 25 +++-- libraries/animation/src/AnimBlendLinear.cpp | 10 +- .../animation/src/AnimBlendLinearMove.cpp | 18 +--- libraries/animation/src/AnimContext.h | 42 +++++++++ libraries/animation/src/AnimNode.cpp | 4 - libraries/animation/src/AnimNode.h | 18 +--- libraries/animation/src/AnimStateMachine.cpp | 25 +---- libraries/animation/src/AnimStateMachine.h | 1 - libraries/animation/src/AnimVariant.cpp | 41 +++++++++ libraries/animation/src/AnimVariant.h | 3 + libraries/animation/src/Rig.cpp | 2 + libraries/animation/src/Rig.h | 7 +- 14 files changed, 264 insertions(+), 85 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index d5cfcff1e2..26682d3db8 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -193,18 +193,63 @@ Item { text: "Yaw: " + root.yaw.toFixed(1) } StatText { - visible: root.animStackNames.length > 0; - text: "Anim Stack Names:" + visible: root.animAlphaValues.length > 0; + text: "Anim Alpha Values:" } ListView { width: geoCol.width - height: root.animStackNames.length * 15 - visible: root.animStackNames.length > 0; - model: root.animStackNames + height: root.animAlphaValues.length * 15 + visible: root.animAlphaValues.length > 0; + model: root.animAlphaValues delegate: StatText { - text: modelData.length > 30 - ? modelData.substring(0, 5) + "..." + modelData.substring(modelData.length - 22) - : modelData + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + if (actualText.length > 30) { + return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); + } else { + return actualText; + } + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, 1.0); + } + } + } + StatText { + visible: root.animVars.length > 0; + text: "AnimVars:" + } + ListView { + width: geoCol.width + height: root.animVars.length * 15 + visible: root.animVars.length > 0; + model: root.animVars + delegate: StatText { + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + if (actualText.length > 30) { + return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); + } else { + return actualText; + } + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, 1.0); + } } } StatText { diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 1b26c9b621..62e44645b9 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -207,13 +207,94 @@ void Stats::updateStats(bool force) { // Third column, avatar stats auto myAvatar = avatarManager->getMyAvatar(); - auto animStack = myAvatar->getSkeletonModel()->getRig().getAnimStack(); + auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); - _animStackNames.clear(); - for (auto animStackIterator = animStack.begin(); animStackIterator != animStack.end(); ++animStackIterator) { - _animStackNames << animStackIterator->first + ": " + QString::number(animStackIterator->second,'f',3); + // update animation debug alpha values + QStringList newAnimAlphaValues; + qint64 now = usecTimestampNow(); + for (auto& iter : debugAlphaMap) { + QString key = iter.first; + float alpha = std::get<0>(iter.second); + + auto prevIter = _prevDebugAlphaMap.find(key); + if (prevIter != _prevDebugAlphaMap.end()) { + float prevAlpha = std::get<0>(iter.second); + if (prevAlpha != alpha) { + // change detected: reset timer + _animAlphaValueChangedTimers[key] = now; + } + } else { + // new value: start timer + _animAlphaValueChangedTimers[key] = now; + } + + AnimNodeType type = std::get<1>(iter.second); + if (type == AnimNodeType::Clip) { + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 1.0f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3); + } + } } - emit animStackNamesChanged(); + + _animAlphaValues = newAnimAlphaValues; + _prevDebugAlphaMap = debugAlphaMap; + + emit animAlphaValuesChanged(); + + // update animation anim vars + _animVarsList.clear(); + auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap(); + for (auto& iter : animVars) { + QString key = iter.first; + QString value = iter.second; + + auto prevIter = _prevAnimVars.find(key); + if (prevIter != _prevAnimVars.end()) { + QString prevValue = prevIter->second; + if (value != prevValue) { + // change detected: reset timer + _animVarChangedTimers[key] = now; + } + } else { + // new value: start timer + _animVarChangedTimers[key] = now; + } + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 0.5f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + _animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value; + } + } + _prevAnimVars = animVars; + emit animVarsChanged(); glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); @@ -347,6 +428,7 @@ void Stats::updateStats(bool force) { } sendingModeStream << "] " << serverCount << " servers"; if (movingServerCount > 0) { + sendingModeStream << " "; } else { sendingModeStream << " "; diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index a0453a09c5..3e71c75da1 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -14,6 +14,7 @@ #include #include #include +#include #define STATS_PROPERTY(type, name, initialValue) \ Q_PROPERTY(type name READ name NOTIFY name##Changed) \ @@ -134,7 +135,6 @@ private: \ * @property {number} batchFrameTime - Read-only. * @property {number} engineFrameTime - Read-only. * @property {number} avatarSimulationTime - Read-only. - * @property {string[]} animStackNames - Read-only. * * * @property {number} x @@ -292,7 +292,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(float, batchFrameTime, 0) STATS_PROPERTY(float, engineFrameTime, 0) STATS_PROPERTY(float, avatarSimulationTime, 0) - Q_PROPERTY(QStringList animStackNames READ animStackNames NOTIFY animStackNamesChanged) + Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) + Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) STATS_PROPERTY(int, stylusPicksCount, 0) STATS_PROPERTY(int, rayPicksCount, 0) @@ -326,7 +327,8 @@ public: } QStringList downloadUrls () { return _downloadUrls; } - QStringList animStackNames() { return _animStackNames; } + QStringList animAlphaValues() { return _animAlphaValues; } + QStringList animVars() { return _animVarsList; } public slots: void forceUpdateStats() { updateStats(true); } @@ -1028,12 +1030,8 @@ signals: */ void avatarSimulationTimeChanged(); - /**jsdoc - * Triggered when the value of the animStackNames property changes. - * @function Stats.animStackNamesChanged - * @returns {Signal} - */ - void animStackNamesChanged(); + void animAlphaValuesChanged(); + void animVarsChanged(); /**jsdoc * Triggered when the value of the rectifiedTextureCount property changes. @@ -1336,7 +1334,14 @@ private: QString _monospaceFont; const AudioIOStats* _audioStats; QStringList _downloadUrls = QStringList(); - QStringList _animStackNames = QStringList(); + + QStringList _animAlphaValues = QStringList(); + AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame + std::map _animAlphaValueChangedTimers; // last time alpha value has changed + + QStringList _animVarsList = QStringList(); + std::map _prevAnimVars; // anim vars from previous frame + std::map _animVarChangedTimers; // last time animVar value has changed. }; #endif // hifi_Stats_h diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index e2d79f864d..17ca88123f 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -27,7 +27,7 @@ AnimBlendLinear::~AnimBlendLinear() { const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { _alpha = animVars.lookup(_alphaVar, _alpha); - float parentAlpha = _animStack[_id]; + float parentDebugAlpha = context.getDebugAlpha(_id); if (_children.size() == 0) { for (auto&& pose : _poses) { @@ -35,7 +35,7 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, con } } else if (_children.size() == 1) { _poses = _children[0]->evaluate(animVars, context, dt, triggersOut); - _animStack[_children[0]->getID()] = parentAlpha; + context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); } else { float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); size_t prevPoseIndex = glm::floor(clampedAlpha); @@ -48,12 +48,12 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, con float weight2 = 0.0f; if (prevPoseIndex == nextPoseIndex) { weight2 = 1.0f; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); } else { weight2 = alpha; weight1 = 1.0f - weight2; - _animStack[_children[prevPoseIndex]->getID()] = weight1 * parentAlpha; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); } } processOutputJoints(triggersOut); diff --git a/libraries/animation/src/AnimBlendLinearMove.cpp b/libraries/animation/src/AnimBlendLinearMove.cpp index 42098eb072..07e1c17f77 100644 --- a/libraries/animation/src/AnimBlendLinearMove.cpp +++ b/libraries/animation/src/AnimBlendLinearMove.cpp @@ -62,9 +62,7 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, speed = animVars.lookup("moveForwardSpeed", speed); } _alpha = calculateAlpha(speed, _characteristicSpeeds); - float parentAlpha = _animStack[_id]; - - _animStack["speed"] = speed; + float parentDebugAlpha = context.getDebugAlpha(_id); if (_children.size() == 0) { for (auto&& pose : _poses) { @@ -77,7 +75,7 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, float prevDeltaTime, nextDeltaTime; setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime); - _animStack[_children[0]->getID()] = parentAlpha; + context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); } else { auto clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); auto prevPoseIndex = glm::floor(clampedAlpha); @@ -87,17 +85,11 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime); - // weights are for animation stack debug purposes only. - float weight1 = 0.0f; - float weight2 = 0.0f; if (prevPoseIndex == nextPoseIndex) { - weight2 = 1.0f; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[nextPoseIndex]->getID(), parentDebugAlpha, _children[nextPoseIndex]->getType()); } else { - weight2 = alpha; - weight1 = 1.0f - weight2; - _animStack[_children[prevPoseIndex]->getID()] = weight1 * parentAlpha; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), (1.0f - alpha) * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), alpha * parentDebugAlpha, _children[nextPoseIndex]->getType()); } } diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index e8bf5c34eb..ecfb94a28e 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -14,8 +14,27 @@ #include #include +#include +#include +#include + +enum class AnimNodeType { + Clip = 0, + BlendLinear, + BlendLinearMove, + Overlay, + StateMachine, + Manipulator, + InverseKinematics, + DefaultPose, + TwoBoneIK, + PoleVectorConstraint, + NumTypes +}; + class AnimContext { public: + AnimContext() {} AnimContext(bool enableDebugDrawIKTargets, bool enableDebugDrawIKConstraints, bool enableDebugDrawIKChains, const glm::mat4& geometryToRigMatrix, const glm::mat4& rigToWorldMatrix); @@ -25,6 +44,26 @@ public: const glm::mat4& getGeometryToRigMatrix() const { return _geometryToRigMatrix; } const glm::mat4& getRigToWorldMatrix() const { return _rigToWorldMatrix; } + float getDebugAlpha(const QString& key) const { + auto it = _debugAlphaMap.find(key); + if (it != _debugAlphaMap.end()) { + return std::get<0>(it->second); + } else { + return 1.0f; + } + } + + using DebugAlphaMapValue = std::tuple; + using DebugAlphaMap = std::map; + + void setDebugAlpha(const QString& key, float alpha, AnimNodeType type) const { + _debugAlphaMap[key] = DebugAlphaMapValue(alpha, type); + } + + const DebugAlphaMap& getDebugAlphaMap() const { + return _debugAlphaMap; + } + protected: bool _enableDebugDrawIKTargets { false }; @@ -32,6 +71,9 @@ protected: bool _enableDebugDrawIKChains { false }; glm::mat4 _geometryToRigMatrix; glm::mat4 _rigToWorldMatrix; + + // used for debugging internal state of animation system. + mutable DebugAlphaMap _debugAlphaMap; }; #endif // hifi_AnimContext_h diff --git a/libraries/animation/src/AnimNode.cpp b/libraries/animation/src/AnimNode.cpp index a8e76617ae..f055e6b473 100644 --- a/libraries/animation/src/AnimNode.cpp +++ b/libraries/animation/src/AnimNode.cpp @@ -12,10 +12,6 @@ #include -std::map AnimNode::_animStack = { - {"none", 0.0f} -}; - AnimNode::Pointer AnimNode::getParent() { return _parent.lock(); } diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 1f14889ce4..1a12bb8ddb 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -36,19 +36,7 @@ class QJsonObject; class AnimNode : public std::enable_shared_from_this { public: - enum class Type { - Clip = 0, - BlendLinear, - BlendLinearMove, - Overlay, - StateMachine, - Manipulator, - InverseKinematics, - DefaultPose, - TwoBoneIK, - PoleVectorConstraint, - NumTypes - }; + using Type = AnimNodeType; using Pointer = std::shared_ptr; using ConstPointer = std::shared_ptr; @@ -84,7 +72,6 @@ public: } void setCurrentFrame(float frame); - const std::map getAnimStack() { return _animStack; } template bool traverse(F func) { @@ -127,9 +114,6 @@ protected: std::weak_ptr _parent; std::vector _outputJointNames; - // global available to Stats.h - static std::map _animStack; - // no copies AnimNode(const AnimNode&) = delete; AnimNode& operator=(const AnimNode&) = delete; diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index 90fd425ae5..00ae5e6d39 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -23,9 +23,7 @@ AnimStateMachine::~AnimStateMachine() { const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { - if (_id.contains("userAnimStateMachine")) { - _animStack.clear(); - } + float parentDebugAlpha = context.getDebugAlpha(_id); QString desiredStateID = animVars.lookup(_currentStateVar, _currentState->getID()); if (_currentState->getID() != desiredStateID) { @@ -33,8 +31,6 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co bool foundState = false; for (auto& state : _states) { if (state->getID() == desiredStateID) { - // parenthesis means previous state, which is a snapshot. - _previousStateID = "(" + _currentState->getID() + ")"; switchState(animVars, context, state); foundState = true; break; @@ -48,8 +44,6 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co // evaluate currentState transitions auto desiredState = evaluateTransitions(animVars); if (desiredState != _currentState) { - // parenthesis means previous state, which is a snapshot. - _previousStateID = "(" + _currentState->getID() + ")"; switchState(animVars, context, desiredState); } @@ -57,17 +51,8 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co auto currentStateNode = _children[_currentState->getChildIndex()]; assert(currentStateNode); - if (!_previousStateID.contains("none")) { - _animStack[_previousStateID] = 1.0f - _alpha; - } - if (_duringInterp) { _alpha += _alphaVel * dt; - if (_alpha > 1.0f) { - _animStack[_currentState->getID()] = 1.0f; - } else { - _animStack[_currentState->getID()] = _alpha; - } if (_alpha < 1.0f) { AnimPoseVec* nextPoses = nullptr; AnimPoseVec* prevPoses = nullptr; @@ -88,18 +73,16 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) { ::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), _alpha, &_poses[0]); } + context.setDebugAlpha(_currentState->getID(), _alpha * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType()); } else { _duringInterp = false; - if (_animStack.count(_previousStateID) > 0) { - _animStack.erase(_previousStateID); - } - _previousStateID = "none"; _prevPoses.clear(); _nextPoses.clear(); } } + if (!_duringInterp) { - _animStack[_currentState->getID()] = 1.0f; + context.setDebugAlpha(_currentState->getID(), parentDebugAlpha, _children[_currentState->getChildIndex()]->getType()); _poses = currentStateNode->evaluate(animVars, context, dt, triggersOut); } processOutputJoints(triggersOut); diff --git a/libraries/animation/src/AnimStateMachine.h b/libraries/animation/src/AnimStateMachine.h index b20e5203a1..8e1e1b7bd8 100644 --- a/libraries/animation/src/AnimStateMachine.h +++ b/libraries/animation/src/AnimStateMachine.h @@ -138,7 +138,6 @@ protected: float _alpha = 0.0f; AnimPoseVec _prevPoses; AnimPoseVec _nextPoses; - QString _previousStateID { "none" }; State::Pointer _currentState; std::vector _states; diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 483a7999c9..509462984a 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -67,6 +67,7 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine, } return target; } + void AnimVariantMap::copyVariantsFrom(const AnimVariantMap& other) { for (auto& pair : other._map) { _map[pair.first] = pair.second; @@ -124,3 +125,43 @@ void AnimVariantMap::animVariantMapFromScriptValue(const QScriptValue& source) { } } } + +std::map AnimVariantMap::toDebugMap() const { + std::map result; + for (auto& pair : _map) { + switch (pair.second.getType()) { + case AnimVariant::Type::Bool: + result[pair.first] = QString("%1").arg(pair.second.getBool()); + break; + case AnimVariant::Type::Int: + result[pair.first] = QString("%1").arg(pair.second.getInt()); + break; + case AnimVariant::Type::Float: + result[pair.first] = QString::number(pair.second.getFloat(), 'f', 3); + break; + case AnimVariant::Type::Vec3: { + glm::vec3 value = pair.second.getVec3(); + result[pair.first] = QString("(%1, %2, %3)"). + arg(QString::number(value.x, 'f', 3)). + arg(QString::number(value.y, 'f', 3)). + arg(QString::number(value.z, 'f', 3)); + break; + } + case AnimVariant::Type::Quat: { + glm::quat value = pair.second.getQuat(); + result[pair.first] = QString("(%1, %2, %3, %4)"). + arg(QString::number(value.x, 'f', 3)). + arg(QString::number(value.y, 'f', 3)). + arg(QString::number(value.z, 'f', 3)). + arg(QString::number(value.w, 'f', 3)); + break; + } + case AnimVariant::Type::String: + result[pair.first] = pair.second.getString(); + break; + default: + assert(("invalid AnimVariant::Type", false)); + } + } + return result; +} diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index d383b5abb8..0f921984b1 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -235,6 +235,9 @@ public: void animVariantMapFromScriptValue(const QScriptValue& object); void copyVariantsFrom(const AnimVariantMap& other); + // For stat debugging. + std::map toDebugMap() const; + #ifdef NDEBUG void dump() const { qCDebug(animation) << "AnimVariantMap ="; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 13cf165dac..91d4e0f9d3 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1061,8 +1061,10 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons // animations haven't fully loaded yet. _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); } + _lastAnimVars = _animVars; _animVars.clearTriggers(); _animVars = triggersOut; + _lastContext = context; } applyOverridePoses(); buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index accbcccbbc..95a4b6f40d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -222,7 +222,9 @@ public: // input assumed to be in rig space void computeHeadFromHMD(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut) const; - const std::map getAnimStack() { return _animNode->getAnimStack(); } + // used to debug animation playback + const AnimContext::DebugAlphaMap& getDebugAlphaMap() const { return _lastContext.getDebugAlphaMap(); } + const AnimVariantMap& getAnimVars() const { return _lastAnimVars; } void toggleSmoothPoleVectors() { _smoothPoleVectors = !_smoothPoleVectors; }; signals: @@ -388,6 +390,9 @@ protected: int _rigId; bool _headEnabled { false }; + + AnimContext _lastContext; + AnimVariantMap _lastAnimVars; }; #endif /* defined(__hifi__Rig__) */ From 8420afd14344625b41b636b374f5d0e8c3fe249f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 6 Sep 2018 14:00:33 +1200 Subject: [PATCH 12/20] Fix title not not going back to "Settings" upon Save or Cancel --- interface/resources/qml/hifi/tablet/TabletMenuStack.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml index 4d36a57793..fe636dafa5 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml @@ -1,5 +1,5 @@ // -// MessageDialog.qml +// TabletMenuStack.qml // // Created by Dante Ruiz on 13 Feb 2017 // Copyright 2016 High Fidelity, Inc. @@ -66,7 +66,7 @@ Item { function popSource() { console.log("trying to pop page"); - d.pop(); + closeLastMenu(); } function toModel(items, newMenu) { From ab47e16be1f8bd14c2308b60868b411641d50759 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 6 Sep 2018 14:35:08 +1200 Subject: [PATCH 13/20] Fix up titles and leading white space of some dev menu tablet dialogs --- .../resources/qml/hifi/dialogs/TabletDCDialog.qml | 3 ++- .../qml/hifi/dialogs/TabletEntityStatistics.qml | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletDCDialog.qml b/interface/resources/qml/hifi/dialogs/TabletDCDialog.qml index 1ec7ea3e0e..afe06897df 100644 --- a/interface/resources/qml/hifi/dialogs/TabletDCDialog.qml +++ b/interface/resources/qml/hifi/dialogs/TabletDCDialog.qml @@ -18,6 +18,7 @@ import "../../windows" Rectangle { id: root objectName: "DCConectionTiming" + property string title: "Domain Connection Timing" signal sendToScript(var message); property bool isHMD: false @@ -33,7 +34,7 @@ Rectangle { Row { id: header anchors.top: parent.top - anchors.topMargin: hifi.dimensions.tabletMenuHeader + anchors.topMargin: hifi.dimensions.contentMargin.y anchors.leftMargin: 5 anchors.rightMargin: 5 anchors.left: parent.left diff --git a/interface/resources/qml/hifi/dialogs/TabletEntityStatistics.qml b/interface/resources/qml/hifi/dialogs/TabletEntityStatistics.qml index 7bce460283..24798af21a 100644 --- a/interface/resources/qml/hifi/dialogs/TabletEntityStatistics.qml +++ b/interface/resources/qml/hifi/dialogs/TabletEntityStatistics.qml @@ -18,6 +18,7 @@ import "../../windows" Rectangle { id: root objectName: "EntityStatistics" + property string title: "Entity Statistics" signal sendToScript(var message); property bool isHMD: false @@ -40,6 +41,7 @@ Rectangle { id: scrollView width: parent.width anchors.top: parent.top + anchors.topMargin: hifi.dimensions.contentMargin.y anchors.bottom: parent.bottom anchors.bottomMargin: hifi.dimensions.tabletMenuHeader contentWidth: column.implicitWidth @@ -48,10 +50,15 @@ Rectangle { Column { id: column - anchors.margins: 10 + anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - y: hifi.dimensions.tabletMenuHeader //-bgNavBar + anchors { + topMargin: 0 + leftMargin: 10 + rightMargin: 10 + bottomMargin: 0 + } spacing: 20 TabletEntityStatisticsItem { From a908c1554f4d1a35d88577cfaf47b09d2948645f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Sep 2018 16:04:54 -0700 Subject: [PATCH 14/20] make sure ignoredNode is available before sending packet --- assignment-client/src/avatars/AvatarMixer.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 0289a8aa3f..561afee296 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -655,11 +655,14 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer if (addToIgnore) { senderNode->addIgnoredNode(ignoredUUID); - // send a reliable kill packet to remove the sending avatar for the ignored avatar - auto killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); - killPacket->write(senderNode->getUUID().toRfc4122()); - killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected); - nodeList->sendPacket(std::move(killPacket), *ignoredNode); + if (ignoredNode) { + // send a reliable kill packet to remove the sending avatar for the ignored avatar + auto killPacket = NLPacket::create(PacketType::KillAvatar, + NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); + killPacket->write(senderNode->getUUID().toRfc4122()); + killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected); + nodeList->sendPacket(std::move(killPacket), *ignoredNode); + } } else { senderNode->removeIgnoredNode(ignoredUUID); } From acc7f1f168b734e0d58341a241174ee06b1fcd44 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 6 Sep 2018 16:18:01 -0700 Subject: [PATCH 15/20] Moved AnimStats into its own qml panels. Added state machine tracking as well. --- interface/resources/qml/AnimStats.qml | 157 +++++++++++++++++++ interface/resources/qml/Stats.qml | 35 ++++- interface/src/Application.cpp | 4 + interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/ui/AnimStats.cpp | 141 +++++++++++++++++ interface/src/ui/AnimStats.h | 55 +++++++ interface/src/ui/Stats.cpp | 12 +- interface/src/ui/Stats.h | 12 +- libraries/animation/src/AnimContext.h | 14 ++ libraries/animation/src/AnimStateMachine.cpp | 5 +- libraries/animation/src/AnimStateMachine.h | 1 + libraries/animation/src/Rig.h | 1 + 13 files changed, 427 insertions(+), 12 deletions(-) create mode 100644 interface/resources/qml/AnimStats.qml create mode 100644 interface/src/ui/AnimStats.cpp create mode 100644 interface/src/ui/AnimStats.h diff --git a/interface/resources/qml/AnimStats.qml b/interface/resources/qml/AnimStats.qml new file mode 100644 index 0000000000..35ed3799a6 --- /dev/null +++ b/interface/resources/qml/AnimStats.qml @@ -0,0 +1,157 @@ +import Hifi 1.0 as Hifi +import QtQuick 2.3 +import '.' + +Item { + id: animStats + + anchors.leftMargin: 300 + objectName: "StatsItem" + property int modality: Qt.NonModal + implicitHeight: row.height + implicitWidth: row.width + + Component.onCompleted: { + animStats.parentChanged.connect(fill); + fill(); + } + Component.onDestruction: { + animStats.parentChanged.disconnect(fill); + } + + function fill() { + // This will cause a warning at shutdown, need to find another way to remove + // the warning other than filling the anchors to the parent + anchors.horizontalCenter = parent.horizontalCenter + } + + Hifi.AnimStats { + id: root + objectName: "AnimStats" + implicitHeight: row.height + implicitWidth: row.width + + anchors.horizontalCenter: parent.horizontalCenter + readonly property string bgColor: "#AA111111" + + Row { + id: row + spacing: 8 + + Rectangle { + width: firstCol.width + 8; + height: firstCol.height + 8; + color: root.bgColor; + + Column { + id: firstCol + spacing: 4; x: 4; y: 4; + + StatText { + text: "State Machines:---------------------------------------------------------------------------" + } + ListView { + width: firstCol.width + height: root.animStateMachines.length * 15 + visible: root.animStateMchines.length > 0; + model: root.animStateMachines + delegate: StatText { + text: { + return modelData; + } + } + } + } + } + + Rectangle { + width: secondCol.width + 8 + height: secondCol.height + 8 + color: root.bgColor; + + Column { + id: secondCol + spacing: 4; x: 4; y: 4; + + StatText { + text: "Anim Vars:--------------------------------------------------------------------------------" + } + + ListView { + width: secondCol.width + height: root.animVars.length * 15 + visible: root.animVars.length > 0; + model: root.animVars + delegate: StatText { + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + return actualText; + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); + } + } + } + } + } + + Rectangle { + width: thirdCol.width + 8 + height: thirdCol.height + 8 + color: root.bgColor; + + Column { + id: thirdCol + spacing: 4; x: 4; y: 4; + + StatText { + text: "Alpha Values:--------------------------------------------------------------------------" + } + + ListView { + width: thirdCol.width + height: root.animAlphaValues.length * 15 + visible: root.animAlphaValues.length > 0; + model: root.animAlphaValues + delegate: StatText { + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + return actualText; + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); + } + } + } + + } + } + } + + Connections { + target: root.parent + onWidthChanged: { + root.x = root.parent.width - root.width; + } + } + } + +} diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 26682d3db8..f74f0539c9 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -192,6 +192,25 @@ Item { StatText { text: "Yaw: " + root.yaw.toFixed(1) } + StatText { + visible: root.animStateMachines.length > 0; + text: "Anim State Machines:" + } + ListView { + width: geoCol.width + height: root.animStateMachines.length * 15 + visible: root.animStateMchines.length > 0; + model: root.animStateMachines + delegate: StatText { + text: { + if (modelData.length > 30) { + return modelData.substring(0, 5) + "..." + modelData.substring(.length - 22); + } else { + return modelData; + } + } + } + } StatText { visible: root.animAlphaValues.length > 0; text: "Anim Alpha Values:" @@ -216,9 +235,11 @@ Item { } color: { var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, 1.0); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); } } } @@ -246,9 +267,11 @@ Item { } color: { var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, 1.0); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fe67ec5cb..40edcdbd76 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -195,6 +195,7 @@ #include "ui/SnapshotAnimated.h" #include "ui/StandAloneJSConsole.h" #include "ui/Stats.h" +#include "ui/AnimStats.h" #include "ui/UpdateDialog.h" #include "ui/overlays/Overlays.h" #include "ui/DomainConnectionModel.h" @@ -3081,8 +3082,10 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { Stats::show(); + AnimStats::show(); auto surfaceContext = DependencyManager::get()->getSurfaceContext(); surfaceContext->setContextProperty("Stats", Stats::getInstance()); + surfaceContext->setContextProperty("AnimStats", AnimStats::getInstance()); #if !defined(Q_OS_ANDROID) auto offscreenUi = DependencyManager::get(); @@ -4618,6 +4621,7 @@ void Application::idle() { checkChangeCursor(); Stats::getInstance()->updateStats(); + AnimStats::getInstance()->updateStats(); // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a6ba983ab5..f7be6d17ef 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -737,6 +737,7 @@ Menu::Menu() { // Developer > Stats addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats); + addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AnimStats); // Settings > Enable Speech Control API #if defined(Q_OS_MAC) || defined(Q_OS_WIN) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c4ea3734f5..031ee2561c 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -197,6 +197,7 @@ namespace MenuOption { const QString SMIEyeTracking = "SMI Eye Tracking"; const QString SparseTextureManagement = "Enable Sparse Texture Management"; const QString Stats = "Show Statistics"; + const QString AnimStats = "Show Animation Stats"; const QString StopAllScripts = "Stop All Scripts"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString ThirdPerson = "Third Person"; diff --git a/interface/src/ui/AnimStats.cpp b/interface/src/ui/AnimStats.cpp new file mode 100644 index 0000000000..7b4778e365 --- /dev/null +++ b/interface/src/ui/AnimStats.cpp @@ -0,0 +1,141 @@ +// +// Created by Anthony J. Thibault 2018/08/06 +// Copyright 2018 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 "AnimStats.h" + +#include +#include +#include "Menu.h" + +HIFI_QML_DEF(AnimStats) + +static AnimStats* INSTANCE{ nullptr }; + +AnimStats* AnimStats::getInstance() { + Q_ASSERT(INSTANCE); + return INSTANCE; +} + +AnimStats::AnimStats(QQuickItem* parent) : QQuickItem(parent) { + INSTANCE = this; +} + +void AnimStats::updateStats(bool force) { + QQuickItem* parent = parentItem(); + if (!force) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::AnimStats)) { + if (parent->isVisible()) { + parent->setVisible(false); + } + return; + } else if (!parent->isVisible()) { + parent->setVisible(true); + } + } + + auto avatarManager = DependencyManager::get(); + auto myAvatar = avatarManager->getMyAvatar(); + auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); + + // update animation debug alpha values + QStringList newAnimAlphaValues; + qint64 now = usecTimestampNow(); + for (auto& iter : debugAlphaMap) { + QString key = iter.first; + float alpha = std::get<0>(iter.second); + + auto prevIter = _prevDebugAlphaMap.find(key); + if (prevIter != _prevDebugAlphaMap.end()) { + float prevAlpha = std::get<0>(iter.second); + if (prevAlpha != alpha) { + // change detected: reset timer + _animAlphaValueChangedTimers[key] = now; + } + } else { + // new value: start timer + _animAlphaValueChangedTimers[key] = now; + } + + AnimNodeType type = std::get<1>(iter.second); + if (type == AnimNodeType::Clip) { + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 1.0f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3); + } + } + } + + _animAlphaValues = newAnimAlphaValues; + _prevDebugAlphaMap = debugAlphaMap; + + emit animAlphaValuesChanged(); + + // update animation anim vars + _animVarsList.clear(); + auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap(); + for (auto& iter : animVars) { + QString key = iter.first; + QString value = iter.second; + + auto prevIter = _prevAnimVars.find(key); + if (prevIter != _prevAnimVars.end()) { + QString prevValue = prevIter->second; + if (value != prevValue) { + // change detected: reset timer + _animVarChangedTimers[key] = now; + } + } else { + // new value: start timer + _animVarChangedTimers[key] = now; + } + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 0.5f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + _animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value; + } + } + _prevAnimVars = animVars; + emit animVarsChanged(); + + // animation state machines + _animStateMachines.clear(); + auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap(); + for (auto& iter : stateMachineMap) { + _animStateMachines << iter.second; + } + emit animStateMachinesChanged(); +} + + diff --git a/interface/src/ui/AnimStats.h b/interface/src/ui/AnimStats.h new file mode 100644 index 0000000000..1a6795b498 --- /dev/null +++ b/interface/src/ui/AnimStats.h @@ -0,0 +1,55 @@ +// +// Created by Anthony J. Thibault 2018/08/06 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AnimStats_h +#define hifi_AnimStats_h + +#include +#include + +class AnimStats : public QQuickItem { + Q_OBJECT + HIFI_QML_DECL + + Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) + Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) + Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) + +public: + static AnimStats* getInstance(); + + AnimStats(QQuickItem* parent = nullptr); + + void updateStats(bool force = false); + + QStringList animAlphaValues() { return _animAlphaValues; } + QStringList animVars() { return _animVarsList; } + QStringList animStateMachines() { return _animStateMachines; } + +public slots: + void forceUpdateStats() { updateStats(true); } + +signals: + + void animAlphaValuesChanged(); + void animVarsChanged(); + void animStateMachinesChanged(); + +private: + QStringList _animAlphaValues; + AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame + std::map _animAlphaValueChangedTimers; // last time alpha value has changed + + QStringList _animVarsList; + std::map _prevAnimVars; // anim vars from previous frame + std::map _animVarChangedTimers; // last time animVar value has changed. + + QStringList _animStateMachines; +}; + +#endif // hifi_AnimStats_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 62e44645b9..bfb83f10f8 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -239,7 +239,7 @@ void Stats::updateStats(bool force) { if (secondsElapsed < LIT_TIME) { grayScale = 1.0f; } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; } else { grayScale = 0.0f; } @@ -283,7 +283,7 @@ void Stats::updateStats(bool force) { if (secondsElapsed < LIT_TIME) { grayScale = 1.0f; } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; } else { grayScale = 0.0f; } @@ -296,6 +296,14 @@ void Stats::updateStats(bool force) { _prevAnimVars = animVars; emit animVarsChanged(); + // animation state machines + _animStateMachines.clear(); + auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap(); + for (auto& iter : stateMachineMap) { + _animStateMachines << iter.second; + } + emit animStateMachinesChanged(); + glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getWorldVelocity()), 0.01f); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 3e71c75da1..1febfff8b5 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -184,6 +184,7 @@ class Stats : public QQuickItem { HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) + Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) STATS_PROPERTY(int, serverCount, 0) @@ -294,6 +295,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(float, avatarSimulationTime, 0) Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) + Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) STATS_PROPERTY(int, stylusPicksCount, 0) STATS_PROPERTY(int, rayPicksCount, 0) @@ -329,6 +331,7 @@ public: QStringList downloadUrls () { return _downloadUrls; } QStringList animAlphaValues() { return _animAlphaValues; } QStringList animVars() { return _animVarsList; } + QStringList animStateMachines() { return _animStateMachines; } public slots: void forceUpdateStats() { updateStats(true); } @@ -1032,6 +1035,7 @@ signals: void animAlphaValuesChanged(); void animVarsChanged(); + void animStateMachinesChanged(); /**jsdoc * Triggered when the value of the rectifiedTextureCount property changes. @@ -1333,15 +1337,17 @@ private: bool _showGameUpdateStats{ false }; QString _monospaceFont; const AudioIOStats* _audioStats; - QStringList _downloadUrls = QStringList(); + QStringList _downloadUrls; - QStringList _animAlphaValues = QStringList(); + QStringList _animAlphaValues; AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame std::map _animAlphaValueChangedTimers; // last time alpha value has changed - QStringList _animVarsList = QStringList(); + QStringList _animVarsList; std::map _prevAnimVars; // anim vars from previous frame std::map _animVarChangedTimers; // last time animVar value has changed. + + QStringList _animStateMachines; }; #endif // hifi_Stats_h diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index ecfb94a28e..b30421ae84 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -64,6 +64,19 @@ public: return _debugAlphaMap; } + using DebugStateMachineMapValue = QString; + using DebugStateMachineMap = std::map; + + void addStateMachineInfo(const QString& stateMachineName, const QString& currentState, const QString& previousState, bool duringInterp, float alpha) const { + if (duringInterp) { + _stateMachineMap[stateMachineName] = QString("%1: %2 -> %3 (%4)").arg(stateMachineName).arg(previousState).arg(currentState).arg(QString::number(alpha, 'f', 2)); + } else { + _stateMachineMap[stateMachineName] = QString("%1: %2").arg(stateMachineName).arg(currentState); + } + } + + const DebugStateMachineMap& getStateMachineMap() const { return _stateMachineMap; } + protected: bool _enableDebugDrawIKTargets { false }; @@ -74,6 +87,7 @@ protected: // used for debugging internal state of animation system. mutable DebugAlphaMap _debugAlphaMap; + mutable DebugStateMachineMap _stateMachineMap; }; #endif // hifi_AnimContext_h diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index 00ae5e6d39..7f46cd614a 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -87,10 +87,13 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co } processOutputJoints(triggersOut); + context.addStateMachineInfo(_id, _currentState->getID(), _previousState->getID(), _duringInterp, _alpha); + return _poses; } void AnimStateMachine::setCurrentState(State::Pointer state) { + _previousState = _currentState ? _currentState : state; _currentState = state; } @@ -135,7 +138,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID() << "duration =" << duration << "targetFrame =" << desiredState->_interpTarget << "interpType = " << (int)_interpType; #endif - _currentState = desiredState; + setCurrentState(desiredState); } AnimStateMachine::State::Pointer AnimStateMachine::evaluateTransitions(const AnimVariantMap& animVars) const { diff --git a/libraries/animation/src/AnimStateMachine.h b/libraries/animation/src/AnimStateMachine.h index 8e1e1b7bd8..713c659a1d 100644 --- a/libraries/animation/src/AnimStateMachine.h +++ b/libraries/animation/src/AnimStateMachine.h @@ -140,6 +140,7 @@ protected: AnimPoseVec _nextPoses; State::Pointer _currentState; + State::Pointer _previousState; std::vector _states; QString _currentStateVar; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 95a4b6f40d..48f00d4e5d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -225,6 +225,7 @@ public: // used to debug animation playback const AnimContext::DebugAlphaMap& getDebugAlphaMap() const { return _lastContext.getDebugAlphaMap(); } const AnimVariantMap& getAnimVars() const { return _lastAnimVars; } + const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); } void toggleSmoothPoleVectors() { _smoothPoleVectors = !_smoothPoleVectors; }; signals: From 22df1b3bc699c1917a5b43530e4ab60b5a06d604 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Sep 2018 17:00:12 -0700 Subject: [PATCH 16/20] Add comment to Assets.sendFakeHandshake about excluding jsdoc --- libraries/script-engine/src/AssetScriptingInterface.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 72d6901fb5..0e05a563b2 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -108,6 +108,10 @@ public: Q_INVOKABLE void setBakingEnabled(QString path, bool enabled, QScriptValue callback); #if (PR_BUILD || DEV_BUILD) + /** + * This function is purely for development purposes, and not meant for use in a + * production context. It is not a public-facing API, so it should not contain jsdoc. + */ Q_INVOKABLE void sendFakedHandshake(); #endif From 6508533a15fd3035593535ae87bdb6316b8d6eb1 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 6 Sep 2018 17:58:40 -0700 Subject: [PATCH 17/20] Remove anim stats from plain ole stats. There are still present in anim stats tho. --- interface/resources/qml/Stats.qml | 83 -------------------------- interface/src/ui/Stats.cpp | 98 ------------------------------- interface/src/ui/Stats.h | 25 +------- 3 files changed, 1 insertion(+), 205 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index f74f0539c9..1a29ce87df 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -192,89 +192,6 @@ Item { StatText { text: "Yaw: " + root.yaw.toFixed(1) } - StatText { - visible: root.animStateMachines.length > 0; - text: "Anim State Machines:" - } - ListView { - width: geoCol.width - height: root.animStateMachines.length * 15 - visible: root.animStateMchines.length > 0; - model: root.animStateMachines - delegate: StatText { - text: { - if (modelData.length > 30) { - return modelData.substring(0, 5) + "..." + modelData.substring(.length - 22); - } else { - return modelData; - } - } - } - } - StatText { - visible: root.animAlphaValues.length > 0; - text: "Anim Alpha Values:" - } - ListView { - width: geoCol.width - height: root.animAlphaValues.length * 15 - visible: root.animAlphaValues.length > 0; - model: root.animAlphaValues - delegate: StatText { - text: { - var actualText = modelData.split("|")[1]; - if (actualText) { - if (actualText.length > 30) { - return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); - } else { - return actualText; - } - } else { - return modelData; - } - } - color: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(1.0, 1.0, 1.0, grayScale); - } - styleColor: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.0, 0.0, 0.0, grayScale); - } - } - } - StatText { - visible: root.animVars.length > 0; - text: "AnimVars:" - } - ListView { - width: geoCol.width - height: root.animVars.length * 15 - visible: root.animVars.length > 0; - model: root.animVars - delegate: StatText { - text: { - var actualText = modelData.split("|")[1]; - if (actualText) { - if (actualText.length > 30) { - return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); - } else { - return actualText; - } - } else { - return modelData; - } - } - color: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(1.0, 1.0, 1.0, grayScale); - } - styleColor: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.0, 0.0, 0.0, grayScale); - } - } - } StatText { visible: root.expanded; text: "Avatar Mixer In: " + root.avatarMixerInKbps + " kbps, " + diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index bfb83f10f8..d51b90f15d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -207,103 +207,6 @@ void Stats::updateStats(bool force) { // Third column, avatar stats auto myAvatar = avatarManager->getMyAvatar(); - auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); - - // update animation debug alpha values - QStringList newAnimAlphaValues; - qint64 now = usecTimestampNow(); - for (auto& iter : debugAlphaMap) { - QString key = iter.first; - float alpha = std::get<0>(iter.second); - - auto prevIter = _prevDebugAlphaMap.find(key); - if (prevIter != _prevDebugAlphaMap.end()) { - float prevAlpha = std::get<0>(iter.second); - if (prevAlpha != alpha) { - // change detected: reset timer - _animAlphaValueChangedTimers[key] = now; - } - } else { - // new value: start timer - _animAlphaValueChangedTimers[key] = now; - } - - AnimNodeType type = std::get<1>(iter.second); - if (type == AnimNodeType::Clip) { - - // figure out the grayScale color of this line. - const float LIT_TIME = 2.0f; - const float FADE_OUT_TIME = 1.0f; - float grayScale = 0.0f; - float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; - if (secondsElapsed < LIT_TIME) { - grayScale = 1.0f; - } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; - } else { - grayScale = 0.0f; - } - - if (grayScale > 0.0f) { - // append grayScaleColor to start of debug string - newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3); - } - } - } - - _animAlphaValues = newAnimAlphaValues; - _prevDebugAlphaMap = debugAlphaMap; - - emit animAlphaValuesChanged(); - - // update animation anim vars - _animVarsList.clear(); - auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap(); - for (auto& iter : animVars) { - QString key = iter.first; - QString value = iter.second; - - auto prevIter = _prevAnimVars.find(key); - if (prevIter != _prevAnimVars.end()) { - QString prevValue = prevIter->second; - if (value != prevValue) { - // change detected: reset timer - _animVarChangedTimers[key] = now; - } - } else { - // new value: start timer - _animVarChangedTimers[key] = now; - } - - // figure out the grayScale color of this line. - const float LIT_TIME = 2.0f; - const float FADE_OUT_TIME = 0.5f; - float grayScale = 0.0f; - float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; - if (secondsElapsed < LIT_TIME) { - grayScale = 1.0f; - } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; - } else { - grayScale = 0.0f; - } - - if (grayScale > 0.0f) { - // append grayScaleColor to start of debug string - _animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value; - } - } - _prevAnimVars = animVars; - emit animVarsChanged(); - - // animation state machines - _animStateMachines.clear(); - auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap(); - for (auto& iter : stateMachineMap) { - _animStateMachines << iter.second; - } - emit animStateMachinesChanged(); - glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getWorldVelocity()), 0.01f); @@ -436,7 +339,6 @@ void Stats::updateStats(bool force) { } sendingModeStream << "] " << serverCount << " servers"; if (movingServerCount > 0) { - sendingModeStream << " "; } else { sendingModeStream << " "; diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 1febfff8b5..ae608cfddb 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -14,7 +14,6 @@ #include #include #include -#include #define STATS_PROPERTY(type, name, initialValue) \ Q_PROPERTY(type name READ name NOTIFY name##Changed) \ @@ -184,7 +183,6 @@ class Stats : public QQuickItem { HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) - Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) STATS_PROPERTY(int, serverCount, 0) @@ -293,9 +291,6 @@ class Stats : public QQuickItem { STATS_PROPERTY(float, batchFrameTime, 0) STATS_PROPERTY(float, engineFrameTime, 0) STATS_PROPERTY(float, avatarSimulationTime, 0) - Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) - Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) - Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) STATS_PROPERTY(int, stylusPicksCount, 0) STATS_PROPERTY(int, rayPicksCount, 0) @@ -329,9 +324,6 @@ public: } QStringList downloadUrls () { return _downloadUrls; } - QStringList animAlphaValues() { return _animAlphaValues; } - QStringList animVars() { return _animVarsList; } - QStringList animStateMachines() { return _animStateMachines; } public slots: void forceUpdateStats() { updateStats(true); } @@ -1033,10 +1025,6 @@ signals: */ void avatarSimulationTimeChanged(); - void animAlphaValuesChanged(); - void animVarsChanged(); - void animStateMachinesChanged(); - /**jsdoc * Triggered when the value of the rectifiedTextureCount property changes. * @function Stats.rectifiedTextureCountChanged @@ -1051,7 +1039,6 @@ signals: */ void decimatedTextureCountChanged(); - // QQuickItem signals. /**jsdoc @@ -1337,17 +1324,7 @@ private: bool _showGameUpdateStats{ false }; QString _monospaceFont; const AudioIOStats* _audioStats; - QStringList _downloadUrls; - - QStringList _animAlphaValues; - AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame - std::map _animAlphaValueChangedTimers; // last time alpha value has changed - - QStringList _animVarsList; - std::map _prevAnimVars; // anim vars from previous frame - std::map _animVarChangedTimers; // last time animVar value has changed. - - QStringList _animStateMachines; + QStringList _downloadUrls = QStringList(); }; #endif // hifi_Stats_h From 5a059e93184acc28e21262b8080c6341a7559403 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 7 Sep 2018 09:44:19 -0700 Subject: [PATCH 18/20] Fix for build failure on linux and android. --- libraries/animation/src/AnimContext.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index b30421ae84..c455dd9c8f 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include enum class AnimNodeType { From f9ec53a2e6ac9bcd64d5ab0d53c2c868aa7fde27 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 7 Sep 2018 10:25:26 -0700 Subject: [PATCH 19/20] fix bloom on edges --- libraries/render-utils/src/DeferredFramebuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 2df89b8808..1906375654 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -73,7 +73,7 @@ void DeferredFramebuffer::allocate() { _deferredFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); - auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); + auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP); _lightingTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, gpu::Texture::SINGLE_MIP, smoothSampler); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("lighting")); From 32e2a244a110a7d16a2afd5e319478d6f0f41ac7 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 7 Sep 2018 11:44:35 -0700 Subject: [PATCH 20/20] detailed profile range for avatar unpacking --- libraries/avatars/src/AvatarHashMap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index c1246866dc..1383939b8b 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -21,6 +21,7 @@ #include "AvatarLogging.h" #include "AvatarTraits.h" +#include "Profile.h" void AvatarReplicas::addReplica(const QUuid& parentID, AvatarSharedPointer replica) { if (parentID == QUuid()) { @@ -214,6 +215,7 @@ AvatarSharedPointer AvatarHashMap::findAvatar(const QUuid& sessionUUID) const { } void AvatarHashMap::processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode) { + DETAILED_PROFILE_RANGE(network, __FUNCTION__); PerformanceTimer perfTimer("receiveAvatar"); // enumerate over all of the avatars in this packet // only add them if mixerWeakPointer points to something (meaning that mixer is still around)