Showing the changes to interface/src/Application.cpp (1 of 233 files). Show all
Unified · Split
| @@ -100,6 +100,7 @@ · 99 unmodified lines | ||
| 100 | 100 | #include <MainWindow.h> |
| 101 | 101 | #include <MappingRequest.h> |
| 102 | 102 | #include <MessagesClient.h> |
| 103 | +#include <hfm/ModelFormatRegistry.h> | |
| 103 | 104 | #include <model-networking/ModelCacheScriptingInterface.h> |
| 104 | 105 | #include <model-networking/TextureCacheScriptingInterface.h> |
| 105 | 106 | #include <ModelEntityItem.h> |
| @@ -150,7 +151,6 @@ · 44 unmodified lines | ||
| 150 | 151 | #include <trackers/EyeTracker.h> |
| 151 | 152 | #include <avatars-renderer/ScriptAvatar.h> |
| 152 | 153 | #include <RenderableEntityItem.h> |
| 153 | −#include <procedural/ProceduralSkybox.h> | |
| 154 | 154 | #include <model-networking/MaterialCache.h> |
| 155 | 155 | #include "recording/ClipCache.h" |
| 156 | 156 | |
| @@ -329,7 +329,13 @@ static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entitie · 172 unmodified lines | ||
| 329 | 329 | |
| 330 | 330 | static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); |
| 331 | 331 | |
| 332 | −Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); | |
| 332 | +Setting::Handle<int> maxOctreePacketsPerSecond{"maxOctreePPS", DEFAULT_MAX_OCTREE_PPS}; | |
| 333 | + | |
| 334 | +Setting::Handle<bool> loginDialogPoppedUp{"loginDialogPoppedUp", false}; | |
| 335 | + | |
| 336 | +static const QString STANDARD_TO_ACTION_MAPPING_NAME = "Standard to Action"; | |
| 337 | +static const QString NO_MOVEMENT_MAPPING_NAME = "Standard to Action (No Movement)"; | |
| 338 | +static const QString NO_MOVEMENT_MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/standard_nomovement.json"; | |
| 333 | 339 | |
| 334 | 340 | static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; |
| 335 | 341 | static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds |
| @@ -832,6 +838,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 496 unmodified lines | ||
| 832 | 838 | DependencyManager::set<NodeList>(NodeType::Agent, listenPort); |
| 833 | 839 | DependencyManager::set<recording::ClipCache>(); |
| 834 | 840 | DependencyManager::set<GeometryCache>(); |
| 841 | + DependencyManager::set<ModelFormatRegistry>(); // ModelFormatRegistry must be defined before ModelCache. See the ModelCache constructor. | |
| 835 | 842 | DependencyManager::set<ModelCache>(); |
| 836 | 843 | DependencyManager::set<ModelCacheScriptingInterface>(); |
| 837 | 844 | DependencyManager::set<ScriptCache>(); |
| @@ -972,6 +979,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 134 unmodified lines | ||
| 972 | 979 | _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), |
| 973 | 980 | _hmdTabletScale("hmdTabletScale", DEFAULT_HMD_TABLET_SCALE_PERCENT), |
| 974 | 981 | _desktopTabletScale("desktopTabletScale", DEFAULT_DESKTOP_TABLET_SCALE_PERCENT), |
| 982 | + _firstRun(Settings::firstRun, true), | |
| 975 | 983 | _desktopTabletBecomesToolbarSetting("desktopTabletBecomesToolbar", DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR), |
| 976 | 984 | _hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR), |
| 977 | 985 | _preferStylusOverLaserSetting("preferStylusOverLaser", DEFAULT_PREFER_STYLUS_OVER_LASER), |
| @@ -990,12 +998,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 12 unmodified lines | ||
| 990 | 998 | _lastFaceTrackerUpdate(0), |
| 991 | 999 | _snapshotSound(nullptr), |
| 992 | 1000 | _sampleSound(nullptr) |
| 993 | − | |
| 994 | 1001 | { |
| 995 | 1002 | |
| 996 | 1003 | auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); |
| 997 | 1004 | setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); |
| 998 | 1005 | setProperty(hifi::properties::CRASHED, _previousSessionCrashed); |
| 1006 | + | |
| 999 | 1007 | { |
| 1000 | 1008 | const QStringList args = arguments(); |
| 1001 | 1009 | |
| @@ -1269,6 +1277,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 267 unmodified lines | ||
| 1269 | 1277 | setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0"); |
| 1270 | 1278 | }); |
| 1271 | 1279 | connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode); |
| 1280 | + connect(this, &Application::activeDisplayPluginChanged, this, [&](){ | |
| 1281 | + if (getLoginDialogPoppedUp()) { | |
| 1282 | + auto dialogsManager = DependencyManager::get<DialogsManager>(); | |
| 1283 | + auto keyboard = DependencyManager::get<Keyboard>(); | |
| 1284 | + if (_firstRun.get()) { | |
| 1285 | + // display mode changed. Don't allow auto-switch to work after this session. | |
| 1286 | + _firstRun.set(false); | |
| 1287 | + } | |
| 1288 | + if (isHMDMode()) { | |
| 1289 | + emit loginDialogFocusDisabled(); | |
| 1290 | + dialogsManager->hideLoginDialog(); | |
| 1291 | + createLoginDialogOverlay(); | |
| 1292 | + } else { | |
| 1293 | + getOverlays().deleteOverlay(_loginDialogOverlayID); | |
| 1294 | + _loginDialogOverlayID = OverlayID(); | |
| 1295 | + _loginStateManager.tearDown(); | |
| 1296 | + dialogsManager->showLoginDialog(); | |
| 1297 | + emit loginDialogFocusEnabled(); | |
| 1298 | + } | |
| 1299 | + } | |
| 1300 | + }); | |
| 1272 | 1301 | |
| 1273 | 1302 | // Save avatar location immediately after a teleport. |
| 1274 | 1303 | connect(myAvatar.get(), &MyAvatar::positionGoneTo, |
| @@ -1473,9 +1502,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 198 unmodified lines | ||
| 1473 | 1502 | qDebug() << "Detected installer type:" << installerType; |
| 1474 | 1503 | qDebug() << "Detected installer campaign:" << installerCampaign; |
| 1475 | 1504 | |
| 1476 | − // add firstRun flag from settings to launch event | |
| 1477 | − Setting::Handle<bool> firstRun { Settings::firstRun, true }; | |
| 1478 | − | |
| 1479 | 1505 | auto& userActivityLogger = UserActivityLogger::getInstance(); |
| 1480 | 1506 | if (userActivityLogger.isEnabled()) { |
| 1481 | 1507 | // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. |
| @@ -1524,7 +1550,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 42 unmodified lines | ||
| 1524 | 1550 | properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3; |
| 1525 | 1551 | } |
| 1526 | 1552 | |
| 1527 | − properties["first_run"] = firstRun.get(); | |
| 1553 | + properties["first_run"] = _firstRun.get(); | |
| 1528 | 1554 | |
| 1529 | 1555 | // add the user's machine ID to the launch event |
| 1530 | 1556 | QString machineFingerPrint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); |
| @@ -1737,27 +1763,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 206 unmodified lines | ||
| 1737 | 1763 | userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice()); |
| 1738 | 1764 | } |
| 1739 | 1765 | |
| 1740 | − { | |
| 1741 | − auto scriptEngines = DependencyManager::get<ScriptEngines>().data(); | |
| 1742 | − // this will force the model the look at the correct directory (weird order of operations issue) | |
| 1743 | − scriptEngines->reloadLocalFiles(); | |
| 1744 | − | |
| 1745 | − // do this as late as possible so that all required subsystems are initialized | |
| 1746 | − // If we've overridden the default scripts location, just load default scripts | |
| 1747 | − // otherwise, load 'em all | |
| 1748 | − | |
| 1749 | − // we just want to see if --scripts was set, we've already parsed it and done | |
| 1750 | − // the change in PathUtils. Rather than pass that in the constructor, lets just | |
| 1751 | − // look (this could be debated) | |
| 1752 | − QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH); | |
| 1753 | − QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str())); | |
| 1754 | − if (!defaultScriptsLocation.exists()) { | |
| 1755 | − scriptEngines->loadDefaultScripts(); | |
| 1756 | − scriptEngines->defaultScriptsLocationOverridden(true); | |
| 1757 | − } else { | |
| 1758 | − scriptEngines->loadScripts(); | |
| 1759 | − } | |
| 1760 | − } | |
| 1766 | + QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH); | |
| 1767 | + _defaultScriptsLocation = getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()); | |
| 1761 | 1768 | |
| 1762 | 1769 | // Make sure we don't time out during slow operations at startup |
| 1763 | 1770 | updateHeartbeat(); |
| @@ -1778,11 +1785,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 14 unmodified lines | ||
| 1778 | 1785 | } |
| 1779 | 1786 | }); |
| 1780 | 1787 | |
| 1788 | + connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() { | |
| 1789 | +#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML) | |
| 1790 | + // Do not show login dialog if requested not to on the command line | |
| 1791 | + QString hifiNoLoginCommandLineKey = QString("--").append(HIFI_NO_LOGIN_COMMAND_LINE_KEY); | |
| 1792 | + int index = arguments().indexOf(hifiNoLoginCommandLineKey); | |
| 1793 | + if (index != -1) { | |
| 1794 | + resumeAfterLoginDialogActionTaken(); | |
| 1795 | + return; | |
| 1796 | + } | |
| 1797 | + | |
| 1798 | + showLoginScreen(); | |
| 1799 | +#else | |
| 1800 | + resumeAfterLoginDialogActionTaken(); | |
| 1801 | +#endif | |
| 1802 | + }); | |
| 1803 | + | |
| 1781 | 1804 | // Make sure we don't time out during slow operations at startup |
| 1782 | 1805 | updateHeartbeat(); |
| 1783 | 1806 | QTimer* settingsTimer = new QTimer(); |
| 1784 | 1807 | moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{ |
| 1785 | − // This needs to run on the settings thread, so we need to pass the `settingsTimer` as the | |
| 1808 | + // This needs to run on the settings thread, so we need to pass the `settingsTimer` as the | |
| 1786 | 1809 | // receiver object, otherwise it will run on the application thread and trigger a warning |
| 1787 | 1810 | // about trying to kill the timer on the main thread. |
| 1788 | 1811 | connect(qApp, &Application::beforeAboutToQuit, settingsTimer, [this, settingsTimer]{ |
| @@ -2235,29 +2258,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 446 unmodified lines | ||
| 2235 | 2258 | |
| 2236 | 2259 | _snapshotSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/snapshot/snap.wav")); |
| 2237 | 2260 | |
| 2238 | − QVariant testProperty = property(hifi::properties::TEST); | |
| 2239 | − qDebug() << testProperty; | |
| 2240 | − if (testProperty.isValid()) { | |
| 2241 | − const auto testScript = property(hifi::properties::TEST).toUrl(); | |
| 2242 | − | |
| 2243 | − // Set last parameter to exit interface when the test script finishes, if so requested | |
| 2244 | − DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished); | |
| 2245 | − | |
| 2246 | − // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. | |
| 2247 | − if (arguments().contains("--url")) { | |
| 2248 | − auto reply = SandboxUtils::getStatus(); | |
| 2249 | − connect(reply, &QNetworkReply::finished, this, [this, reply] { | |
| 2250 | − handleSandboxStatus(reply); | |
| 2251 | − }); | |
| 2252 | − } | |
| 2253 | − } else { | |
| 2254 | − PROFILE_RANGE(render, "GetSandboxStatus"); | |
| 2255 | − auto reply = SandboxUtils::getStatus(); | |
| 2256 | − connect(reply, &QNetworkReply::finished, this, [this, reply] { | |
| 2257 | − handleSandboxStatus(reply); | |
| 2258 | − }); | |
| 2259 | − } | |
| 2260 | − | |
| 2261 | 2261 | // Monitor model assets (e.g., from Clara.io) added to the world that may need resizing. |
| 2262 | 2262 | static const int ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS = 1000; |
| 2263 | 2263 | _addAssetToWorldResizeTimer.setInterval(ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable |
| @@ -2331,33 +2331,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 67 unmodified lines | ||
| 2331 | 2331 | connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground); |
| 2332 | 2332 | connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); |
| 2333 | 2333 | AndroidHelper::instance().notifyLoadComplete(); |
| 2334 | −#else | |
| 2335 | −#if !defined(DISABLE_QML) | |
| 2336 | − // Do not show login dialog if requested not to on the command line | |
| 2337 | − const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "--no-login-suggestion"; | |
| 2338 | − int index = arguments().indexOf(HIFI_NO_LOGIN_COMMAND_LINE_KEY); | |
| 2339 | − if (index == -1) { | |
| 2340 | − // request not found | |
| 2341 | − static int CHECK_LOGIN_TIMER = 3000; | |
| 2342 | − QTimer* checkLoginTimer = new QTimer(this); | |
| 2343 | − checkLoginTimer->setInterval(CHECK_LOGIN_TIMER); | |
| 2344 | − checkLoginTimer->setSingleShot(true); | |
| 2345 | − connect(checkLoginTimer, &QTimer::timeout, this, []() { | |
| 2346 | − auto accountManager = DependencyManager::get<AccountManager>(); | |
| 2347 | − auto dialogsManager = DependencyManager::get<DialogsManager>(); | |
| 2348 | − if (!accountManager->isLoggedIn()) { | |
| 2349 | − Setting::Handle<bool>{ "loginDialogPoppedUp", false }.set(true); | |
| 2350 | − dialogsManager->showLoginDialog(); | |
| 2351 | − QJsonObject loginData = {}; | |
| 2352 | − loginData["action"] = "login dialog shown"; | |
| 2353 | − UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData); | |
| 2354 | − } | |
| 2355 | − }); | |
| 2356 | − Setting::Handle<bool>{ "loginDialogPoppedUp", false }.set(false); | |
| 2357 | − checkLoginTimer->start(); | |
| 2358 | − } | |
| 2359 | −#endif | |
| 2360 | 2334 | #endif |
| 2335 | + pauseUntilLoginDetermined(); | |
| 2361 | 2336 | } |
| 2362 | 2337 | |
| 2363 | 2338 | void Application::updateVerboseLogging() { |
| @@ -2497,7 +2472,7 @@ void Application::onAboutToQuit() { · 133 unmodified lines | ||
| 2497 | 2472 | // so its persisted explicitly here |
| 2498 | 2473 | Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName()); |
| 2499 | 2474 | |
| 2500 | − Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(false); | |
| 2475 | + loginDialogPoppedUp.set(false); | |
| 2501 | 2476 | |
| 2502 | 2477 | getActiveDisplayPlugin()->deactivate(); |
| 2503 | 2478 | if (_autoSwitchDisplayModeSupportedHMDPlugin |
| @@ -2666,7 +2641,7 @@ Application::~Application() { · 162 unmodified lines | ||
| 2666 | 2641 | |
| 2667 | 2642 | // shutdown graphics engine |
| 2668 | 2643 | _graphicsEngine.shutdown(); |
| 2669 | − | |
| 2644 | + | |
| 2670 | 2645 | _gameWorkload.shutdown(); |
| 2671 | 2646 | |
| 2672 | 2647 | DependencyManager::destroy<Preferences>(); |
| @@ -2694,6 +2669,7 @@ Application::~Application() { · 21 unmodified lines | ||
| 2694 | 2669 | DependencyManager::destroy<TextureCache>(); |
| 2695 | 2670 | DependencyManager::destroy<ModelCacheScriptingInterface>(); |
| 2696 | 2671 | DependencyManager::destroy<ModelCache>(); |
| 2672 | + DependencyManager::destroy<ModelFormatRegistry>(); | |
| 2697 | 2673 | DependencyManager::destroy<ScriptCache>(); |
| 2698 | 2674 | DependencyManager::destroy<SoundCacheScriptingInterface>(); |
| 2699 | 2675 | DependencyManager::destroy<SoundCache>(); |
| @@ -2822,8 +2798,6 @@ void Application::initializeGL() { · 122 unmodified lines | ||
| 2822 | 2798 | _graphicsEngine.initializeGPU(_glWidget); |
| 2823 | 2799 | } |
| 2824 | 2800 | |
| 2825 | −static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; | |
| 2826 | − | |
| 2827 | 2801 | void Application::initializeDisplayPlugins() { |
| 2828 | 2802 | auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); |
| 2829 | 2803 | Setting::Handle<QString> activeDisplayPluginSetting{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME, displayPlugins.at(0)->getName() }; |
| @@ -2859,45 +2833,6 @@ void Application::initializeDisplayPlugins() { · 29 unmodified lines | ||
| 2859 | 2833 | |
| 2860 | 2834 | // Submit a default frame to render until the engine starts up |
| 2861 | 2835 | updateRenderArgs(0.0f); |
| 2862 | − | |
| 2863 | −#define ENABLE_SPLASH_FRAME 0 | |
| 2864 | −#if ENABLE_SPLASH_FRAME | |
| 2865 | − { | |
| 2866 | − QMutexLocker viewLocker(&_renderArgsMutex); | |
| 2867 | − | |
| 2868 | − if (_appRenderArgs._isStereo) { | |
| 2869 | − _gpuContext->enableStereo(true); | |
| 2870 | − _gpuContext->setStereoProjections(_appRenderArgs._eyeProjections); | |
| 2871 | − _gpuContext->setStereoViews(_appRenderArgs._eyeOffsets); | |
| 2872 | − } | |
| 2873 | − | |
| 2874 | − // Frame resources | |
| 2875 | − auto framebufferCache = DependencyManager::get<FramebufferCache>(); | |
| 2876 | − gpu::FramebufferPointer finalFramebuffer = framebufferCache->getFramebuffer(); | |
| 2877 | − std::shared_ptr<ProceduralSkybox> procedural = std::make_shared<ProceduralSkybox>(); | |
| 2878 | − procedural->parse(SPLASH_SKYBOX); | |
| 2879 | − | |
| 2880 | − _gpuContext->beginFrame(_appRenderArgs._view, _appRenderArgs._headPose); | |
| 2881 | − gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { | |
| 2882 | − batch.resetStages(); | |
| 2883 | − batch.enableStereo(false); | |
| 2884 | − batch.setFramebuffer(finalFramebuffer); | |
| 2885 | − batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); | |
| 2886 | − batch.enableSkybox(true); | |
| 2887 | − batch.enableStereo(_appRenderArgs._isStereo); | |
| 2888 | − batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); | |
| 2889 | − procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum()); | |
| 2890 | − }); | |
| 2891 | − auto frame = _gpuContext->endFrame(); | |
| 2892 | − frame->frameIndex = 0; | |
| 2893 | − frame->framebuffer = finalFramebuffer; | |
| 2894 | − frame->pose = _appRenderArgs._headPose; | |
| 2895 | − frame->framebufferRecycler = [framebufferCache, procedural](const gpu::FramebufferPointer& framebuffer) { | |
| 2896 | − framebufferCache->releaseFramebuffer(framebuffer); | |
| 2897 | − }; | |
| 2898 | − _displayPlugin->submitFrame(frame); | |
| 2899 | − } | |
| 2900 | −#endif | |
| 2901 | 2836 | } |
| 2902 | 2837 | |
| 2903 | 2838 | void Application::initializeRenderEngine() { |
| @@ -2913,6 +2848,32 @@ extern void setupPreferences(); · 9 unmodified lines | ||
| 2913 | 2848 | static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false); |
| 2914 | 2849 | #endif |
| 2915 | 2850 | |
| 2851 | +void Application::showLoginScreen() { | |
| 2852 | +#if !defined(DISABLE_QML) | |
| 2853 | + auto accountManager = DependencyManager::get<AccountManager>(); | |
| 2854 | + auto dialogsManager = DependencyManager::get<DialogsManager>(); | |
| 2855 | + if (!accountManager->isLoggedIn()) { | |
| 2856 | + if (!isHMDMode()) { | |
| 2857 | + auto toolbar = DependencyManager::get<ToolbarScriptingInterface>()->getToolbar("com.highfidelity.interface.toolbar.system"); | |
| 2858 | + toolbar->writeProperty("visible", false); | |
| 2859 | + } | |
| 2860 | + _loginDialogPoppedUp = true; | |
| 2861 | + dialogsManager->showLoginDialog(); | |
| 2862 | + emit loginDialogFocusEnabled(); | |
| 2863 | + QJsonObject loginData = {}; | |
| 2864 | + loginData["action"] = "login dialog shown"; | |
| 2865 | + UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData); | |
| 2866 | + _window->setWindowTitle("High Fidelity Interface"); | |
| 2867 | + } else { | |
| 2868 | + resumeAfterLoginDialogActionTaken(); | |
| 2869 | + } | |
| 2870 | + _loginDialogPoppedUp = !accountManager->isLoggedIn(); | |
| 2871 | + loginDialogPoppedUp.set(_loginDialogPoppedUp); | |
| 2872 | +#else | |
| 2873 | + resumeAfterLoginDialogActionTaken(); | |
| 2874 | +#endif | |
| 2875 | +} | |
| 2876 | + | |
| 2916 | 2877 | void Application::initializeUi() { |
| 2917 | 2878 | AddressBarDialog::registerType(); |
| 2918 | 2879 | ErrorDialog::registerType(); |
| @@ -3059,8 +3020,7 @@ void Application::initializeUi() { · 140 unmodified lines | ||
| 3059 | 3020 | auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); |
| 3060 | 3021 | // first sort the plugins into groupings: standard, advanced, developer |
| 3061 | 3022 | std::stable_sort(displayPlugins.begin(), displayPlugins.end(), |
| 3062 | − [](const DisplayPluginPointer& a, const DisplayPluginPointer& b)->bool { return a->getGrouping() < b->getGrouping(); }); | |
| 3063 | − | |
| 3023 | + [](const DisplayPluginPointer& a, const DisplayPluginPointer& b) -> bool { return a->getGrouping() < b->getGrouping(); }); | |
| 3064 | 3024 | int dpIndex = 1; |
| 3065 | 3025 | // concatenate the groupings into a single list in the order: standard, advanced, developer |
| 3066 | 3026 | for(const auto& displayPlugin : displayPlugins) { |
| @@ -3074,6 +3034,7 @@ void Application::initializeUi() { · 7 unmodified lines | ||
| 3074 | 3034 | } |
| 3075 | 3035 | #endif |
| 3076 | 3036 | |
| 3037 | + | |
| 3077 | 3038 | // The display plugins are created before the menu now, so we need to do this here to hide the menu bar |
| 3078 | 3039 | // now that it exists |
| 3079 | 3040 | if (_window && _window->isFullScreen()) { |
| @@ -3500,8 +3461,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 420 unmodified lines | ||
| 3500 | 3461 | bool isUsingHMD = _displayPlugin->isHmd(); |
| 3501 | 3462 | bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD; |
| 3502 | 3463 | |
| 3503 | − Setting::Handle<bool> firstRun{ Settings::firstRun, true }; | |
| 3504 | − | |
| 3505 | 3464 | qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers; |
| 3506 | 3465 | |
| 3507 | 3466 | // when --url in command line, teleport to location |
| @@ -3523,12 +3482,12 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { · 15 unmodified lines | ||
| 3523 | 3482 | QString sentTo; |
| 3524 | 3483 | |
| 3525 | 3484 | // If this is a first run we short-circuit the address passed in |
| 3526 | − if (firstRun.get()) { | |
| 3485 | + if (_firstRun.get()) { | |
| 3527 | 3486 | #if !defined(Q_OS_ANDROID) |
| 3528 | 3487 | DependencyManager::get<AddressManager>()->goToEntry(); |
| 3529 | 3488 | sentTo = SENT_TO_ENTRY; |
| 3530 | 3489 | #endif |
| 3531 | − firstRun.set(false); | |
| 3490 | + _firstRun.set(false); | |
| 3532 | 3491 | |
| 3533 | 3492 | } else { |
| 3534 | 3493 | #if !defined(Q_OS_ANDROID) |
| @@ -3614,16 +3573,7 @@ void Application::setIsServerlessMode(bool serverlessDomain) { · 79 unmodified lines | ||
| 3614 | 3573 | } |
| 3615 | 3574 | } |
| 3616 | 3575 | |
| 3617 | −void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) { | |
| 3618 | − if (QThread::currentThread() != thread()) { | |
| 3619 | − QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL), Q_ARG(bool, errorDomain)); | |
| 3620 | − return; | |
| 3621 | − } | |
| 3622 | − | |
| 3623 | − if (domainURL.isEmpty()) { | |
| 3624 | − return; | |
| 3625 | − } | |
| 3626 | − | |
| 3576 | +std::map<QString, QString> Application::prepareServerlessDomainContents(QUrl domainURL) { | |
| 3627 | 3577 | QUuid serverlessSessionID = QUuid::createUuid(); |
| 3628 | 3578 | getMyAvatar()->setSessionUUID(serverlessSessionID); |
| 3629 | 3579 | auto nodeList = DependencyManager::get<NodeList>(); |
| @@ -3647,13 +3597,43 @@ void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) { · 17 unmodified lines | ||
| 3647 | 3597 | tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0); |
| 3648 | 3598 | } |
| 3649 | 3599 | |
| 3650 | − std::map<QString, QString> namedPaths = tmpTree->getNamedPaths(); | |
| 3651 | − if (errorDomain) { | |
| 3652 | − nodeList->getDomainHandler().loadedErrorDomain(namedPaths); | |
| 3653 | − } else { | |
| 3654 | − nodeList->getDomainHandler().connectedToServerless(namedPaths); | |
| 3600 | + return tmpTree->getNamedPaths(); | |
| 3601 | + | |
| 3602 | +} | |
| 3603 | + | |
| 3604 | +void Application::loadServerlessDomain(QUrl domainURL) { | |
| 3605 | + if (QThread::currentThread() != thread()) { | |
| 3606 | + QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL)); | |
| 3607 | + return; | |
| 3608 | + } | |
| 3609 | + | |
| 3610 | + if (domainURL.isEmpty()) { | |
| 3611 | + return; | |
| 3655 | 3612 | } |
| 3656 | 3613 | |
| 3614 | + auto namedPaths = prepareServerlessDomainContents(domainURL); | |
| 3615 | + auto nodeList = DependencyManager::get<NodeList>(); | |
| 3616 | + | |
| 3617 | + nodeList->getDomainHandler().connectedToServerless(namedPaths); | |
| 3618 | + | |
| 3619 | + _fullSceneReceivedCounter++; | |
| 3620 | +} | |
| 3621 | + | |
| 3622 | +void Application::loadErrorDomain(QUrl domainURL) { | |
| 3623 | + if (QThread::currentThread() != thread()) { | |
| 3624 | + QMetaObject::invokeMethod(this, "loadErrorDomain", Q_ARG(QUrl, domainURL)); | |
| 3625 | + return; | |
| 3626 | + } | |
| 3627 | + | |
| 3628 | + if (domainURL.isEmpty()) { | |
| 3629 | + return; | |
| 3630 | + } | |
| 3631 | + | |
| 3632 | + auto namedPaths = prepareServerlessDomainContents(domainURL); | |
| 3633 | + auto nodeList = DependencyManager::get<NodeList>(); | |
| 3634 | + | |
| 3635 | + nodeList->getDomainHandler().loadedErrorDomain(namedPaths); | |
| 3636 | + | |
| 3657 | 3637 | _fullSceneReceivedCounter++; |
| 3658 | 3638 | } |
| 3659 | 3639 | |
| @@ -3893,7 +3873,34 @@ void Application::keyPressEvent(QKeyEvent* event) { · 233 unmodified lines | ||
| 3893 | 3873 | return; |
| 3894 | 3874 | } |
| 3895 | 3875 | |
| 3896 | − if (hasFocus()) { | |
| 3876 | + if (hasFocus() && getLoginDialogPoppedUp()) { | |
| 3877 | + if (_keyboardMouseDevice->isActive()) { | |
| 3878 | + _keyboardMouseDevice->keyReleaseEvent(event); | |
| 3879 | + } | |
| 3880 | + | |
| 3881 | + bool isMeta = event->modifiers().testFlag(Qt::ControlModifier); | |
| 3882 | + bool isOption = event->modifiers().testFlag(Qt::AltModifier); | |
| 3883 | + switch (event->key()) { | |
| 3884 | + case Qt::Key_4: | |
| 3885 | + case Qt::Key_5: | |
| 3886 | + case Qt::Key_6: | |
| 3887 | + case Qt::Key_7: | |
| 3888 | + if (isMeta || isOption) { | |
| 3889 | + unsigned int index = static_cast<unsigned int>(event->key() - Qt::Key_1); | |
| 3890 | + auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); | |
| 3891 | + if (index < displayPlugins.size()) { | |
| 3892 | + auto targetPlugin = displayPlugins.at(index); | |
| 3893 | + QString targetName = targetPlugin->getName(); | |
| 3894 | + auto menu = Menu::getInstance(); | |
| 3895 | + QAction* action = menu->getActionForOption(targetName); | |
| 3896 | + if (action && !action->isChecked()) { | |
| 3897 | + action->trigger(); | |
| 3898 | + } | |
| 3899 | + } | |
| 3900 | + } | |
| 3901 | + break; | |
| 3902 | + } | |
| 3903 | + } else if (hasFocus()) { | |
| 3897 | 3904 | if (_keyboardMouseDevice->isActive()) { |
| 3898 | 3905 | _keyboardMouseDevice->keyPressEvent(event); |
| 3899 | 3906 | } |
| @@ -4420,7 +4427,7 @@ void Application::wheelEvent(QWheelEvent* event) const { · 520 unmodified lines | ||
| 4420 | 4427 | _controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts |
| 4421 | 4428 | |
| 4422 | 4429 | // if one of our scripts have asked to capture this event, then stop processing it |
| 4423 | − if (_controllerScriptingInterface->isWheelCaptured()) { | |
| 4430 | + if (_controllerScriptingInterface->isWheelCaptured() || getLoginDialogPoppedUp()) { | |
| 4424 | 4431 | return; |
| 4425 | 4432 | } |
| 4426 | 4433 | |
| @@ -5015,9 +5022,8 @@ void Application::loadSettings() { · 588 unmodified lines | ||
| 5015 | 5022 | } |
| 5016 | 5023 | } |
| 5017 | 5024 | |
| 5018 | − Setting::Handle<bool> firstRun { Settings::firstRun, true }; | |
| 5019 | 5025 | bool isFirstPerson = false; |
| 5020 | − if (firstRun.get()) { | |
| 5026 | + if (_firstRun.get()) { | |
| 5021 | 5027 | // If this is our first run, and no preferred devices were set, default to |
| 5022 | 5028 | // an HMD device if available. |
| 5023 | 5029 | auto displayPlugins = pluginManager->getDisplayPlugins(); |
| @@ -5167,6 +5173,141 @@ void Application::init() { · 143 unmodified lines | ||
| 5167 | 5173 | _entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace()); |
| 5168 | 5174 | } |
| 5169 | 5175 | |
| 5176 | +void Application::pauseUntilLoginDetermined() { | |
| 5177 | + if (QThread::currentThread() != qApp->thread()) { | |
| 5178 | + QMetaObject::invokeMethod(this, "pauseUntilLoginDetermined"); | |
| 5179 | + return; | |
| 5180 | + } | |
| 5181 | + | |
| 5182 | + auto myAvatar = getMyAvatar(); | |
| 5183 | + _previousAvatarTargetScale = myAvatar->getTargetScale(); | |
| 5184 | + _previousAvatarSkeletonModel = myAvatar->getSkeletonModelURL().toString(); | |
| 5185 | + myAvatar->setTargetScale(1.0f); | |
| 5186 | + myAvatar->setSkeletonModelURLFromScript(myAvatar->defaultFullAvatarModelUrl().toString()); | |
| 5187 | + myAvatar->setEnableMeshVisible(false); | |
| 5188 | + | |
| 5189 | + _controllerScriptingInterface->disableMapping(STANDARD_TO_ACTION_MAPPING_NAME); | |
| 5190 | + | |
| 5191 | + { | |
| 5192 | + auto userInputMapper = DependencyManager::get<UserInputMapper>(); | |
| 5193 | + if (userInputMapper->loadMapping(NO_MOVEMENT_MAPPING_JSON)) { | |
| 5194 | + _controllerScriptingInterface->enableMapping(NO_MOVEMENT_MAPPING_NAME); | |
| 5195 | + } | |
| 5196 | + } | |
| 5197 | + | |
| 5198 | + const auto& nodeList = DependencyManager::get<NodeList>(); | |
| 5199 | + // save interstitial mode setting until resuming. | |
| 5200 | + _interstitialModeEnabled = nodeList->getDomainHandler().getInterstitialModeEnabled(); | |
| 5201 | + nodeList->getDomainHandler().setInterstitialModeEnabled(false); | |
| 5202 | + | |
| 5203 | + auto menu = Menu::getInstance(); | |
| 5204 | + menu->getMenu("Edit")->setVisible(false); | |
| 5205 | + menu->getMenu("View")->setVisible(false); | |
| 5206 | + menu->getMenu("Navigate")->setVisible(false); | |
| 5207 | + menu->getMenu("Settings")->setVisible(false); | |
| 5208 | + _developerMenuVisible = menu->getMenu("Developer")->isVisible(); | |
| 5209 | + menu->setIsOptionChecked(MenuOption::Stats, false); | |
| 5210 | + if (_developerMenuVisible) { | |
| 5211 | + menu->getMenu("Developer")->setVisible(false); | |
| 5212 | + } | |
| 5213 | + _previousCameraMode = _myCamera.getMode(); | |
| 5214 | + _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); | |
| 5215 | + cameraModeChanged(); | |
| 5216 | + | |
| 5217 | + // disconnect domain handler. | |
| 5218 | + nodeList->getDomainHandler().disconnect(); | |
| 5219 | + | |
| 5220 | +} | |
| 5221 | + | |
| 5222 | +void Application::resumeAfterLoginDialogActionTaken() { | |
| 5223 | + if (QThread::currentThread() != qApp->thread()) { | |
| 5224 | + QMetaObject::invokeMethod(this, "resumeAfterLoginDialogActionTaken"); | |
| 5225 | + return; | |
| 5226 | + } | |
| 5227 | + | |
| 5228 | + if (!isHMDMode() && getDesktopTabletBecomesToolbarSetting()) { | |
| 5229 | + auto toolbar = DependencyManager::get<ToolbarScriptingInterface>()->getToolbar("com.highfidelity.interface.toolbar.system"); | |
| 5230 | + toolbar->writeProperty("visible", true); | |
| 5231 | + } else { | |
| 5232 | + getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(true); | |
| 5233 | + getApplicationCompositor().getReticleInterface()->setVisible(true); | |
| 5234 | + } | |
| 5235 | + | |
| 5236 | + updateSystemTabletMode(); | |
| 5237 | + | |
| 5238 | + { | |
| 5239 | + auto userInputMapper = DependencyManager::get<UserInputMapper>(); | |
| 5240 | + userInputMapper->unloadMapping(NO_MOVEMENT_MAPPING_JSON); | |
| 5241 | + _controllerScriptingInterface->disableMapping(NO_MOVEMENT_MAPPING_NAME); | |
| 5242 | + } | |
| 5243 | + | |
| 5244 | + auto myAvatar = getMyAvatar(); | |
| 5245 | + myAvatar->setTargetScale(_previousAvatarTargetScale); | |
| 5246 | + myAvatar->setSkeletonModelURLFromScript(_previousAvatarSkeletonModel); | |
| 5247 | + myAvatar->setEnableMeshVisible(true); | |
| 5248 | + | |
| 5249 | + _controllerScriptingInterface->enableMapping(STANDARD_TO_ACTION_MAPPING_NAME); | |
| 5250 | + | |
| 5251 | + const auto& nodeList = DependencyManager::get<NodeList>(); | |
| 5252 | + nodeList->getDomainHandler().setInterstitialModeEnabled(_interstitialModeEnabled); | |
| 5253 | + { | |
| 5254 | + auto scriptEngines = DependencyManager::get<ScriptEngines>().data(); | |
| 5255 | + // this will force the model the look at the correct directory (weird order of operations issue) | |
| 5256 | + scriptEngines->reloadLocalFiles(); | |
| 5257 | + | |
| 5258 | + if (!_defaultScriptsLocation.exists()) { | |
| 5259 | + scriptEngines->loadDefaultScripts(); | |
| 5260 | + scriptEngines->defaultScriptsLocationOverridden(true); | |
| 5261 | + } else { | |
| 5262 | + scriptEngines->loadScripts(); | |
| 5263 | + } | |
| 5264 | + } | |
| 5265 | + | |
| 5266 | + if (_firstRun.get()) { | |
| 5267 | + // not first run anymore since action was taken. | |
| 5268 | + _firstRun.set(false); | |
| 5269 | + } | |
| 5270 | + | |
| 5271 | + auto accountManager = DependencyManager::get<AccountManager>(); | |
| 5272 | + auto addressManager = DependencyManager::get<AddressManager>(); | |
| 5273 | + | |
| 5274 | + // restart domain handler. | |
| 5275 | + nodeList->getDomainHandler().resetting(); | |
| 5276 | + | |
| 5277 | + if (!accountManager->isLoggedIn()) { | |
| 5278 | + if (arguments().contains("--url")) { | |
| 5279 | + auto reply = SandboxUtils::getStatus(); | |
| 5280 | + connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); }); | |
| 5281 | + } else { | |
| 5282 | + addressManager->goToEntry(); | |
| 5283 | + } | |
| 5284 | + } else { | |
| 5285 | + QVariant testProperty = property(hifi::properties::TEST); | |
| 5286 | + if (testProperty.isValid()) { | |
| 5287 | + const auto testScript = property(hifi::properties::TEST).toUrl(); | |
| 5288 | + // Set last parameter to exit interface when the test script finishes, if so requested | |
| 5289 | + DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished); | |
| 5290 | + // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. | |
| 5291 | + if (arguments().contains("--url")) { | |
| 5292 | + auto reply = SandboxUtils::getStatus(); | |
| 5293 | + connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); }); | |
| 5294 | + } | |
| 5295 | + } else { | |
| 5296 | + auto reply = SandboxUtils::getStatus(); | |
| 5297 | + connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); }); | |
| 5298 | + } | |
| 5299 | + } | |
| 5300 | + | |
| 5301 | + auto menu = Menu::getInstance(); | |
| 5302 | + menu->getMenu("Edit")->setVisible(true); | |
| 5303 | + menu->getMenu("View")->setVisible(true); | |
| 5304 | + menu->getMenu("Navigate")->setVisible(true); | |
| 5305 | + menu->getMenu("Settings")->setVisible(true); | |
| 5306 | + menu->getMenu("Developer")->setVisible(_developerMenuVisible); | |
| 5307 | + _myCamera.setMode(_previousCameraMode); | |
| 5308 | + cameraModeChanged(); | |
| 5309 | +} | |
| 5310 | + | |
| 5170 | 5311 | void Application::loadAvatarScripts(const QVector<QString>& urls) { |
| 5171 | 5312 | auto scriptEngines = DependencyManager::get<ScriptEngines>(); |
| 5172 | 5313 | auto runningScripts = scriptEngines->getRunningScripts(); |
| @@ -5481,6 +5622,9 @@ void Application::rotationModeChanged() const { · 308 unmodified lines | ||
| 5481 | 5622 | |
| 5482 | 5623 | void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) { |
| 5483 | 5624 | // Create focus |
| 5625 | + if (qApp->getLoginDialogPoppedUp()) { | |
| 5626 | + return; | |
| 5627 | + } | |
| 5484 | 5628 | if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { |
| 5485 | 5629 | _keyboardFocusHighlight = std::make_shared<Cube3DOverlay>(); |
| 5486 | 5630 | _keyboardFocusHighlight->setAlpha(1.0f); |
| @@ -5508,6 +5652,9 @@ QUuid Application::getKeyboardFocusEntity() const { · 21 unmodified lines | ||
| 5508 | 5652 | static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; |
| 5509 | 5653 | |
| 5510 | 5654 | void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { |
| 5655 | + if (qApp->getLoginDialogPoppedUp()) { | |
| 5656 | + return; | |
| 5657 | + } | |
| 5511 | 5658 | if (_keyboardFocusedEntity.get() != entityItemID) { |
| 5512 | 5659 | _keyboardFocusedEntity.set(entityItemID); |
| 5513 | 5660 | |
| @@ -5548,6 +5695,15 @@ OverlayID Application::getKeyboardFocusOverlay() { · 34 unmodified lines | ||
| 5548 | 5695 | |
| 5549 | 5696 | void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) { |
| 5550 | 5697 | if (overlayID != _keyboardFocusedOverlay.get()) { |
| 5698 | + if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) { | |
| 5699 | + if (overlayID == _loginDialogOverlayID) { | |
| 5700 | + emit loginDialogFocusEnabled(); | |
| 5701 | + } else { | |
| 5702 | + // that's the only overlay we want in focus; | |
| 5703 | + return; | |
| 5704 | + } | |
| 5705 | + } | |
| 5706 | + | |
| 5551 | 5707 | _keyboardFocusedOverlay.set(overlayID); |
| 5552 | 5708 | |
| 5553 | 5709 | if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) { |
| @@ -5607,7 +5763,44 @@ void Application::updateSecondaryCameraViewFrustum() { · 53 unmodified lines | ||
| 5607 | 5763 | } |
| 5608 | 5764 | |
| 5609 | 5765 | ViewFrustum secondaryViewFrustum; |
| 5610 | − if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { | |
| 5766 | + if (camera->portalProjection && !camera->attachedEntityId.isNull() && !camera->portalEntranceEntityId.isNull()) { | |
| 5767 | + auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | |
| 5768 | + EntityItemPointer portalEntrance = qApp->getEntities()->getTree()->findEntityByID(camera->portalEntranceEntityId); | |
| 5769 | + EntityItemPointer portalExit = qApp->getEntities()->getTree()->findEntityByID(camera->attachedEntityId); | |
| 5770 | + | |
| 5771 | + glm::vec3 portalEntrancePropertiesPosition = portalEntrance->getWorldPosition(); | |
| 5772 | + glm::quat portalEntrancePropertiesRotation = portalEntrance->getWorldOrientation(); | |
| 5773 | + glm::mat4 worldFromPortalEntranceRotation = glm::mat4_cast(portalEntrancePropertiesRotation); | |
| 5774 | + glm::mat4 worldFromPortalEntranceTranslation = glm::translate(portalEntrancePropertiesPosition); | |
| 5775 | + glm::mat4 worldFromPortalEntrance = worldFromPortalEntranceTranslation * worldFromPortalEntranceRotation; | |
| 5776 | + glm::mat4 portalEntranceFromWorld = glm::inverse(worldFromPortalEntrance); | |
| 5777 | + | |
| 5778 | + glm::vec3 portalExitPropertiesPosition = portalExit->getWorldPosition(); | |
| 5779 | + glm::quat portalExitPropertiesRotation = portalExit->getWorldOrientation(); | |
| 5780 | + glm::vec3 portalExitPropertiesDimensions = portalExit->getScaledDimensions(); | |
| 5781 | + glm::vec3 halfPortalExitPropertiesDimensions = 0.5f * portalExitPropertiesDimensions; | |
| 5782 | + | |
| 5783 | + glm::mat4 worldFromPortalExitRotation = glm::mat4_cast(portalExitPropertiesRotation); | |
| 5784 | + glm::mat4 worldFromPortalExitTranslation = glm::translate(portalExitPropertiesPosition); | |
| 5785 | + glm::mat4 worldFromPortalExit = worldFromPortalExitTranslation * worldFromPortalExitRotation; | |
| 5786 | + | |
| 5787 | + glm::vec3 mainCameraPositionWorld = getCamera().getPosition(); | |
| 5788 | + glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f)); | |
| 5789 | + mainCameraPositionPortalEntrance = vec3(-mainCameraPositionPortalEntrance.x, mainCameraPositionPortalEntrance.y, | |
| 5790 | + -mainCameraPositionPortalEntrance.z); | |
| 5791 | + glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f)); | |
| 5792 | + | |
| 5793 | + secondaryViewFrustum.setPosition(portalExitCameraPositionWorld); | |
| 5794 | + secondaryViewFrustum.setOrientation(portalExitPropertiesRotation); | |
| 5795 | + | |
| 5796 | + float nearClip = mainCameraPositionPortalEntrance.z + portalExitPropertiesDimensions.z * 2.0f; | |
| 5797 | + // `mainCameraPositionPortalEntrance` should technically be `mainCameraPositionPortalExit`, | |
| 5798 | + // but the values are the same. | |
| 5799 | + glm::vec3 upperRight = halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; | |
| 5800 | + glm::vec3 bottomLeft = -halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; | |
| 5801 | + glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); | |
| 5802 | + secondaryViewFrustum.setProjection(frustum); | |
| 5803 | + } else if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { | |
| 5611 | 5804 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| 5612 | 5805 | auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); |
| 5613 | 5806 | glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition(); |
| @@ -5774,7 +5967,6 @@ void Application::update(float deltaTime) { · 160 unmodified lines | ||
| 5774 | 5967 | if (keyboardMousePlugin && keyboardMousePlugin->isActive()) { |
| 5775 | 5968 | keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData); |
| 5776 | 5969 | } |
| 5777 | − | |
| 5778 | 5970 | // Transfer the user inputs to the driveKeys |
| 5779 | 5971 | // FIXME can we drop drive keys and just have the avatar read the action states directly? |
| 5780 | 5972 | myAvatar->clearDriveKeys(); |
| @@ -6049,6 +6241,11 @@ void Application::update(float deltaTime) { · 268 unmodified lines | ||
| 6049 | 6241 | |
| 6050 | 6242 | updateLOD(deltaTime); |
| 6051 | 6243 | |
| 6244 | + if (!_loginDialogOverlayID.isNull()) { | |
| 6245 | + _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogOverlayID); | |
| 6246 | + updateLoginDialogOverlayPosition(); | |
| 6247 | + } | |
| 6248 | + | |
| 6052 | 6249 | // TODO: break these out into distinct perfTimers when they prove interesting |
| 6053 | 6250 | { |
| 6054 | 6251 | PROFILE_RANGE(app, "PickManager"); |
| @@ -6614,12 +6811,11 @@ void Application::goToErrorDomainURL(QUrl errorDomainURL) { · 559 unmodified lines | ||
| 6614 | 6811 | resetPhysicsReadyInformation(); |
| 6615 | 6812 | setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI); |
| 6616 | 6813 | if (isServerlessMode()) { |
| 6617 | − loadServerlessDomain(errorDomainURL, true); | |
| 6814 | + loadErrorDomain(errorDomainURL); | |
| 6618 | 6815 | } |
| 6619 | 6816 | updateWindowTitle(); |
| 6620 | 6817 | } |
| 6621 | 6818 | |
| 6622 | − | |
| 6623 | 6819 | void Application::resettingDomain() { |
| 6624 | 6820 | _notifiedPacketVersionMismatchThisDomain = false; |
| 6625 | 6821 | |
| @@ -7273,7 +7469,7 @@ void Application::showScriptLogs() { · 647 unmodified lines | ||
| 7273 | 7469 | } |
| 7274 | 7470 | |
| 7275 | 7471 | void Application::showAssetServerWidget(QString filePath) { |
| 7276 | − if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) { | |
| 7472 | + if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets() || getLoginDialogPoppedUp()) { | |
| 7277 | 7473 | return; |
| 7278 | 7474 | } |
| 7279 | 7475 | static const QUrl url { "hifi/AssetServer.qml" }; |
| @@ -7909,6 +8105,9 @@ void Application::loadDomainConnectionDialog() { · 629 unmodified lines | ||
| 7909 | 8105 | } |
| 7910 | 8106 | |
| 7911 | 8107 | void Application::toggleLogDialog() { |
| 8108 | + if (getLoginDialogPoppedUp()) { | |
| 8109 | + return; | |
| 8110 | + } | |
| 7912 | 8111 | if (! _logDialog) { |
| 7913 | 8112 | _logDialog = new LogDialog(nullptr, getLogger()); |
| 7914 | 8113 | } |
| @@ -8441,6 +8640,102 @@ void Application::setShowBulletConstraintLimits(bool value) { · 526 unmodified lines | ||
| 8441 | 8640 | _physicsEngine->setShowBulletConstraintLimits(value); |
| 8442 | 8641 | } |
| 8443 | 8642 | |
| 8643 | +void Application::createLoginDialogOverlay() { | |
| 8644 | + const glm::vec2 LOGIN_OVERLAY_DIMENSIONS{ 0.89f, 0.5f }; | |
| 8645 | + const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f); | |
| 8646 | + auto cameraPosition = _myCamera.getPosition(); | |
| 8647 | + auto cameraOrientation = _myCamera.getOrientation(); | |
| 8648 | + auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; | |
| 8649 | + auto headLookVec = (cameraOrientation * Vectors::FRONT); | |
| 8650 | + // DEFAULT_DPI / tablet scale percentage | |
| 8651 | + const float OVERLAY_DPI = 31.0f / (75.0f / 100.0f); | |
| 8652 | + auto offset = headLookVec * OVERLAY_OFFSET.x; | |
| 8653 | + auto overlayPosition = (cameraPosition + offset) + (upVec * OVERLAY_OFFSET.y); | |
| 8654 | + QVariantMap overlayProperties = { | |
| 8655 | + { "name", "LoginDialogOverlay" }, | |
| 8656 | + { "url", OVERLAY_LOGIN_DIALOG }, | |
| 8657 | + { "position", vec3toVariant(overlayPosition) }, | |
| 8658 | + { "orientation", quatToVariant(cameraOrientation) }, | |
| 8659 | + { "isSolid", true }, | |
| 8660 | + { "grabbable", false }, | |
| 8661 | + { "ignorePickIntersection", false }, | |
| 8662 | + { "alpha", 1.0 }, | |
| 8663 | + { "dimensions", vec2ToVariant(LOGIN_OVERLAY_DIMENSIONS)}, | |
| 8664 | + { "dpi", OVERLAY_DPI }, | |
| 8665 | + { "visible", true } | |
| 8666 | + }; | |
| 8667 | + auto& overlays = getOverlays(); | |
| 8668 | + _loginDialogOverlayID = overlays.addOverlay("web3d", overlayProperties); | |
| 8669 | + auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID)); | |
| 8670 | + auto keyboard = DependencyManager::get<Keyboard>().data(); | |
| 8671 | + if (!keyboard->getAnchorID().isNull() && !_loginDialogOverlayID.isNull()) { | |
| 8672 | + const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); | |
| 8673 | + auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); | |
| 8674 | + QVariantMap properties { | |
| 8675 | + { "position", vec3toVariant(overlayPosition + keyboardLocalOffset) }, | |
| 8676 | + { "orientation", quatToVariant(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION) }, | |
| 8677 | + }; | |
| 8678 | + overlays.editOverlay(keyboard->getAnchorID(), properties); | |
| 8679 | + keyboard->setResetKeyboardPositionOnRaise(false); | |
| 8680 | + } | |
| 8681 | + setKeyboardFocusOverlay(_loginDialogOverlayID); | |
| 8682 | + emit loginDialogFocusEnabled(); | |
| 8683 | + getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); | |
| 8684 | + getApplicationCompositor().getReticleInterface()->setVisible(false); | |
| 8685 | + if (!_loginStateManager.isSetUp()) { | |
| 8686 | + _loginStateManager.setUp(); | |
| 8687 | + } | |
| 8688 | +} | |
| 8689 | + | |
| 8690 | +void Application::updateLoginDialogOverlayPosition() { | |
| 8691 | + const float LOOK_AWAY_THRESHOLD_ANGLE = 70.0f; | |
| 8692 | + const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f); | |
| 8693 | + auto& overlays = getOverlays(); | |
| 8694 | + auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID)); | |
| 8695 | + auto overlayPositionVec = loginOverlay->getWorldPosition(); | |
| 8696 | + auto cameraPositionVec = _myCamera.getPosition(); | |
| 8697 | + auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation()); | |
| 8698 | + auto headLookVec = (cameraOrientation * Vectors::FRONT); | |
| 8699 | + auto overlayToHeadVec = overlayPositionVec - cameraPositionVec; | |
| 8700 | + auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI); | |
| 8701 | + auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; | |
| 8702 | + auto offset = headLookVec * OVERLAY_OFFSET.x; | |
| 8703 | + auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * OVERLAY_OFFSET.y); | |
| 8704 | + auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; | |
| 8705 | + | |
| 8706 | + bool overlayOutOfBounds = glm::distance(overlayPositionVec, cameraPositionVec) > 1.0f; | |
| 8707 | + | |
| 8708 | + if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || overlayOutOfBounds) { | |
| 8709 | + QVariantMap properties { | |
| 8710 | + {"position", vec3toVariant(newOverlayPositionVec)}, | |
| 8711 | + {"orientation", quatToVariant(newOverlayOrientation)} | |
| 8712 | + }; | |
| 8713 | + overlays.editOverlay(_loginDialogOverlayID, properties); | |
| 8714 | + const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); | |
| 8715 | + auto keyboardLocalOffset = newOverlayOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); | |
| 8716 | + QVariantMap keyboardProperties { | |
| 8717 | + { "position", vec3toVariant(newOverlayPositionVec + keyboardLocalOffset) }, | |
| 8718 | + { "orientation", quatToVariant(newOverlayOrientation * KEYBOARD_LOCAL_ORIENTATION) }, | |
| 8719 | + }; | |
| 8720 | + auto keyboard = DependencyManager::get<Keyboard>().data(); | |
| 8721 | + overlays.editOverlay(keyboard->getAnchorID(), keyboardProperties); | |
| 8722 | + } | |
| 8723 | +} | |
| 8724 | + | |
| 8725 | +void Application::onDismissedLoginDialog() { | |
| 8726 | + _loginDialogPoppedUp = false; | |
| 8727 | + loginDialogPoppedUp.set(false); | |
| 8728 | + auto keyboard = DependencyManager::get<Keyboard>().data(); | |
| 8729 | + keyboard->setResetKeyboardPositionOnRaise(true); | |
| 8730 | + if (!_loginDialogOverlayID.isNull()) { | |
| 8731 | + // deleting overlay. | |
| 8732 | + getOverlays().deleteOverlay(_loginDialogOverlayID); | |
| 8733 | + _loginDialogOverlayID = OverlayID(); | |
| 8734 | + _loginStateManager.tearDown(); | |
| 8735 | + } | |
| 8736 | + resumeAfterLoginDialogActionTaken(); | |
| 8737 | +} | |
| 8738 | + | |
| 8444 | 8739 | void Application::setShowTrackedObjects(bool value) { |
| 8445 | 8740 | _showTrackedObjects = value; |
| 8446 | 8741 | } |
| @@ -8591,7 +8886,7 @@ void Application::updateThreadPoolCount() const { · 144 unmodified lines | ||
| 8591 | 8886 | } |
| 8592 | 8887 | |
| 8593 | 8888 | void Application::updateSystemTabletMode() { |
| 8594 | − if (_settingsLoaded) { | |
| 8889 | + if (_settingsLoaded && !getLoginDialogPoppedUp()) { | |
| 8595 | 8890 | qApp->setProperty(hifi::properties::HMD, isHMDMode()); |
| 8596 | 8891 | if (isHMDMode()) { |
| 8597 | 8892 | DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getHmdTabletBecomesToolbarSetting()); |
| @@ -8617,7 +8912,7 @@ QUuid Application::getTabletFrameID() const { · 19 unmodified lines | ||
| 8617 | 8912 | } |
| 8618 | 8913 | |
| 8619 | 8914 | QVector<QUuid> Application::getTabletIDs() const { |
| 8620 | − // Most important overlays first. | |
| 8915 | + // Most important overlays first. | |
| 8621 | 8916 | QVector<QUuid> result; |
| 8622 | 8917 | auto HMD = DependencyManager::get<HMDScriptingInterface>(); |
| 8623 | 8918 | result << HMD->getCurrentTabletScreenID(); |