History

Merge branch 'master' of github.com:highfidelity/hifi into audio/parity

Zach Pomerantz committed 9 years ago

Commit a8f69bb2 parents e7da007 ae81738385 files · +9641 −4012Browse files

Showing the changes to interface/src/Application.cpp (1 of 385 files). Show all

Unified · Split

interface/src/Application.cpp+283−241
@@ -11,6 +11,9 @@ · 10 unmodified lines
11 11
12#include "Application.h"12#include "Application.h"
13 13
14#include <chrono>
15#include <thread>
16
14#include <gl/Config.h>17#include <gl/Config.h>
15#include <glm/glm.hpp>18#include <glm/glm.hpp>
16#include <glm/gtx/component_wise.hpp>19#include <glm/gtx/component_wise.hpp>
@@ -69,6 +72,7 @@ · 52 unmodified lines
69#include <ErrorDialog.h>72#include <ErrorDialog.h>
70#include <FileScriptingInterface.h>73#include <FileScriptingInterface.h>
71#include <Finally.h>74#include <Finally.h>
75#include <FingerprintUtils.h>
72#include <FramebufferCache.h>76#include <FramebufferCache.h>
73#include <gpu/Batch.h>77#include <gpu/Batch.h>
74#include <gpu/Context.h>78#include <gpu/Context.h>
@@ -110,7 +114,9 @@ · 35 unmodified lines
110#include <render/RenderFetchCullSortTask.h>114#include <render/RenderFetchCullSortTask.h>
111#include <RenderDeferredTask.h>115#include <RenderDeferredTask.h>
112#include <RenderForwardTask.h>116#include <RenderForwardTask.h>
117#include <RenderViewTask.h>
113#include <ResourceCache.h>118#include <ResourceCache.h>
119#include <ResourceRequest.h>
114#include <SandboxUtils.h>120#include <SandboxUtils.h>
115#include <SceneScriptingInterface.h>121#include <SceneScriptingInterface.h>
116#include <ScriptEngines.h>122#include <ScriptEngines.h>
@@ -144,10 +150,8 @@ · 27 unmodified lines
144#include "InterfaceLogging.h"150#include "InterfaceLogging.h"
145#include "LODManager.h"151#include "LODManager.h"
146#include "ModelPackager.h"152#include "ModelPackager.h"
147#include "networking/HFWebEngineProfile.h"
148#include "networking/HFTabletWebEngineProfile.h"
149#include "networking/FileTypeProfile.h"
150#include "scripting/Audio.h"153#include "scripting/Audio.h"
154#include "networking/CloseEventSender.h"
151#include "scripting/TestScriptingInterface.h"155#include "scripting/TestScriptingInterface.h"
152#include "scripting/AccountScriptingInterface.h"156#include "scripting/AccountScriptingInterface.h"
153#include "scripting/AssetMappingsScriptingInterface.h"157#include "scripting/AssetMappingsScriptingInterface.h"
@@ -244,6 +248,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda · 90 unmodified lines
244Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);248Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
245 249
246static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";250static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
251static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
252static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
247 253
248static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";254static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
249 255
@@ -438,6 +444,10 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 188 unmodified lines
438 const char* portStr = getCmdOption(argc, constArgv, "--listenPort");444 const char* portStr = getCmdOption(argc, constArgv, "--listenPort");
439 const int listenPort = portStr ? atoi(portStr) : INVALID_PORT;445 const int listenPort = portStr ? atoi(portStr) : INVALID_PORT;
440 446
447 static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
448 bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
449 bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
450
441 Setting::init();451 Setting::init();
442 452
443 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {453 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
@@ -458,10 +468,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 14 unmodified lines
458 QCoreApplication::addLibraryPath(audioDLLPath);468 QCoreApplication::addLibraryPath(audioDLLPath);
459#endif469#endif
460 470
461 static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
462 bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
463 bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
464
465 DependencyManager::registerInheritance<LimitedNodeList, NodeList>();471 DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
466 DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();472 DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
467 DependencyManager::registerInheritance<EntityDynamicFactoryInterface, InterfaceDynamicFactory>();473 DependencyManager::registerInheritance<EntityDynamicFactoryInterface, InterfaceDynamicFactory>();
@@ -536,6 +542,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 68 unmodified lines
536 DependencyManager::set<AvatarBookmarks>();542 DependencyManager::set<AvatarBookmarks>();
537 DependencyManager::set<LocationBookmarks>();543 DependencyManager::set<LocationBookmarks>();
538 DependencyManager::set<Snapshot>();544 DependencyManager::set<Snapshot>();
545 DependencyManager::set<CloseEventSender>();
539 546
540 return previousSessionCrashed;547 return previousSessionCrashed;
541}548}
@@ -649,6 +656,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 107 unmodified lines
649 Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us656 Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us
650 657
651 auto nodeList = DependencyManager::get<NodeList>();658 auto nodeList = DependencyManager::get<NodeList>();
659 nodeList->startThread();
652 660
653 // Set up a watchdog thread to intentionally crash the application on deadlocks661 // Set up a watchdog thread to intentionally crash the application on deadlocks
654 _deadlockWatchdogThread = new DeadlockWatchdogThread();662 _deadlockWatchdogThread = new DeadlockWatchdogThread();
@@ -674,25 +682,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 19 unmodified lines
674 682
675 updateHeartbeat();683 updateHeartbeat();
676 684
677 // start the nodeThread so its event loop is running
678 QThread* nodeThread = new QThread(this);
679 nodeThread->setObjectName("NodeList Thread");
680 nodeThread->start();
681
682 // make sure the node thread is given highest priority
683 nodeThread->setPriority(QThread::TimeCriticalPriority);
684
685 // setup a timer for domain-server check ins685 // setup a timer for domain-server check ins
686 QTimer* domainCheckInTimer = new QTimer(nodeList.data());686 QTimer* domainCheckInTimer = new QTimer(nodeList.data());
687 connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);687 connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
688 domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);688 domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
689 689
690 // put the NodeList and datagram processing on the node thread
691 nodeList->moveToThread(nodeThread);
692
693 // put the audio processing on a separate thread
694 QThread* audioThread = new QThread();
695 audioThread->setObjectName("Audio Thread");
696 690
697 auto audioIO = DependencyManager::get<AudioClient>();691 auto audioIO = DependencyManager::get<AudioClient>();
698 audioIO->setPositionGetter([]{692 audioIO->setPositionGetter([]{
@@ -708,7 +702,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 9 unmodified lines
708 return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;702 return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;
709 });703 });
710 704
711 audioIO->moveToThread(audioThread);
712 recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) {705 recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) {
713 audioIO->handleRecordedAudioInput(frame->data);706 audioIO->handleRecordedAudioInput(frame->data);
714 });707 });
@@ -720,11 +713,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 5 unmodified lines
720 recorder->recordFrame(AUDIO_FRAME_TYPE, audio);713 recorder->recordFrame(AUDIO_FRAME_TYPE, audio);
721 }714 }
722 });715 });
723 716 audioIO->startThread();
724 connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start);
725 connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit);
726 connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
727 audioThread->start();
728 717
729 auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface, scripting::Audio>();718 auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface, scripting::Audio>();
730 connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);719 connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);
@@ -750,12 +739,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 19 unmodified lines
750 updateHeartbeat();739 updateHeartbeat();
751 740
752 // Setup MessagesClient741 // Setup MessagesClient
753 auto messagesClient = DependencyManager::get<MessagesClient>();742 DependencyManager::get<MessagesClient>()->startThread();
754 QThread* messagesThread = new QThread;
755 messagesThread->setObjectName("Messages Client Thread");
756 messagesClient->moveToThread(messagesThread);
757 connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init);
758 messagesThread->start();
759 743
760 const DomainHandler& domainHandler = nodeList->getDomainHandler();744 const DomainHandler& domainHandler = nodeList->getDomainHandler();
761 745
@@ -950,6 +934,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 188 unmodified lines
950 properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;934 properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
951 }935 }
952 936
937 // add firstRun flag from settings to launch event
938 Setting::Handle<bool> firstRun { Settings::firstRun, true };
939 properties["first_run"] = firstRun.get();
940
941 // add the user's machine ID to the launch event
942 properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
943
953 UserActivityLogger::getInstance().logAction("launch", properties);944 UserActivityLogger::getInstance().logAction("launch", properties);
954 945
955 // Tell our entity edit sender about our known jurisdictions946 // Tell our entity edit sender about our known jurisdictions
@@ -1309,6 +1300,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 353 unmodified lines
1309 properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();1300 properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();
1310 properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();1301 properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();
1311 1302
1303 properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer);
1304
1312 auto nodeList = DependencyManager::get<NodeList>();1305 auto nodeList = DependencyManager::get<NodeList>();
1313 SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);1306 SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);
1314 SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);1307 SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
@@ -1322,8 +1315,61 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 7 unmodified lines
1322 properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;1315 properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;
1323 1316
1324 auto loadingRequests = ResourceCache::getLoadingRequests();1317 auto loadingRequests = ResourceCache::getLoadingRequests();
1318
1319 QJsonArray loadingRequestsStats;
1320 for (const auto& request : loadingRequests) {
1321 QJsonObject requestStats;
1322 requestStats["filename"] = request->getURL().fileName();
1323 requestStats["received"] = request->getBytesReceived();
1324 requestStats["total"] = request->getBytesTotal();
1325 requestStats["attempts"] = (int)request->getDownloadAttempts();
1326 loadingRequestsStats.append(requestStats);
1327 }
1328
1325 properties["active_downloads"] = loadingRequests.size();1329 properties["active_downloads"] = loadingRequests.size();
1326 properties["pending_downloads"] = ResourceCache::getPendingRequestCount();1330 properties["pending_downloads"] = ResourceCache::getPendingRequestCount();
1331 properties["active_downloads_details"] = loadingRequestsStats;
1332
1333 auto statTracker = DependencyManager::get<StatTracker>();
1334
1335 properties["processing_resources"] = statTracker->getStat("Processing").toInt();
1336 properties["pending_processing_resources"] = statTracker->getStat("PendingProcessing").toInt();
1337
1338 QJsonObject startedRequests;
1339 startedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt();
1340 startedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt();
1341 startedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt();
1342 startedRequests["total"] = startedRequests["atp"].toInt() + startedRequests["http"].toInt()
1343 + startedRequests["file"].toInt();
1344 properties["started_requests"] = startedRequests;
1345
1346 QJsonObject successfulRequests;
1347 successfulRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt();
1348 successfulRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt();
1349 successfulRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt();
1350 successfulRequests["total"] = successfulRequests["atp"].toInt() + successfulRequests["http"].toInt()
1351 + successfulRequests["file"].toInt();
1352 properties["successful_requests"] = successfulRequests;
1353
1354 QJsonObject failedRequests;
1355 failedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt();
1356 failedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt();
1357 failedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt();
1358 failedRequests["total"] = failedRequests["atp"].toInt() + failedRequests["http"].toInt()
1359 + failedRequests["file"].toInt();
1360 properties["failed_requests"] = failedRequests;
1361
1362 QJsonObject cacheRequests;
1363 cacheRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt();
1364 cacheRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_CACHE).toInt();
1365 cacheRequests["total"] = cacheRequests["atp"].toInt() + cacheRequests["http"].toInt();
1366 properties["cache_requests"] = cacheRequests;
1367
1368 QJsonObject atpMappingRequests;
1369 atpMappingRequests["started"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_STARTED).toInt();
1370 atpMappingRequests["failed"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_FAILED).toInt();
1371 atpMappingRequests["successful"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_SUCCESS).toInt();
1372 properties["atp_mapping_requests"] = atpMappingRequests;
1327 1373
1328 properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;1374 properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
1329 1375
@@ -1339,9 +1385,43 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 9 unmodified lines
1339 properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount;1385 properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount;
1340 properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount;1386 properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount;
1341 1387
1388 NodeToOctreeSceneStats* octreeServerSceneStats = getOcteeSceneStats();
1389 unsigned long totalServerOctreeElements = 0;
1390 for (NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) {
1391 totalServerOctreeElements += i->second.getTotalElements();
1392 }
1393
1394 properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount();
1395 properties["server_octree_elements"] = (qint64) totalServerOctreeElements;
1396
1342 properties["active_display_plugin"] = getActiveDisplayPlugin()->getName();1397 properties["active_display_plugin"] = getActiveDisplayPlugin()->getName();
1343 properties["using_hmd"] = isHMDMode();1398 properties["using_hmd"] = isHMDMode();
1344 1399
1400 _autoSwitchDisplayModeSupportedHMDPlugin = nullptr;
1401 foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
1402 if (displayPlugin->isHmd() &&
1403 displayPlugin->getSupportsAutoSwitch()) {
1404 _autoSwitchDisplayModeSupportedHMDPlugin = displayPlugin;
1405 _autoSwitchDisplayModeSupportedHMDPluginName =
1406 _autoSwitchDisplayModeSupportedHMDPlugin->getName();
1407 _previousHMDWornStatus =
1408 _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible();
1409 break;
1410 }
1411 }
1412
1413 if (_autoSwitchDisplayModeSupportedHMDPlugin) {
1414 if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin &&
1415 !_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
1416 startHMDStandBySession();
1417 }
1418 // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly.
1419 // If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode.
1420 QTimer* autoSwitchDisplayModeTimer = new QTimer(this);
1421 connect(autoSwitchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode()));
1422 autoSwitchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_WORN_STATUS);
1423 }
1424
1345 auto glInfo = getGLContextData();1425 auto glInfo = getGLContextData();
1346 properties["gl_info"] = glInfo;1426 properties["gl_info"] = glInfo;
1347 properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize());1427 properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize());
@@ -1364,6 +1444,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 16 unmodified lines
1364 lastLeftHandPose = leftHandPose;1444 lastLeftHandPose = leftHandPose;
1365 lastRightHandPose = rightHandPose;1445 lastRightHandPose = rightHandPose;
1366 1446
1447 properties["local_socket_changes"] = DependencyManager::get<StatTracker>()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt();
1448
1367 UserActivityLogger::getInstance().logAction("stats", properties);1449 UserActivityLogger::getInstance().logAction("stats", properties);
1368 });1450 });
1369 sendStatsTimer->start();1451 sendStatsTimer->start();
@@ -1463,6 +1545,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 93 unmodified lines
1463 updateSystemTabletMode();1545 updateSystemTabletMode();
1464 1546
1465 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);1547 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
1548
1549 qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
1466}1550}
1467 1551
1468void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {1552void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
@@ -1571,6 +1655,12 @@ void Application::aboutToQuit() { · 102 unmodified lines
1571 }1655 }
1572 1656
1573 getActiveDisplayPlugin()->deactivate();1657 getActiveDisplayPlugin()->deactivate();
1658 if (_autoSwitchDisplayModeSupportedHMDPlugin
1659 && _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
1660 _autoSwitchDisplayModeSupportedHMDPlugin->endSession();
1661 }
1662 // use the CloseEventSender via a QThread to send an event that says the user asked for the app to close
1663 DependencyManager::get<CloseEventSender>()->startThread();
1574 1664
1575 // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown.1665 // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown.
1576 DependencyManager::get<OffscreenUi>()->hide("RunningScripts");1666 DependencyManager::get<OffscreenUi>()->hide("RunningScripts");
@@ -1658,6 +1748,8 @@ void Application::cleanupBeforeQuit() { · 81 unmodified lines
1658 // stop QML1748 // stop QML
1659 DependencyManager::destroy<OffscreenUi>();1749 DependencyManager::destroy<OffscreenUi>();
1660 1750
1751 DependencyManager::destroy<OffscreenQmlSurfaceCache>();
1752
1661 if (_snapshotSoundInjector != nullptr) {1753 if (_snapshotSoundInjector != nullptr) {
1662 _snapshotSoundInjector->stop();1754 _snapshotSoundInjector->stop();
1663 }1755 }
@@ -1685,6 +1777,10 @@ Application::~Application() { · 21 unmodified lines
1685 1777
1686 _physicsEngine->setCharacterController(nullptr);1778 _physicsEngine->setCharacterController(nullptr);
1687 1779
1780 // the _shapeManager should have zero references
1781 _shapeManager.collectGarbage();
1782 assert(_shapeManager.getNumShapes() == 0);
1783
1688 // shutdown render engine1784 // shutdown render engine
1689 _main3DScene = nullptr;1785 _main3DScene = nullptr;
1690 _renderEngine = nullptr;1786 _renderEngine = nullptr;
@@ -1713,15 +1809,9 @@ Application::~Application() { · 22 unmodified lines
1713 1809
1714 ResourceManager::cleanup();1810 ResourceManager::cleanup();
1715 1811
1716 QThread* nodeThread = DependencyManager::get<NodeList>()->thread();
1717
1718 // remove the NodeList from the DependencyManager1812 // remove the NodeList from the DependencyManager
1719 DependencyManager::destroy<NodeList>();1813 DependencyManager::destroy<NodeList>();
1720 1814
1721 // ask the node thread to quit and wait until it is done
1722 nodeThread->quit();
1723 nodeThread->wait();
1724
1725 Leapmotion::destroy();1815 Leapmotion::destroy();
1726 1816
1727 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {1817 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
@@ -1736,6 +1826,15 @@ Application::~Application() { · 8 unmodified lines
1736 1826
1737 _window->deleteLater();1827 _window->deleteLater();
1738 1828
1829 // make sure that the quit event has finished sending before we take the application down
1830 auto closeEventSender = DependencyManager::get<CloseEventSender>();
1831 while (!closeEventSender->hasFinishedQuitEvent() && !closeEventSender->hasTimedOutQuitEvent()) {
1832 // sleep a little so we're not spinning at 100%
1833 std::this_thread::sleep_for(std::chrono::milliseconds(10));
1834 }
1835 // quit the thread used by the closure event sender
1836 closeEventSender->thread()->quit();
1837
1739 // Can't log to file passed this point, FileLogger about to be deleted1838 // Can't log to file passed this point, FileLogger about to be deleted
1740 qInstallMessageHandler(LogHandler::verboseMessageHandler);1839 qInstallMessageHandler(LogHandler::verboseMessageHandler);
1741}1840}
@@ -1771,15 +1870,9 @@ void Application::initializeGL() { · 29 unmodified lines
1771 1870
1772 // Set up the render engine1871 // Set up the render engine
1773 render::CullFunctor cullFunctor = LODManager::shouldRender;1872 render::CullFunctor cullFunctor = LODManager::shouldRender;
1774 _renderEngine->addJob<RenderShadowTask>("RenderShadowTask", cullFunctor);
1775 const auto items = _renderEngine->addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
1776 assert(items.canCast<RenderFetchCullSortTask::Output>());
1777 static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD";1873 static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD";
1778 if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) {1874 bool isDeferred = !QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD);
1779 _renderEngine->addJob<RenderForwardTask>("Forward", items);1875 _renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, isDeferred);
1780 } else {
1781 _renderEngine->addJob<RenderDeferredTask>("RenderDeferredTask", items);
1782 }
1783 _renderEngine->load();1876 _renderEngine->load();
1784 _renderEngine->registerScene(_main3DScene);1877 _renderEngine->registerScene(_main3DScene);
1785 1878
@@ -1828,14 +1921,10 @@ void Application::initializeUi() { · 42 unmodified lines
1828 UpdateDialog::registerType();1921 UpdateDialog::registerType();
1829 qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");1922 qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
1830 1923
1831 qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
1832 qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
1833 qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
1834
1835 auto offscreenUi = DependencyManager::get<OffscreenUi>();1924 auto offscreenUi = DependencyManager::get<OffscreenUi>();
1836 offscreenUi->create(_glWidget->qglContext());1925 offscreenUi->create(_glWidget->qglContext());
1837 1926
1838 auto rootContext = offscreenUi->getRootContext();1927 auto surfaceContext = offscreenUi->getSurfaceContext();
1839 1928
1840 offscreenUi->setProxyWindow(_window->windowHandle());1929 offscreenUi->setProxyWindow(_window->windowHandle());
1841 offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));1930 offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
@@ -1847,7 +1936,7 @@ void Application::initializeUi() { · 5 unmodified lines
1847 // do better detection in the offscreen UI of what has focus1936 // do better detection in the offscreen UI of what has focus
1848 offscreenUi->setNavigationFocused(false);1937 offscreenUi->setNavigationFocused(false);
1849 1938
1850 auto engine = rootContext->engine();1939 auto engine = surfaceContext->engine();
1851 connect(engine, &QQmlEngine::quit, [] {1940 connect(engine, &QQmlEngine::quit, [] {
1852 qApp->quit();1941 qApp->quit();
1853 });1942 });
@@ -1856,78 +1945,77 @@ void Application::initializeUi() { · 2 unmodified lines
1856 1945
1857 // For some reason there is already an "Application" object in the QML context,1946 // For some reason there is already an "Application" object in the QML context,
1858 // though I can't find it. Hence, "ApplicationInterface"1947 // though I can't find it. Hence, "ApplicationInterface"
1859 rootContext->setContextProperty("ApplicationInterface", this);1948 surfaceContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
1860 rootContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());1949 surfaceContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
1861 rootContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());1950 surfaceContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
1862 rootContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
1863 1951
1864 rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());1952 surfaceContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
1865 rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());1953 surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
1866 _fileDownload = new FileScriptingInterface(engine);1954 _fileDownload = new FileScriptingInterface(engine);
1867 rootContext->setContextProperty("File", _fileDownload);1955 surfaceContext->setContextProperty("File", _fileDownload);
1868 connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip);1956 connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip);
1869 rootContext->setContextProperty("MyAvatar", getMyAvatar().get());1957 surfaceContext->setContextProperty("MyAvatar", getMyAvatar().get());
1870 rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());1958 surfaceContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
1871 rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());1959 surfaceContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
1872 rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());1960 surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
1873 rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());1961 surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
1874 rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);1962 surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
1875 rootContext->setContextProperty("Rates", new RatesScriptingInterface(this));1963 surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this));
1876 rootContext->setContextProperty("pathToFonts", "../../");
1877 1964
1878 rootContext->setContextProperty("TREE_SCALE", TREE_SCALE);1965 surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE);
1879 rootContext->setContextProperty("Quat", new Quat());1966 // FIXME Quat and Vec3 won't work with QJSEngine used by QML
1880 rootContext->setContextProperty("Vec3", new Vec3());1967 surfaceContext->setContextProperty("Quat", new Quat());
1881 rootContext->setContextProperty("Uuid", new ScriptUUID());1968 surfaceContext->setContextProperty("Vec3", new Vec3());
1882 rootContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());1969 surfaceContext->setContextProperty("Uuid", new ScriptUUID());
1970 surfaceContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
1883 1971
1884 rootContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());1972 surfaceContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
1885 rootContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());1973 surfaceContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
1886 1974
1887 rootContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());1975 surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
1888 1976
1889 rootContext->setContextProperty("Camera", &_myCamera);1977 surfaceContext->setContextProperty("Camera", &_myCamera);
1890 1978
1891#if defined(Q_OS_MAC) || defined(Q_OS_WIN)1979#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1892 rootContext->setContextProperty("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());1980 surfaceContext->setContextProperty("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());
1893#endif1981#endif
1894 1982
1895 rootContext->setContextProperty("Overlays", &_overlays);1983 surfaceContext->setContextProperty("Overlays", &_overlays);
1896 rootContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());1984 surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
1897 rootContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());1985 surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
1898 rootContext->setContextProperty("Stats", Stats::getInstance());1986 surfaceContext->setContextProperty("Stats", Stats::getInstance());
1899 rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());1987 surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
1900 rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());1988 surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
1901 rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());1989 surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
1902 rootContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());1990 surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
1903 1991
1904 // Caches1992 // Caches
1905 rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());1993 surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
1906 rootContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());1994 surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
1907 rootContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());1995 surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
1908 rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());1996 surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
1909 1997
1910 rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance());1998 surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
1911 rootContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data()); 1999 surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
1912 rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);2000 surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
1913 rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());2001 surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
1914 rootContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());2002 surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
1915 rootContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());2003 surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
1916 rootContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);2004 surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
1917 rootContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());2005 surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
1918 rootContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());2006 surfaceContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
1919 rootContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());2007 surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
1920 rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());2008 surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
1921 rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get());2009 surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
1922 rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());2010 surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
1923 rootContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());2011 surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
1924 2012
1925 rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());2013 surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
1926 2014
1927 rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());2015 surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
1928 2016
1929 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {2017 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
1930 rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));2018 surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
1931 }2019 }
1932 2020
1933 2021
@@ -2066,7 +2154,7 @@ void Application::paintGL() { · 132 unmodified lines
2066 _myCamera.setOrientation(glm::quat_cast(camMat));2154 _myCamera.setOrientation(glm::quat_cast(camMat));
2067 } else {2155 } else {
2068 _myCamera.setPosition(myAvatar->getDefaultEyePosition());2156 _myCamera.setPosition(myAvatar->getDefaultEyePosition());
2069 _myCamera.setOrientation(myAvatar->getMyHead()->getCameraOrientation());2157 _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
2070 }2158 }
2071 } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {2159 } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
2072 if (isHMDMode()) {2160 if (isHMDMode()) {
@@ -2186,6 +2274,9 @@ void Application::paintGL() { · 113 unmodified lines
2186 });2274 });
2187 renderArgs._context->setStereoProjections(eyeProjections);2275 renderArgs._context->setStereoProjections(eyeProjections);
2188 renderArgs._context->setStereoViews(eyeOffsets);2276 renderArgs._context->setStereoViews(eyeOffsets);
2277
2278 // Configure the type of display / stereo
2279 renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
2189 }2280 }
2190 renderArgs._blitFramebuffer = finalFramebuffer;2281 renderArgs._blitFramebuffer = finalFramebuffer;
2191 displaySide(&renderArgs, _myCamera);2282 displaySide(&renderArgs, _myCamera);
@@ -2379,15 +2470,16 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 187 unmodified lines
2379 2470
2380 // Check HMD use (may be technically available without being in use)2471 // Check HMD use (may be technically available without being in use)
2381 bool hasHMD = PluginUtils::isHMDAvailable();2472 bool hasHMD = PluginUtils::isHMDAvailable();
2382 bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();2473 bool isUsingHMD = _displayPlugin->isHmd();
2474 bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD;
2383 2475
2384 Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };2476 Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
2385 Setting::Handle<bool> firstRun{ Settings::firstRun, true };2477 Setting::Handle<bool> firstRun{ Settings::firstRun, true };
2386 2478
2387 bool isTutorialComplete = tutorialComplete.get();2479 bool isTutorialComplete = tutorialComplete.get();
2388 bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;2480 bool shouldGoToTutorial = isUsingHMDAndHandControllers && hasTutorialContent && !isTutorialComplete;
2389 2481
2390 qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;2482 qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
2391 qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<2483 qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
2392 ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;2484 ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
2393 2485
@@ -2401,10 +2493,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 7 unmodified lines
2401 2493
2402 const QString TUTORIAL_PATH = "/tutorial_begin";2494 const QString TUTORIAL_PATH = "/tutorial_begin";
2403 2495
2496 static const QString SENT_TO_TUTORIAL = "tutorial";
2497 static const QString SENT_TO_PREVIOUS_LOCATION = "previous_location";
2498 static const QString SENT_TO_ENTRY = "entry";
2499 static const QString SENT_TO_SANDBOX = "sandbox";
2500
2501 QString sentTo;
2502
2404 if (shouldGoToTutorial) {2503 if (shouldGoToTutorial) {
2405 if (sandboxIsRunning) {2504 if (sandboxIsRunning) {
2406 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";2505 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
2407 DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);2506 DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
2507 sentTo = SENT_TO_TUTORIAL;
2408 } else {2508 } else {
2409 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";2509 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
2410 if (firstRun.get()) {2510 if (firstRun.get()) {
@@ -2412,8 +2512,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 1 unmodified line
2412 }2512 }
2413 if (addressLookupString.isEmpty()) {2513 if (addressLookupString.isEmpty()) {
2414 DependencyManager::get<AddressManager>()->goToEntry();2514 DependencyManager::get<AddressManager>()->goToEntry();
2515 sentTo = SENT_TO_ENTRY;
2415 } else {2516 } else {
2416 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);2517 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2518 sentTo = SENT_TO_PREVIOUS_LOCATION;
2417 }2519 }
2418 }2520 }
2419 } else {2521 } else {
@@ -2426,23 +2528,40 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 6 unmodified lines
2426 2528
2427 // If this is a first run we short-circuit the address passed in2529 // If this is a first run we short-circuit the address passed in
2428 if (isFirstRun) {2530 if (isFirstRun) {
2429 if (isUsingHMD) {2531 if (isUsingHMDAndHandControllers) {
2430 if (sandboxIsRunning) {2532 if (sandboxIsRunning) {
2431 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";2533 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
2432 DependencyManager::get<AddressManager>()->goToLocalSandbox();2534 DependencyManager::get<AddressManager>()->goToLocalSandbox();
2535 sentTo = SENT_TO_SANDBOX;
2433 } else {2536 } else {
2434 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";2537 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
2435 DependencyManager::get<AddressManager>()->goToEntry();2538 DependencyManager::get<AddressManager>()->goToEntry();
2539 sentTo = SENT_TO_ENTRY;
2436 }2540 }
2437 } else {2541 } else {
2438 DependencyManager::get<AddressManager>()->goToEntry();2542 DependencyManager::get<AddressManager>()->goToEntry();
2543 sentTo = SENT_TO_ENTRY;
2439 }2544 }
2440 } else {2545 } else {
2441 qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);2546 qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
2442 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);2547 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2548 sentTo = SENT_TO_PREVIOUS_LOCATION;
2443 }2549 }
2444 }2550 }
2445 2551
2552 UserActivityLogger::getInstance().logAction("startup_sent_to", {
2553 { "sent_to", sentTo },
2554 { "sandbox_is_running", sandboxIsRunning },
2555 { "has_hmd", hasHMD },
2556 { "has_hand_controllers", hasHandControllers },
2557 { "is_using_hmd", isUsingHMD },
2558 { "is_using_hmd_and_hand_controllers", isUsingHMDAndHandControllers },
2559 { "content_version", contentVersion },
2560 { "is_tutorial_complete", isTutorialComplete },
2561 { "has_tutorial_content", hasTutorialContent },
2562 { "should_go_to_tutorial", shouldGoToTutorial }
2563 });
2564
2446 _connectionMonitor.init();2565 _connectionMonitor.init();
2447 2566
2448 // After all of the constructor is completed, then set firstRun to false.2567 // After all of the constructor is completed, then set firstRun to false.
@@ -2777,6 +2896,17 @@ void Application::keyPressEvent(QKeyEvent* event) { · 328 unmodified lines
2777 if (isShifted && isMeta && !isOption) {2896 if (isShifted && isMeta && !isOption) {
2778 Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);2897 Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
2779 } else if (!isOption && !isShifted && isMeta) {2898 } else if (!isOption && !isShifted && isMeta) {
2899 AudioInjectorOptions options;
2900 options.localOnly = true;
2901 options.stereo = true;
2902
2903 if (_snapshotSoundInjector) {
2904 _snapshotSoundInjector->setOptions(options);
2905 _snapshotSoundInjector->restart();
2906 } else {
2907 QByteArray samples = _snapshotSound->getByteArray();
2908 _snapshotSoundInjector = AudioInjector::playSound(samples, options);
2909 }
2780 takeSnapshot(true);2910 takeSnapshot(true);
2781 }2911 }
2782 break;2912 break;
@@ -3951,6 +4081,7 @@ void Application::updateMyAvatarLookAtPosition() { · 1168 unmodified lines
3951 lookAtPosition.x = -lookAtPosition.x;4081 lookAtPosition.x = -lookAtPosition.x;
3952 }4082 }
3953 if (isHMD) {4083 if (isHMD) {
4084 // TODO -- this code is probably wrong, getHeadPose() returns something in sensor frame, not avatar
3954 glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose();4085 glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose();
3955 glm::quat hmdRotation = glm::quat_cast(headPose);4086 glm::quat hmdRotation = glm::quat_cast(headPose);
3956 lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition);4087 lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition);
@@ -3992,9 +4123,10 @@ void Application::updateMyAvatarLookAtPosition() { · 35 unmodified lines
3992 }4123 }
3993 } else {4124 } else {
3994 // I am not looking at anyone else, so just look forward4125 // I am not looking at anyone else, so just look forward
3995 if (isHMD) {4126 auto headPose = myAvatar->getHeadControllerPoseInSensorFrame();
3996 glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();4127 if (headPose.isValid()) {
3997 lookAtSpot = transformPoint(worldHMDMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE));4128 glm::mat4 worldHeadMat = myAvatar->getSensorToWorldMatrix() * headPose.getMatrix();
4129 lookAtSpot = transformPoint(worldHeadMat, glm::vec3(0.0f, 0.0f, TREE_SCALE));
3998 } else {4130 } else {
3999 lookAtSpot = myAvatar->getHead()->getEyePosition() +4131 lookAtSpot = myAvatar->getHead()->getEyePosition() +
4000 (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));4132 (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
@@ -4492,12 +4624,13 @@ void Application::update(float deltaTime) { · 491 unmodified lines
4492 4624
4493 getEntities()->getTree()->withWriteLock([&] {4625 getEntities()->getTree()->withWriteLock([&] {
4494 PerformanceTimer perfTimer("handleOutgoingChanges");4626 PerformanceTimer perfTimer("handleOutgoingChanges");
4495 const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates();
4496 _entitySimulation->handleDeactivatedMotionStates(deactivations);
4497 4627
4498 const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();4628 const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();
4499 _entitySimulation->handleChangedMotionStates(outgoingChanges);4629 _entitySimulation->handleChangedMotionStates(outgoingChanges);
4500 avatarManager->handleChangedMotionStates(outgoingChanges);4630 avatarManager->handleChangedMotionStates(outgoingChanges);
4631
4632 const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates();
4633 _entitySimulation->handleDeactivatedMotionStates(deactivations);
4501 });4634 });
4502 4635
4503 if (!_aboutToQuit) {4636 if (!_aboutToQuit) {
@@ -4885,12 +5018,6 @@ QRect Application::getDesirableApplicationGeometry() const { · 381 unmodified lines
4885 return applicationGeometry;5018 return applicationGeometry;
4886}5019}
4887 5020
4888glm::vec3 Application::getSunDirection() const {
4889 // Sun direction is in fact just the location of the sun relative to the origin
4890 auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
4891 return skyStage->getSunLight()->getDirection();
4892}
4893
4894// FIXME, preprocessor guard this check to occur only in DEBUG builds5021// FIXME, preprocessor guard this check to occur only in DEBUG builds
4895static QThread * activeRenderingThread = nullptr;5022static QThread * activeRenderingThread = nullptr;
4896 5023
@@ -4947,7 +5074,7 @@ namespace render { · 50 unmodified lines
4947 template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); }5074 template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); }
4948 template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }5075 template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
4949 template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {5076 template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
4950 if (args->_renderMode != RenderArgs::MIRROR_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {5077 if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
4951 PerformanceTimer perfTimer("worldBox");5078 PerformanceTimer perfTimer("worldBox");
4952 5079
4953 auto& batch = *args->_batch;5080 auto& batch = *args->_batch;
@@ -4957,90 +5084,6 @@ namespace render { · 3 unmodified lines
4957 }5084 }
4958}5085}
4959 5086
4960// Background Render Data & rendering functions
4961class BackgroundRenderData {
4962public:
4963 typedef render::Payload<BackgroundRenderData> Payload;
4964 typedef Payload::DataPointer Pointer;
4965
4966 static render::ItemID _item; // unique WorldBoxRenderData
4967};
4968
4969render::ItemID BackgroundRenderData::_item = 0;
4970
4971namespace render {
4972 template <> const ItemKey payloadGetKey(const BackgroundRenderData::Pointer& stuff) {
4973 return ItemKey::Builder::background();
4974 }
4975
4976 template <> const Item::Bound payloadGetBound(const BackgroundRenderData::Pointer& stuff) {
4977 return Item::Bound();
4978 }
4979
4980 template <> void payloadRender(const BackgroundRenderData::Pointer& background, RenderArgs* args) {
4981 Q_ASSERT(args->_batch);
4982 gpu::Batch& batch = *args->_batch;
4983
4984 // Background rendering decision
4985 auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
4986 auto backgroundMode = skyStage->getBackgroundMode();
4987
4988 switch (backgroundMode) {
4989 case model::SunSkyStage::SKY_DEFAULT: {
4990 auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
4991 auto sceneKeyLight = scene->getKeyLight();
4992
4993 scene->setSunModelEnable(false);
4994 sceneKeyLight->setColor(ColorUtils::toVec3(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_COLOR));
4995 sceneKeyLight->setIntensity(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY);
4996 sceneKeyLight->setAmbientIntensity(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY);
4997 sceneKeyLight->setDirection(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION);
4998 // fall through: render a skybox (if available), or the defaults (if requested)
4999 }
5000
5001 case model::SunSkyStage::SKY_BOX: {
5002 auto skybox = skyStage->getSkybox();
5003 if (!skybox->empty()) {
5004 PerformanceTimer perfTimer("skybox");
5005 skybox->render(batch, args->getViewFrustum());
5006 break;
5007 }
5008 // fall through: render defaults (if requested)
5009 }
5010
5011 case model::SunSkyStage::SKY_DEFAULT_AMBIENT_TEXTURE: {
5012 if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
5013 auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
5014 auto sceneKeyLight = scene->getKeyLight();
5015 auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture();
5016 if (defaultSkyboxAmbientTexture) {
5017 sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance());
5018 sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
5019 } else {
5020 static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(
5021 "Failed to get a valid Default Skybox Ambient Texture ? probably because it couldn't be find during initialization step");
5022 }
5023 // fall through: render defaults skybox
5024 } else {
5025 break;
5026 }
5027 }
5028
5029 case model::SunSkyStage::SKY_DEFAULT_TEXTURE:
5030 if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
5031 qApp->getDefaultSkybox()->render(batch, args->getViewFrustum());
5032 }
5033 break;
5034
5035 // Any other cases require no extra rendering
5036 case model::SunSkyStage::NO_BACKGROUND:
5037 default:
5038 break;
5039 }
5040 }
5041}
5042
5043
5044void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {5087void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
5045 5088
5046 // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.5089 // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
@@ -5064,15 +5107,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 17 unmodified lines
5064 // The pending changes collecting the changes here5107 // The pending changes collecting the changes here
5065 render::Transaction transaction;5108 render::Transaction transaction;
5066 5109
5067 // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities
5068 // Background rendering decision
5069 if (!render::Item::isValidID(BackgroundRenderData::_item)) {
5070 auto backgroundRenderData = make_shared<BackgroundRenderData>();
5071 auto backgroundRenderPayload = make_shared<BackgroundRenderData::Payload>(backgroundRenderData);
5072 BackgroundRenderData::_item = _main3DScene->allocateID();
5073 transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload);
5074 }
5075
5076 // Assuming nothing gets rendered through that5110 // Assuming nothing gets rendered through that
5077 if (!selfAvatarOnly) {5111 if (!selfAvatarOnly) {
5078 if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {5112 if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
@@ -5108,12 +5142,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 29 unmodified lines
5108 });5142 });
5109 }5143 }
5110 5144
5111 // Setup the current Zone Entity lighting
5112 {
5113 auto stage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
5114 DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight());
5115 }
5116
5117 {5145 {
5118 PerformanceTimer perfTimer("SceneProcessTransaction");5146 PerformanceTimer perfTimer("SceneProcessTransaction");
5119 _main3DScene->enqueueTransaction(transaction);5147 _main3DScene->enqueueTransaction(transaction);
@@ -6384,21 +6412,6 @@ void Application::loadAddAvatarBookmarkDialog() const { · 1264 unmodified lines
6384}6412}
6385 6413
6386void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) {6414void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) {
6387
6388 //keep sound thread out of event loop scope
6389
6390 AudioInjectorOptions options;
6391 options.localOnly = true;
6392 options.stereo = true;
6393
6394 if (_snapshotSoundInjector) {
6395 _snapshotSoundInjector->setOptions(options);
6396 _snapshotSoundInjector->restart();
6397 } else {
6398 QByteArray samples = _snapshotSound->getByteArray();
6399 _snapshotSoundInjector = AudioInjector::playSound(samples, options);
6400 }
6401
6402 postLambdaEvent([notify, includeAnimated, aspectRatio, this] {6415 postLambdaEvent([notify, includeAnimated, aspectRatio, this] {
6403 // Get a screenshot and save it6416 // Get a screenshot and save it
6404 QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio));6417 QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio));
@@ -6811,6 +6824,35 @@ void Application::updateDisplayMode() { · 406 unmodified lines
6811 Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");6824 Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
6812}6825}
6813 6826
6827void Application::switchDisplayMode() {
6828 if (!_autoSwitchDisplayModeSupportedHMDPlugin) {
6829 return;
6830 }
6831 bool currentHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible();
6832 if (currentHMDWornStatus != _previousHMDWornStatus) {
6833 // Switch to respective mode as soon as currentHMDWornStatus changes
6834 if (currentHMDWornStatus) {
6835 qCDebug(interfaceapp) << "Switching from Desktop to HMD mode";
6836 endHMDSession();
6837 setActiveDisplayPlugin(_autoSwitchDisplayModeSupportedHMDPluginName);
6838 } else {
6839 qCDebug(interfaceapp) << "Switching from HMD to desktop mode";
6840 setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME);
6841 startHMDStandBySession();
6842 }
6843 emit activeDisplayPluginChanged();
6844 }
6845 _previousHMDWornStatus = currentHMDWornStatus;
6846}
6847
6848void Application::startHMDStandBySession() {
6849 _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
6850}
6851
6852void Application::endHMDSession() {
6853 _autoSwitchDisplayModeSupportedHMDPlugin->endSession();
6854}
6855
6814mat4 Application::getEyeProjection(int eye) const {6856mat4 Application::getEyeProjection(int eye) const {
6815 QMutexLocker viewLocker(&_viewMutex);6857 QMutexLocker viewLocker(&_viewMutex);
6816 if (isHMDMode()) {6858 if (isHMDMode()) {