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
1111
1212 #include "Application.h"
1313
14+#include <chrono>
15+#include <thread>
16+
1417 #include <gl/Config.h>
1518 #include <glm/glm.hpp>
1619 #include <glm/gtx/component_wise.hpp>
@@ -69,6 +72,7 @@ · 52 unmodified lines
6972 #include <ErrorDialog.h>
7073 #include <FileScriptingInterface.h>
7174 #include <Finally.h>
75+#include <FingerprintUtils.h>
7276 #include <FramebufferCache.h>
7377 #include <gpu/Batch.h>
7478 #include <gpu/Context.h>
@@ -110,7 +114,9 @@ · 35 unmodified lines
110114 #include <render/RenderFetchCullSortTask.h>
111115 #include <RenderDeferredTask.h>
112116 #include <RenderForwardTask.h>
117+#include <RenderViewTask.h>
113118 #include <ResourceCache.h>
119+#include <ResourceRequest.h>
114120 #include <SandboxUtils.h>
115121 #include <SceneScriptingInterface.h>
116122 #include <ScriptEngines.h>
@@ -144,10 +150,8 @@ · 27 unmodified lines
144150 #include "InterfaceLogging.h"
145151 #include "LODManager.h"
146152 #include "ModelPackager.h"
147−#include "networking/HFWebEngineProfile.h"
148−#include "networking/HFTabletWebEngineProfile.h"
149−#include "networking/FileTypeProfile.h"
150153 #include "scripting/Audio.h"
154+#include "networking/CloseEventSender.h"
151155 #include "scripting/TestScriptingInterface.h"
152156 #include "scripting/AccountScriptingInterface.h"
153157 #include "scripting/AssetMappingsScriptingInterface.h"
@@ -244,6 +248,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda · 90 unmodified lines
244248 Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
245249
246250 static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
251+static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
252+static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
247253
248254 static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
249255
@@ -438,6 +444,10 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 188 unmodified lines
438444 const char* portStr = getCmdOption(argc, constArgv, "--listenPort");
439445 const int listenPort = portStr ? atoi(portStr) : INVALID_PORT;
440446
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+
441451 Setting::init();
442452
443453 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
@@ -458,10 +468,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 14 unmodified lines
458468 QCoreApplication::addLibraryPath(audioDLLPath);
459469 #endif
460470
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−
465471 DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
466472 DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
467473 DependencyManager::registerInheritance<EntityDynamicFactoryInterface, InterfaceDynamicFactory>();
@@ -536,6 +542,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 68 unmodified lines
536542 DependencyManager::set<AvatarBookmarks>();
537543 DependencyManager::set<LocationBookmarks>();
538544 DependencyManager::set<Snapshot>();
545+ DependencyManager::set<CloseEventSender>();
539546
540547 return previousSessionCrashed;
541548 }
@@ -649,6 +656,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 107 unmodified lines
649656 Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us
650657
651658 auto nodeList = DependencyManager::get<NodeList>();
659+ nodeList->startThread();
652660
653661 // Set up a watchdog thread to intentionally crash the application on deadlocks
654662 _deadlockWatchdogThread = new DeadlockWatchdogThread();
@@ -674,25 +682,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 19 unmodified lines
674682
675683 updateHeartbeat();
676684
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−
685685 // setup a timer for domain-server check ins
686686 QTimer* domainCheckInTimer = new QTimer(nodeList.data());
687687 connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
688688 domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
689689
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");
696690
697691 auto audioIO = DependencyManager::get<AudioClient>();
698692 audioIO->setPositionGetter([]{
@@ -708,7 +702,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 9 unmodified lines
708702 return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;
709703 });
710704
711− audioIO->moveToThread(audioThread);
712705 recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) {
713706 audioIO->handleRecordedAudioInput(frame->data);
714707 });
@@ -720,11 +713,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 5 unmodified lines
720713 recorder->recordFrame(AUDIO_FRAME_TYPE, audio);
721714 }
722715 });
723−
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();
716+ audioIO->startThread();
728717
729718 auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface, scripting::Audio>();
730719 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
750739 updateHeartbeat();
751740
752741 // Setup MessagesClient
753− auto messagesClient = DependencyManager::get<MessagesClient>();
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();
742+ DependencyManager::get<MessagesClient>()->startThread();
759743
760744 const DomainHandler& domainHandler = nodeList->getDomainHandler();
761745
@@ -950,6 +934,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 188 unmodified lines
950934 properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
951935 }
952936
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+
953944 UserActivityLogger::getInstance().logAction("launch", properties);
954945
955946 // 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
13091300 properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();
13101301 properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();
13111302
1303+ properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer);
1304+
13121305 auto nodeList = DependencyManager::get<NodeList>();
13131306 SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);
13141307 SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
@@ -1322,8 +1315,61 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 7 unmodified lines
13221315 properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;
13231316
13241317 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+
13251329 properties["active_downloads"] = loadingRequests.size();
13261330 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;
13271373
13281374 properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
13291375
@@ -1339,9 +1385,43 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 9 unmodified lines
13391385 properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount;
13401386 properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount;
13411387
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+
13421397 properties["active_display_plugin"] = getActiveDisplayPlugin()->getName();
13431398 properties["using_hmd"] = isHMDMode();
13441399
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+
13451425 auto glInfo = getGLContextData();
13461426 properties["gl_info"] = glInfo;
13471427 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
13641444 lastLeftHandPose = leftHandPose;
13651445 lastRightHandPose = rightHandPose;
13661446
1447+ properties["local_socket_changes"] = DependencyManager::get<StatTracker>()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt();
1448+
13671449 UserActivityLogger::getInstance().logAction("stats", properties);
13681450 });
13691451 sendStatsTimer->start();
@@ -1463,6 +1545,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 93 unmodified lines
14631545 updateSystemTabletMode();
14641546
14651547 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
1548+
1549+ qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
14661550 }
14671551
14681552 void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
@@ -1571,6 +1655,12 @@ void Application::aboutToQuit() { · 102 unmodified lines
15711655 }
15721656
15731657 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();
15741664
15751665 // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown.
15761666 DependencyManager::get<OffscreenUi>()->hide("RunningScripts");
@@ -1658,6 +1748,8 @@ void Application::cleanupBeforeQuit() { · 81 unmodified lines
16581748 // stop QML
16591749 DependencyManager::destroy<OffscreenUi>();
16601750
1751+ DependencyManager::destroy<OffscreenQmlSurfaceCache>();
1752+
16611753 if (_snapshotSoundInjector != nullptr) {
16621754 _snapshotSoundInjector->stop();
16631755 }
@@ -1685,6 +1777,10 @@ Application::~Application() { · 21 unmodified lines
16851777
16861778 _physicsEngine->setCharacterController(nullptr);
16871779
1780+ // the _shapeManager should have zero references
1781+ _shapeManager.collectGarbage();
1782+ assert(_shapeManager.getNumShapes() == 0);
1783+
16881784 // shutdown render engine
16891785 _main3DScene = nullptr;
16901786 _renderEngine = nullptr;
@@ -1713,15 +1809,9 @@ Application::~Application() { · 22 unmodified lines
17131809
17141810 ResourceManager::cleanup();
17151811
1716− QThread* nodeThread = DependencyManager::get<NodeList>()->thread();
1717−
17181812 // remove the NodeList from the DependencyManager
17191813 DependencyManager::destroy<NodeList>();
17201814
1721− // ask the node thread to quit and wait until it is done
1722− nodeThread->quit();
1723− nodeThread->wait();
1724−
17251815 Leapmotion::destroy();
17261816
17271817 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
@@ -1736,6 +1826,15 @@ Application::~Application() { · 8 unmodified lines
17361826
17371827 _window->deleteLater();
17381828
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+
17391838 // Can't log to file passed this point, FileLogger about to be deleted
17401839 qInstallMessageHandler(LogHandler::verboseMessageHandler);
17411840 }
@@ -1771,15 +1870,9 @@ void Application::initializeGL() { · 29 unmodified lines
17711870
17721871 // Set up the render engine
17731872 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>());
17771873 static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD";
1778− if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) {
1779− _renderEngine->addJob<RenderForwardTask>("Forward", items);
1780− } else {
1781− _renderEngine->addJob<RenderDeferredTask>("RenderDeferredTask", items);
1782− }
1874+ bool isDeferred = !QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD);
1875+ _renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, isDeferred);
17831876 _renderEngine->load();
17841877 _renderEngine->registerScene(_main3DScene);
17851878
@@ -1828,14 +1921,10 @@ void Application::initializeUi() { · 42 unmodified lines
18281921 UpdateDialog::registerType();
18291922 qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
18301923
1831− qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
1832− qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
1833− qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
1834−
18351924 auto offscreenUi = DependencyManager::get<OffscreenUi>();
18361925 offscreenUi->create(_glWidget->qglContext());
18371926
1838− auto rootContext = offscreenUi->getRootContext();
1927+ auto surfaceContext = offscreenUi->getSurfaceContext();
18391928
18401929 offscreenUi->setProxyWindow(_window->windowHandle());
18411930 offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
@@ -1847,7 +1936,7 @@ void Application::initializeUi() { · 5 unmodified lines
18471936 // do better detection in the offscreen UI of what has focus
18481937 offscreenUi->setNavigationFocused(false);
18491938
1850− auto engine = rootContext->engine();
1939+ auto engine = surfaceContext->engine();
18511940 connect(engine, &QQmlEngine::quit, [] {
18521941 qApp->quit();
18531942 });
@@ -1856,78 +1945,77 @@ void Application::initializeUi() { · 2 unmodified lines
18561945
18571946 // For some reason there is already an "Application" object in the QML context,
18581947 // though I can't find it. Hence, "ApplicationInterface"
1859− rootContext->setContextProperty("ApplicationInterface", this);
1860− rootContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
1861− rootContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
1862− rootContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
1948+ surfaceContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
1949+ surfaceContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
1950+ surfaceContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
18631951
1864− rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
1865− rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
1952+ surfaceContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
1953+ surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
18661954 _fileDownload = new FileScriptingInterface(engine);
1867− rootContext->setContextProperty("File", _fileDownload);
1955+ surfaceContext->setContextProperty("File", _fileDownload);
18681956 connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip);
1869− rootContext->setContextProperty("MyAvatar", getMyAvatar().get());
1870− rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
1871− rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
1872− rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
1873− rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
1874− rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
1875− rootContext->setContextProperty("Rates", new RatesScriptingInterface(this));
1876− rootContext->setContextProperty("pathToFonts", "../../");
1957+ surfaceContext->setContextProperty("MyAvatar", getMyAvatar().get());
1958+ surfaceContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
1959+ surfaceContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
1960+ surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
1961+ surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
1962+ surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
1963+ surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this));
18771964
1878− rootContext->setContextProperty("TREE_SCALE", TREE_SCALE);
1879− rootContext->setContextProperty("Quat", new Quat());
1880− rootContext->setContextProperty("Vec3", new Vec3());
1881− rootContext->setContextProperty("Uuid", new ScriptUUID());
1882− rootContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
1965+ surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE);
1966+ // FIXME Quat and Vec3 won't work with QJSEngine used by QML
1967+ surfaceContext->setContextProperty("Quat", new Quat());
1968+ surfaceContext->setContextProperty("Vec3", new Vec3());
1969+ surfaceContext->setContextProperty("Uuid", new ScriptUUID());
1970+ surfaceContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
18831971
1884− rootContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
1885− rootContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
1972+ surfaceContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
1973+ surfaceContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
18861974
1887− rootContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
1975+ surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
18881976
1889− rootContext->setContextProperty("Camera", &_myCamera);
1977+ surfaceContext->setContextProperty("Camera", &_myCamera);
18901978
18911979 #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());
18931981 #endif
18941982
1895− rootContext->setContextProperty("Overlays", &_overlays);
1896− rootContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
1897− rootContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
1898− rootContext->setContextProperty("Stats", Stats::getInstance());
1899− rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
1900− rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
1901− rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
1902− rootContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
1983+ surfaceContext->setContextProperty("Overlays", &_overlays);
1984+ surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
1985+ surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
1986+ surfaceContext->setContextProperty("Stats", Stats::getInstance());
1987+ surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
1988+ surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
1989+ surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
1990+ surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
19031991
19041992 // Caches
1905− rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
1906− rootContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
1907− rootContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
1908− rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
1909−
1910− rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
1911− rootContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
1912− rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
1913− rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
1914− rootContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
1915− rootContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
1916− rootContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
1917− rootContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
1918− rootContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
1919− rootContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
1920− rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
1921− rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
1922− rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
1923− rootContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
1924−
1925− rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
1926−
1927− rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
1993+ surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
1994+ surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
1995+ surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
1996+ surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
1997+
1998+ surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
1999+ surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
2000+ surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
2001+ surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
2002+ surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
2003+ surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
2004+ surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
2005+ surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
2006+ surfaceContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
2007+ surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
2008+ surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
2009+ surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
2010+ surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
2011+ surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
2012+
2013+ surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
2014+
2015+ surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
19282016
19292017 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
1930− rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
2018+ surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
19312019 }
19322020
19332021
@@ -2066,7 +2154,7 @@ void Application::paintGL() { · 132 unmodified lines
20662154 _myCamera.setOrientation(glm::quat_cast(camMat));
20672155 } else {
20682156 _myCamera.setPosition(myAvatar->getDefaultEyePosition());
2069− _myCamera.setOrientation(myAvatar->getMyHead()->getCameraOrientation());
2157+ _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
20702158 }
20712159 } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
20722160 if (isHMDMode()) {
@@ -2186,6 +2274,9 @@ void Application::paintGL() { · 113 unmodified lines
21862274 });
21872275 renderArgs._context->setStereoProjections(eyeProjections);
21882276 renderArgs._context->setStereoViews(eyeOffsets);
2277+
2278+ // Configure the type of display / stereo
2279+ renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
21892280 }
21902281 renderArgs._blitFramebuffer = finalFramebuffer;
21912282 displaySide(&renderArgs, _myCamera);
@@ -2379,15 +2470,16 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 187 unmodified lines
23792470
23802471 // Check HMD use (may be technically available without being in use)
23812472 bool hasHMD = PluginUtils::isHMDAvailable();
2382− bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();
2473+ bool isUsingHMD = _displayPlugin->isHmd();
2474+ bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD;
23832475
23842476 Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
23852477 Setting::Handle<bool> firstRun{ Settings::firstRun, true };
23862478
23872479 bool isTutorialComplete = tutorialComplete.get();
2388− bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;
2480+ bool shouldGoToTutorial = isUsingHMDAndHandControllers && hasTutorialContent && !isTutorialComplete;
23892481
2390− qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;
2482+ qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
23912483 qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
23922484 ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
23932485
@@ -2401,10 +2493,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 7 unmodified lines
24012493
24022494 const QString TUTORIAL_PATH = "/tutorial_begin";
24032495
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+
24042503 if (shouldGoToTutorial) {
24052504 if (sandboxIsRunning) {
24062505 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
24072506 DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
2507+ sentTo = SENT_TO_TUTORIAL;
24082508 } else {
24092509 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
24102510 if (firstRun.get()) {
@@ -2412,8 +2512,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 1 unmodified line
24122512 }
24132513 if (addressLookupString.isEmpty()) {
24142514 DependencyManager::get<AddressManager>()->goToEntry();
2515+ sentTo = SENT_TO_ENTRY;
24152516 } else {
24162517 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2518+ sentTo = SENT_TO_PREVIOUS_LOCATION;
24172519 }
24182520 }
24192521 } else {
@@ -2426,23 +2528,40 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 6 unmodified lines
24262528
24272529 // If this is a first run we short-circuit the address passed in
24282530 if (isFirstRun) {
2429− if (isUsingHMD) {
2531+ if (isUsingHMDAndHandControllers) {
24302532 if (sandboxIsRunning) {
24312533 qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
24322534 DependencyManager::get<AddressManager>()->goToLocalSandbox();
2535+ sentTo = SENT_TO_SANDBOX;
24332536 } else {
24342537 qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
24352538 DependencyManager::get<AddressManager>()->goToEntry();
2539+ sentTo = SENT_TO_ENTRY;
24362540 }
24372541 } else {
24382542 DependencyManager::get<AddressManager>()->goToEntry();
2543+ sentTo = SENT_TO_ENTRY;
24392544 }
24402545 } else {
24412546 qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
24422547 DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
2548+ sentTo = SENT_TO_PREVIOUS_LOCATION;
24432549 }
24442550 }
24452551
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+
24462565 _connectionMonitor.init();
24472566
24482567 // After all of the constructor is completed, then set firstRun to false.
@@ -2777,6 +2896,17 @@ void Application::keyPressEvent(QKeyEvent* event) { · 328 unmodified lines
27772896 if (isShifted && isMeta && !isOption) {
27782897 Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
27792898 } 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+ }
27802910 takeSnapshot(true);
27812911 }
27822912 break;
@@ -3951,6 +4081,7 @@ void Application::updateMyAvatarLookAtPosition() { · 1168 unmodified lines
39514081 lookAtPosition.x = -lookAtPosition.x;
39524082 }
39534083 if (isHMD) {
4084+ // TODO -- this code is probably wrong, getHeadPose() returns something in sensor frame, not avatar
39544085 glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose();
39554086 glm::quat hmdRotation = glm::quat_cast(headPose);
39564087 lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition);
@@ -3992,9 +4123,10 @@ void Application::updateMyAvatarLookAtPosition() { · 35 unmodified lines
39924123 }
39934124 } else {
39944125 // I am not looking at anyone else, so just look forward
3995− if (isHMD) {
3996− glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
3997− lookAtSpot = transformPoint(worldHMDMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE));
4126+ auto headPose = myAvatar->getHeadControllerPoseInSensorFrame();
4127+ if (headPose.isValid()) {
4128+ glm::mat4 worldHeadMat = myAvatar->getSensorToWorldMatrix() * headPose.getMatrix();
4129+ lookAtSpot = transformPoint(worldHeadMat, glm::vec3(0.0f, 0.0f, TREE_SCALE));
39984130 } else {
39994131 lookAtSpot = myAvatar->getHead()->getEyePosition() +
40004132 (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
@@ -4492,12 +4624,13 @@ void Application::update(float deltaTime) { · 491 unmodified lines
44924624
44934625 getEntities()->getTree()->withWriteLock([&] {
44944626 PerformanceTimer perfTimer("handleOutgoingChanges");
4495− const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates();
4496− _entitySimulation->handleDeactivatedMotionStates(deactivations);
44974627
44984628 const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();
44994629 _entitySimulation->handleChangedMotionStates(outgoingChanges);
45004630 avatarManager->handleChangedMotionStates(outgoingChanges);
4631+
4632+ const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates();
4633+ _entitySimulation->handleDeactivatedMotionStates(deactivations);
45014634 });
45024635
45034636 if (!_aboutToQuit) {
@@ -4885,12 +5018,6 @@ QRect Application::getDesirableApplicationGeometry() const { · 381 unmodified lines
48855018 return applicationGeometry;
48865019 }
48875020
4888−glm::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−
48945021 // FIXME, preprocessor guard this check to occur only in DEBUG builds
48955022 static QThread * activeRenderingThread = nullptr;
48965023
@@ -4947,7 +5074,7 @@ namespace render { · 50 unmodified lines
49475074 template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); }
49485075 template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
49495076 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)) {
49515078 PerformanceTimer perfTimer("worldBox");
49525079
49535080 auto& batch = *args->_batch;
@@ -4957,90 +5084,6 @@ namespace render { · 3 unmodified lines
49575084 }
49585085 }
49595086
4960−// Background Render Data & rendering functions
4961−class BackgroundRenderData {
4962−public:
4963− typedef render::Payload<BackgroundRenderData> Payload;
4964− typedef Payload::DataPointer Pointer;
4965−
4966− static render::ItemID _item; // unique WorldBoxRenderData
4967−};
4968−
4969−render::ItemID BackgroundRenderData::_item = 0;
4970−
4971−namespace 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−
50445087 void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
50455088
50465089 // 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
50645107 // The pending changes collecting the changes here
50655108 render::Transaction transaction;
50665109
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−
50765110 // Assuming nothing gets rendered through that
50775111 if (!selfAvatarOnly) {
50785112 if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
@@ -5108,12 +5142,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 29 unmodified lines
51085142 });
51095143 }
51105144
5111− // Setup the current Zone Entity lighting
5112− {
5113− auto stage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
5114− DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight());
5115− }
5116−
51175145 {
51185146 PerformanceTimer perfTimer("SceneProcessTransaction");
51195147 _main3DScene->enqueueTransaction(transaction);
@@ -6384,21 +6412,6 @@ void Application::loadAddAvatarBookmarkDialog() const { · 1264 unmodified lines
63846412 }
63856413
63866414 void 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−
64026415 postLambdaEvent([notify, includeAnimated, aspectRatio, this] {
64036416 // Get a screenshot and save it
64046417 QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio));
@@ -6811,6 +6824,35 @@ void Application::updateDisplayMode() { · 406 unmodified lines
68116824 Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
68126825 }
68136826
6827+void 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+
6848+void Application::startHMDStandBySession() {
6849+ _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
6850+}
6851+
6852+void Application::endHMDSession() {
6853+ _autoSwitchDisplayModeSupportedHMDPlugin->endSession();
6854+}
6855+
68146856 mat4 Application::getEyeProjection(int eye) const {
68156857 QMutexLocker viewLocker(&_viewMutex);
68166858 if (isHMDMode()) {