Showing the changes to interface/src/Application.cpp (1 of 385 files). Show all
Unified · Split
| @@ -11,6 +11,9 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include "Application.h" |
| 13 | 13 | |
| 14 | +#include <chrono> | |
| 15 | +#include <thread> | |
| 16 | + | |
| 14 | 17 | #include <gl/Config.h> |
| 15 | 18 | #include <glm/glm.hpp> |
| 16 | 19 | #include <glm/gtx/component_wise.hpp> |
| @@ -69,6 +72,7 @@ · 52 unmodified lines | ||
| 69 | 72 | #include <ErrorDialog.h> |
| 70 | 73 | #include <FileScriptingInterface.h> |
| 71 | 74 | #include <Finally.h> |
| 75 | +#include <FingerprintUtils.h> | |
| 72 | 76 | #include <FramebufferCache.h> |
| 73 | 77 | #include <gpu/Batch.h> |
| 74 | 78 | #include <gpu/Context.h> |
| @@ -110,7 +114,9 @@ · 35 unmodified lines | ||
| 110 | 114 | #include <render/RenderFetchCullSortTask.h> |
| 111 | 115 | #include <RenderDeferredTask.h> |
| 112 | 116 | #include <RenderForwardTask.h> |
| 117 | +#include <RenderViewTask.h> | |
| 113 | 118 | #include <ResourceCache.h> |
| 119 | +#include <ResourceRequest.h> | |
| 114 | 120 | #include <SandboxUtils.h> |
| 115 | 121 | #include <SceneScriptingInterface.h> |
| 116 | 122 | #include <ScriptEngines.h> |
| @@ -144,10 +150,8 @@ · 27 unmodified lines | ||
| 144 | 150 | #include "InterfaceLogging.h" |
| 145 | 151 | #include "LODManager.h" |
| 146 | 152 | #include "ModelPackager.h" |
| 147 | −#include "networking/HFWebEngineProfile.h" | |
| 148 | −#include "networking/HFTabletWebEngineProfile.h" | |
| 149 | −#include "networking/FileTypeProfile.h" | |
| 150 | 153 | #include "scripting/Audio.h" |
| 154 | +#include "networking/CloseEventSender.h" | |
| 151 | 155 | #include "scripting/TestScriptingInterface.h" |
| 152 | 156 | #include "scripting/AccountScriptingInterface.h" |
| 153 | 157 | #include "scripting/AssetMappingsScriptingInterface.h" |
| @@ -244,6 +248,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda · 90 unmodified lines | ||
| 244 | 248 | Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); |
| 245 | 249 | |
| 246 | 250 | 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"; | |
| 247 | 253 | |
| 248 | 254 | static 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 | 444 | const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); |
| 439 | 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 | 451 | Setting::init(); |
| 442 | 452 | |
| 443 | 453 | if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { |
| @@ -458,10 +468,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 14 unmodified lines | ||
| 458 | 468 | QCoreApplication::addLibraryPath(audioDLLPath); |
| 459 | 469 | #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 | 471 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); |
| 466 | 472 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); |
| 467 | 473 | DependencyManager::registerInheritance<EntityDynamicFactoryInterface, InterfaceDynamicFactory>(); |
| @@ -536,6 +542,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 68 unmodified lines | ||
| 536 | 542 | DependencyManager::set<AvatarBookmarks>(); |
| 537 | 543 | DependencyManager::set<LocationBookmarks>(); |
| 538 | 544 | DependencyManager::set<Snapshot>(); |
| 545 | + DependencyManager::set<CloseEventSender>(); | |
| 539 | 546 | |
| 540 | 547 | return previousSessionCrashed; |
| 541 | 548 | } |
| @@ -649,6 +656,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 107 unmodified lines | ||
| 649 | 656 | Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us |
| 650 | 657 | |
| 651 | 658 | auto nodeList = DependencyManager::get<NodeList>(); |
| 659 | + nodeList->startThread(); | |
| 652 | 660 | |
| 653 | 661 | // Set up a watchdog thread to intentionally crash the application on deadlocks |
| 654 | 662 | _deadlockWatchdogThread = new DeadlockWatchdogThread(); |
| @@ -674,25 +682,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 19 unmodified lines | ||
| 674 | 682 | |
| 675 | 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 | 685 | // setup a timer for domain-server check ins |
| 686 | 686 | QTimer* domainCheckInTimer = new QTimer(nodeList.data()); |
| 687 | 687 | connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); |
| 688 | 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 | 691 | auto audioIO = DependencyManager::get<AudioClient>(); |
| 698 | 692 | audioIO->setPositionGetter([]{ |
| @@ -708,7 +702,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 9 unmodified lines | ||
| 708 | 702 | return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY; |
| 709 | 703 | }); |
| 710 | 704 | |
| 711 | − audioIO->moveToThread(audioThread); | |
| 712 | 705 | recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) { |
| 713 | 706 | audioIO->handleRecordedAudioInput(frame->data); |
| 714 | 707 | }); |
| @@ -720,11 +713,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 5 unmodified lines | ||
| 720 | 713 | recorder->recordFrame(AUDIO_FRAME_TYPE, audio); |
| 721 | 714 | } |
| 722 | 715 | }); |
| 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(); | |
| 728 | 717 | |
| 729 | 718 | auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface, scripting::Audio>(); |
| 730 | 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 | 739 | updateHeartbeat(); |
| 751 | 740 | |
| 752 | 741 | // 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(); | |
| 759 | 743 | |
| 760 | 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 | 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 | 944 | UserActivityLogger::getInstance().logAction("launch", properties); |
| 954 | 945 | |
| 955 | 946 | // 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 | 1300 | properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(); |
| 1310 | 1301 | properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond(); |
| 1311 | 1302 | |
| 1303 | + properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer); | |
| 1304 | + | |
| 1312 | 1305 | auto nodeList = DependencyManager::get<NodeList>(); |
| 1313 | 1306 | SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer); |
| 1314 | 1307 | SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); |
| @@ -1322,8 +1315,61 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 7 unmodified lines | ||
| 1322 | 1315 | properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1; |
| 1323 | 1316 | |
| 1324 | 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 | 1329 | properties["active_downloads"] = loadingRequests.size(); |
| 1326 | 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 | 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 | 1385 | properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount; |
| 1340 | 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 | 1397 | properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); |
| 1343 | 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 | 1425 | auto glInfo = getGLContextData(); |
| 1346 | 1426 | properties["gl_info"] = glInfo; |
| 1347 | 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 | 1444 | lastLeftHandPose = leftHandPose; |
| 1365 | 1445 | lastRightHandPose = rightHandPose; |
| 1366 | 1446 | |
| 1447 | + properties["local_socket_changes"] = DependencyManager::get<StatTracker>()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt(); | |
| 1448 | + | |
| 1367 | 1449 | UserActivityLogger::getInstance().logAction("stats", properties); |
| 1368 | 1450 | }); |
| 1369 | 1451 | sendStatsTimer->start(); |
| @@ -1463,6 +1545,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 93 unmodified lines | ||
| 1463 | 1545 | updateSystemTabletMode(); |
| 1464 | 1546 | |
| 1465 | 1547 | connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); |
| 1548 | + | |
| 1549 | + qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); | |
| 1466 | 1550 | } |
| 1467 | 1551 | |
| 1468 | 1552 | void 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 | 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 | 1665 | // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. |
| 1576 | 1666 | DependencyManager::get<OffscreenUi>()->hide("RunningScripts"); |
| @@ -1658,6 +1748,8 @@ void Application::cleanupBeforeQuit() { · 81 unmodified lines | ||
| 1658 | 1748 | // stop QML |
| 1659 | 1749 | DependencyManager::destroy<OffscreenUi>(); |
| 1660 | 1750 | |
| 1751 | + DependencyManager::destroy<OffscreenQmlSurfaceCache>(); | |
| 1752 | + | |
| 1661 | 1753 | if (_snapshotSoundInjector != nullptr) { |
| 1662 | 1754 | _snapshotSoundInjector->stop(); |
| 1663 | 1755 | } |
| @@ -1685,6 +1777,10 @@ Application::~Application() { · 21 unmodified lines | ||
| 1685 | 1777 | |
| 1686 | 1778 | _physicsEngine->setCharacterController(nullptr); |
| 1687 | 1779 | |
| 1780 | + // the _shapeManager should have zero references | |
| 1781 | + _shapeManager.collectGarbage(); | |
| 1782 | + assert(_shapeManager.getNumShapes() == 0); | |
| 1783 | + | |
| 1688 | 1784 | // shutdown render engine |
| 1689 | 1785 | _main3DScene = nullptr; |
| 1690 | 1786 | _renderEngine = nullptr; |
| @@ -1713,15 +1809,9 @@ Application::~Application() { · 22 unmodified lines | ||
| 1713 | 1809 | |
| 1714 | 1810 | ResourceManager::cleanup(); |
| 1715 | 1811 | |
| 1716 | − QThread* nodeThread = DependencyManager::get<NodeList>()->thread(); | |
| 1717 | − | |
| 1718 | 1812 | // remove the NodeList from the DependencyManager |
| 1719 | 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 | 1815 | Leapmotion::destroy(); |
| 1726 | 1816 | |
| 1727 | 1817 | if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { |
| @@ -1736,6 +1826,15 @@ Application::~Application() { · 8 unmodified lines | ||
| 1736 | 1826 | |
| 1737 | 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 | 1838 | // Can't log to file passed this point, FileLogger about to be deleted |
| 1740 | 1839 | qInstallMessageHandler(LogHandler::verboseMessageHandler); |
| 1741 | 1840 | } |
| @@ -1771,15 +1870,9 @@ void Application::initializeGL() { · 29 unmodified lines | ||
| 1771 | 1870 | |
| 1772 | 1871 | // Set up the render engine |
| 1773 | 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 | 1873 | 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); | |
| 1783 | 1876 | _renderEngine->load(); |
| 1784 | 1877 | _renderEngine->registerScene(_main3DScene); |
| 1785 | 1878 | |
| @@ -1828,14 +1921,10 @@ void Application::initializeUi() { · 42 unmodified lines | ||
| 1828 | 1921 | UpdateDialog::registerType(); |
| 1829 | 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 | 1924 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); |
| 1836 | 1925 | offscreenUi->create(_glWidget->qglContext()); |
| 1837 | 1926 | |
| 1838 | − auto rootContext = offscreenUi->getRootContext(); | |
| 1927 | + auto surfaceContext = offscreenUi->getSurfaceContext(); | |
| 1839 | 1928 | |
| 1840 | 1929 | offscreenUi->setProxyWindow(_window->windowHandle()); |
| 1841 | 1930 | offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); |
| @@ -1847,7 +1936,7 @@ void Application::initializeUi() { · 5 unmodified lines | ||
| 1847 | 1936 | // do better detection in the offscreen UI of what has focus |
| 1848 | 1937 | offscreenUi->setNavigationFocused(false); |
| 1849 | 1938 | |
| 1850 | − auto engine = rootContext->engine(); | |
| 1939 | + auto engine = surfaceContext->engine(); | |
| 1851 | 1940 | connect(engine, &QQmlEngine::quit, [] { |
| 1852 | 1941 | qApp->quit(); |
| 1853 | 1942 | }); |
| @@ -1856,78 +1945,77 @@ void Application::initializeUi() { · 2 unmodified lines | ||
| 1856 | 1945 | |
| 1857 | 1946 | // For some reason there is already an "Application" object in the QML context, |
| 1858 | 1947 | // 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()); | |
| 1863 | 1951 | |
| 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()); | |
| 1866 | 1954 | _fileDownload = new FileScriptingInterface(engine); |
| 1867 | − rootContext->setContextProperty("File", _fileDownload); | |
| 1955 | + surfaceContext->setContextProperty("File", _fileDownload); | |
| 1868 | 1956 | 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)); | |
| 1877 | 1964 | |
| 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()); | |
| 1883 | 1971 | |
| 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()); | |
| 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 | 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 | 1981 | #endif |
| 1894 | 1982 | |
| 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()); | |
| 1903 | 1991 | |
| 1904 | 1992 | // 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()); | |
| 1928 | 2016 | |
| 1929 | 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 | 2154 | _myCamera.setOrientation(glm::quat_cast(camMat)); |
| 2067 | 2155 | } else { |
| 2068 | 2156 | _myCamera.setPosition(myAvatar->getDefaultEyePosition()); |
| 2069 | − _myCamera.setOrientation(myAvatar->getMyHead()->getCameraOrientation()); | |
| 2157 | + _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); | |
| 2070 | 2158 | } |
| 2071 | 2159 | } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { |
| 2072 | 2160 | if (isHMDMode()) { |
| @@ -2186,6 +2274,9 @@ void Application::paintGL() { · 113 unmodified lines | ||
| 2186 | 2274 | }); |
| 2187 | 2275 | renderArgs._context->setStereoProjections(eyeProjections); |
| 2188 | 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 | 2281 | renderArgs._blitFramebuffer = finalFramebuffer; |
| 2191 | 2282 | displaySide(&renderArgs, _myCamera); |
| @@ -2379,15 +2470,16 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 187 unmodified lines | ||
| 2379 | 2470 | |
| 2380 | 2471 | // Check HMD use (may be technically available without being in use) |
| 2381 | 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 | 2476 | Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false }; |
| 2385 | 2477 | Setting::Handle<bool> firstRun{ Settings::firstRun, true }; |
| 2386 | 2478 | |
| 2387 | 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 | 2483 | qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent << |
| 2392 | 2484 | ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial; |
| 2393 | 2485 | |
| @@ -2401,10 +2493,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 7 unmodified lines | ||
| 2401 | 2493 | |
| 2402 | 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 | 2503 | if (shouldGoToTutorial) { |
| 2405 | 2504 | if (sandboxIsRunning) { |
| 2406 | 2505 | qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; |
| 2407 | 2506 | DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH); |
| 2507 | + sentTo = SENT_TO_TUTORIAL; | |
| 2408 | 2508 | } else { |
| 2409 | 2509 | qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry."; |
| 2410 | 2510 | if (firstRun.get()) { |
| @@ -2412,8 +2512,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 1 unmodified line | ||
| 2412 | 2512 | } |
| 2413 | 2513 | if (addressLookupString.isEmpty()) { |
| 2414 | 2514 | DependencyManager::get<AddressManager>()->goToEntry(); |
| 2515 | + sentTo = SENT_TO_ENTRY; | |
| 2415 | 2516 | } else { |
| 2416 | 2517 | DependencyManager::get<AddressManager>()->loadSettings(addressLookupString); |
| 2518 | + sentTo = SENT_TO_PREVIOUS_LOCATION; | |
| 2417 | 2519 | } |
| 2418 | 2520 | } |
| 2419 | 2521 | } else { |
| @@ -2426,23 +2528,40 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 6 unmodified lines | ||
| 2426 | 2528 | |
| 2427 | 2529 | // If this is a first run we short-circuit the address passed in |
| 2428 | 2530 | if (isFirstRun) { |
| 2429 | − if (isUsingHMD) { | |
| 2531 | + if (isUsingHMDAndHandControllers) { | |
| 2430 | 2532 | if (sandboxIsRunning) { |
| 2431 | 2533 | qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; |
| 2432 | 2534 | DependencyManager::get<AddressManager>()->goToLocalSandbox(); |
| 2535 | + sentTo = SENT_TO_SANDBOX; | |
| 2433 | 2536 | } else { |
| 2434 | 2537 | qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry."; |
| 2435 | 2538 | DependencyManager::get<AddressManager>()->goToEntry(); |
| 2539 | + sentTo = SENT_TO_ENTRY; | |
| 2436 | 2540 | } |
| 2437 | 2541 | } else { |
| 2438 | 2542 | DependencyManager::get<AddressManager>()->goToEntry(); |
| 2543 | + sentTo = SENT_TO_ENTRY; | |
| 2439 | 2544 | } |
| 2440 | 2545 | } else { |
| 2441 | 2546 | qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString); |
| 2442 | 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 | 2565 | _connectionMonitor.init(); |
| 2447 | 2566 | |
| 2448 | 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 | 2896 | if (isShifted && isMeta && !isOption) { |
| 2778 | 2897 | Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings); |
| 2779 | 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 | 2910 | takeSnapshot(true); |
| 2781 | 2911 | } |
| 2782 | 2912 | break; |
| @@ -3951,6 +4081,7 @@ void Application::updateMyAvatarLookAtPosition() { · 1168 unmodified lines | ||
| 3951 | 4081 | lookAtPosition.x = -lookAtPosition.x; |
| 3952 | 4082 | } |
| 3953 | 4083 | if (isHMD) { |
| 4084 | + // TODO -- this code is probably wrong, getHeadPose() returns something in sensor frame, not avatar | |
| 3954 | 4085 | glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose(); |
| 3955 | 4086 | glm::quat hmdRotation = glm::quat_cast(headPose); |
| 3956 | 4087 | lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition); |
| @@ -3992,9 +4123,10 @@ void Application::updateMyAvatarLookAtPosition() { · 35 unmodified lines | ||
| 3992 | 4123 | } |
| 3993 | 4124 | } else { |
| 3994 | 4125 | // 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)); | |
| 3998 | 4130 | } else { |
| 3999 | 4131 | lookAtSpot = myAvatar->getHead()->getEyePosition() + |
| 4000 | 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 | 4625 | getEntities()->getTree()->withWriteLock([&] { |
| 4494 | 4626 | PerformanceTimer perfTimer("handleOutgoingChanges"); |
| 4495 | − const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates(); | |
| 4496 | − _entitySimulation->handleDeactivatedMotionStates(deactivations); | |
| 4497 | 4627 | |
| 4498 | 4628 | const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates(); |
| 4499 | 4629 | _entitySimulation->handleChangedMotionStates(outgoingChanges); |
| 4500 | 4630 | avatarManager->handleChangedMotionStates(outgoingChanges); |
| 4631 | + | |
| 4632 | + const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates(); | |
| 4633 | + _entitySimulation->handleDeactivatedMotionStates(deactivations); | |
| 4501 | 4634 | }); |
| 4502 | 4635 | |
| 4503 | 4636 | if (!_aboutToQuit) { |
| @@ -4885,12 +5018,6 @@ QRect Application::getDesirableApplicationGeometry() const { · 381 unmodified lines | ||
| 4885 | 5018 | return applicationGeometry; |
| 4886 | 5019 | } |
| 4887 | 5020 | |
| 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 | − | |
| 4894 | 5021 | // FIXME, preprocessor guard this check to occur only in DEBUG builds |
| 4895 | 5022 | static QThread * activeRenderingThread = nullptr; |
| 4896 | 5023 | |
| @@ -4947,7 +5074,7 @@ namespace render { · 50 unmodified lines | ||
| 4947 | 5074 | template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); } |
| 4948 | 5075 | template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } |
| 4949 | 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 | 5078 | PerformanceTimer perfTimer("worldBox"); |
| 4952 | 5079 | |
| 4953 | 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 | |
| 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 | − | |
| 5044 | 5087 | void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) { |
| 5045 | 5088 | |
| 5046 | 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 | 5107 | // The pending changes collecting the changes here |
| 5065 | 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 | 5110 | // Assuming nothing gets rendered through that |
| 5077 | 5111 | if (!selfAvatarOnly) { |
| 5078 | 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 | 5146 | PerformanceTimer perfTimer("SceneProcessTransaction"); |
| 5119 | 5147 | _main3DScene->enqueueTransaction(transaction); |
| @@ -6384,21 +6412,6 @@ void Application::loadAddAvatarBookmarkDialog() const { · 1264 unmodified lines | ||
| 6384 | 6412 | } |
| 6385 | 6413 | |
| 6386 | 6414 | 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 | − | |
| 6402 | 6415 | postLambdaEvent([notify, includeAnimated, aspectRatio, this] { |
| 6403 | 6416 | // Get a screenshot and save it |
| 6404 | 6417 | QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio)); |
| @@ -6811,6 +6824,35 @@ void Application::updateDisplayMode() { · 406 unmodified lines | ||
| 6811 | 6824 | Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); |
| 6812 | 6825 | } |
| 6813 | 6826 | |
| 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 | + | |
| 6814 | 6856 | mat4 Application::getEyeProjection(int eye) const { |
| 6815 | 6857 | QMutexLocker viewLocker(&_viewMutex); |
| 6816 | 6858 | if (isHMDMode()) { |