History

Merge branch 'master' of https://github.com/highfidelity/hifi into project-freeloco

r3tk0n committed 7 years ago

Commit ebbf48a2 parents 0305877 051ab611002 files · +32726 −23541Browse files

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

Unified · Split

interface/src/Application.cpp+526−355
@@ -102,7 +102,7 @@ · 101 unmodified lines
102#include <MessagesClient.h>102#include <MessagesClient.h>
103#include <hfm/ModelFormatRegistry.h>103#include <hfm/ModelFormatRegistry.h>
104#include <model-networking/ModelCacheScriptingInterface.h>104#include <model-networking/ModelCacheScriptingInterface.h>
105#include <model-networking/TextureCacheScriptingInterface.h>105#include <material-networking/TextureCacheScriptingInterface.h>
106#include <ModelEntityItem.h>106#include <ModelEntityItem.h>
107#include <NetworkAccessManager.h>107#include <NetworkAccessManager.h>
108#include <NetworkingConstants.h>108#include <NetworkingConstants.h>
@@ -120,6 +120,7 @@ · 11 unmodified lines
120#include <plugins/PluginManager.h>120#include <plugins/PluginManager.h>
121#include <plugins/PluginUtils.h>121#include <plugins/PluginUtils.h>
122#include <plugins/SteamClientPlugin.h>122#include <plugins/SteamClientPlugin.h>
123#include <plugins/OculusPlatformPlugin.h>
123#include <plugins/InputConfiguration.h>124#include <plugins/InputConfiguration.h>
124#include <RecordingScriptingInterface.h>125#include <RecordingScriptingInterface.h>
125#include <render/EngineStats.h>126#include <render/EngineStats.h>
@@ -151,7 +152,9 @@ · 25 unmodified lines
151#include <trackers/EyeTracker.h>152#include <trackers/EyeTracker.h>
152#include <avatars-renderer/ScriptAvatar.h>153#include <avatars-renderer/ScriptAvatar.h>
153#include <RenderableEntityItem.h>154#include <RenderableEntityItem.h>
154#include <model-networking/MaterialCache.h>155#include <RenderableTextEntityItem.h>
156#include <RenderableWebEntityItem.h>
157#include <material-networking/MaterialCache.h>
155#include "recording/ClipCache.h"158#include "recording/ClipCache.h"
156 159
157#include "AudioClient.h"160#include "AudioClient.h"
@@ -159,6 +162,7 @@ · 1 unmodified line
159#include "avatar/AvatarManager.h"162#include "avatar/AvatarManager.h"
160#include "avatar/MyHead.h"163#include "avatar/MyHead.h"
161#include "avatar/AvatarPackager.h"164#include "avatar/AvatarPackager.h"
165#include "avatar/MyCharacterController.h"
162#include "CrashRecoveryHandler.h"166#include "CrashRecoveryHandler.h"
163#include "CrashHandler.h"167#include "CrashHandler.h"
164#include "devices/DdeFaceTracker.h"168#include "devices/DdeFaceTracker.h"
@@ -195,15 +199,12 @@ · 30 unmodified lines
195#include "ui/AvatarInputs.h"199#include "ui/AvatarInputs.h"
196#include "ui/DialogsManager.h"200#include "ui/DialogsManager.h"
197#include "ui/LoginDialog.h"201#include "ui/LoginDialog.h"
198#include "ui/overlays/Cube3DOverlay.h"
199#include "ui/overlays/Web3DOverlay.h"
200#include "ui/Snapshot.h"202#include "ui/Snapshot.h"
201#include "ui/SnapshotAnimated.h"203#include "ui/SnapshotAnimated.h"
202#include "ui/StandAloneJSConsole.h"204#include "ui/StandAloneJSConsole.h"
203#include "ui/Stats.h"205#include "ui/Stats.h"
204#include "ui/AnimStats.h"206#include "ui/AnimStats.h"
205#include "ui/UpdateDialog.h"207#include "ui/UpdateDialog.h"
206#include "ui/overlays/Overlays.h"
207#include "ui/DomainConnectionModel.h"208#include "ui/DomainConnectionModel.h"
208#include "ui/Keyboard.h"209#include "ui/Keyboard.h"
209#include "Util.h"210#include "Util.h"
@@ -232,6 +233,7 @@ · 22 unmodified lines
232#include "commerce/Ledger.h"233#include "commerce/Ledger.h"
233#include "commerce/Wallet.h"234#include "commerce/Wallet.h"
234#include "commerce/QmlCommerce.h"235#include "commerce/QmlCommerce.h"
236#include "commerce/QmlMarketplace.h"
235#include "ResourceRequestObserver.h"237#include "ResourceRequestObserver.h"
236 238
237#include "webbrowser/WebBrowserSuggestionsEngine.h"239#include "webbrowser/WebBrowserSuggestionsEngine.h"
@@ -347,6 +349,8 @@ static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin"; · 109 unmodified lines
347static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";349static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
348static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn";350static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn";
349 351
352static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
353
350#if defined(Q_OS_ANDROID)354#if defined(Q_OS_ANDROID)
351static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt";355static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt";
352#endif356#endif
@@ -599,8 +603,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt · 246 unmodified lines
599 __android_log_write(ANDROID_LOG_FATAL,"Interface",local);603 __android_log_write(ANDROID_LOG_FATAL,"Interface",local);
600 abort();604 abort();
601 }605 }
602#endif606#else
603 qApp->getLogger()->addMessage(qPrintable(logMessage));607 qApp->getLogger()->addMessage(qPrintable(logMessage));
608#endif
604 }609 }
605}610}
606 611
@@ -618,7 +623,7 @@ public: · 11 unmodified lines
618 case NestableType::Entity:623 case NestableType::Entity:
619 return getEntityModelProvider(static_cast<EntityItemID>(uuid));624 return getEntityModelProvider(static_cast<EntityItemID>(uuid));
620 case NestableType::Overlay:625 case NestableType::Overlay:
621 return getOverlayModelProvider(static_cast<OverlayID>(uuid));626 return nullptr;
622 case NestableType::Avatar:627 case NestableType::Avatar:
623 return getAvatarModelProvider(uuid);628 return getAvatarModelProvider(uuid);
624 }629 }
@@ -642,22 +647,6 @@ private: · 17 unmodified lines
642 return provider;647 return provider;
643 }648 }
644 649
645 scriptable::ModelProviderPointer getOverlayModelProvider(OverlayID overlayID) {
646 scriptable::ModelProviderPointer provider;
647 auto &overlays = qApp->getOverlays();
648 if (auto overlay = overlays.getOverlay(overlayID)) {
649 if (auto base3d = std::dynamic_pointer_cast<Base3DOverlay>(overlay)) {
650 provider = std::dynamic_pointer_cast<scriptable::ModelProvider>(base3d);
651 provider->modelProviderType = NestableType::Overlay;
652 } else {
653 qCWarning(interfaceapp) << "no renderer for overlay ID" << overlayID.toString();
654 }
655 } else {
656 qCWarning(interfaceapp) << "overlay not found" << overlayID.toString();
657 }
658 return provider;
659 }
660
661 scriptable::ModelProviderPointer getAvatarModelProvider(QUuid sessionUUID) {650 scriptable::ModelProviderPointer getAvatarModelProvider(QUuid sessionUUID) {
662 scriptable::ModelProviderPointer provider;651 scriptable::ModelProviderPointer provider;
663 auto avatarManager = DependencyManager::get<AvatarManager>();652 auto avatarManager = DependencyManager::get<AvatarManager>();
@@ -762,6 +751,11 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 98 unmodified lines
762 static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";751 static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
763 bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);752 bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
764 753
754 // set the OCULUS_STORE property so the oculus plugin can know if we ran from the Oculus Store
755 static const auto OCULUS_STORE_ARG = "--oculus-store";
756 bool isStore = cmdOptionExists(argc, const_cast<const char**>(argv), OCULUS_STORE_ARG);
757 qApp->setProperty(hifi::properties::OCULUS_STORE, isStore);
758
765 // Ignore any previous crashes if running from command line with a test script.759 // Ignore any previous crashes if running from command line with a test script.
766 bool inTestMode { false };760 bool inTestMode { false };
767 for (int i = 0; i < argc; ++i) {761 for (int i = 0; i < argc; ++i) {
@@ -803,6 +797,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 35 unmodified lines
803 if (auto steamClient = pluginManager->getSteamClientPlugin()) {797 if (auto steamClient = pluginManager->getSteamClientPlugin()) {
804 steamClient->init();798 steamClient->init();
805 }799 }
800 if (auto oculusPlatform = pluginManager->getOculusPlatformPlugin()) {
801 oculusPlatform->init();
802 }
806 803
807 PROFILE_SET_THREAD_NAME("Main Thread");804 PROFILE_SET_THREAD_NAME("Main Thread");
808 805
@@ -923,6 +920,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 114 unmodified lines
923 DependencyManager::set<Wallet>();920 DependencyManager::set<Wallet>();
924 DependencyManager::set<WalletScriptingInterface>();921 DependencyManager::set<WalletScriptingInterface>();
925 DependencyManager::set<TTSScriptingInterface>();922 DependencyManager::set<TTSScriptingInterface>();
923 DependencyManager::set<QmlCommerce>();
926 924
927 DependencyManager::set<FadeEffect>();925 DependencyManager::set<FadeEffect>();
928 DependencyManager::set<ResourceRequestObserver>();926 DependencyManager::set<ResourceRequestObserver>();
@@ -937,9 +935,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 8 unmodified lines
937// FIXME move to header, or better yet, design some kind of UI manager935// FIXME move to header, or better yet, design some kind of UI manager
938// to take care of highlighting keyboard focused items, rather than936// to take care of highlighting keyboard focused items, rather than
939// continuing to overburden Application.cpp937// continuing to overburden Application.cpp
940std::shared_ptr<Cube3DOverlay> _keyboardFocusHighlight{ nullptr };938QUuid _keyboardFocusHighlightID;
941OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID };
942
943 939
944OffscreenGLCanvas* _qmlShareContext { nullptr };940OffscreenGLCanvas* _qmlShareContext { nullptr };
945 941
@@ -980,7 +976,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 34 unmodified lines
980 QApplication(argc, argv),976 QApplication(argc, argv),
981 _window(new MainWindow(desktop())),977 _window(new MainWindow(desktop())),
982 _sessionRunTimer(startupTimer),978 _sessionRunTimer(startupTimer),
979#ifndef Q_OS_ANDROID
983 _logger(new FileLogger(this)),980 _logger(new FileLogger(this)),
981#endif
984 _previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)),982 _previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)),
985 _entitySimulation(new PhysicalEntitySimulation()),983 _entitySimulation(new PhysicalEntitySimulation()),
986 _physicsEngine(new PhysicsEngine(Vectors::ZERO)),984 _physicsEngine(new PhysicsEngine(Vectors::ZERO)),
@@ -1114,7 +1112,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 127 unmodified lines
1114 }1112 }
1115 auto accountManager = DependencyManager::get<AccountManager>();1113 auto accountManager = DependencyManager::get<AccountManager>();
1116 1114
1115#ifndef Q_OS_ANDROID
1117 _logger->setSessionID(accountManager->getSessionID());1116 _logger->setSessionID(accountManager->getSessionID());
1117#endif
1118 1118
1119 setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());1119 setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());
1120 setCrashAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId()));1120 setCrashAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId()));
@@ -1135,10 +1135,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 14 unmodified lines
1135 qCDebug(interfaceapp) << "[VERSION] We will use DEVELOPMENT global services.";1135 qCDebug(interfaceapp) << "[VERSION] We will use DEVELOPMENT global services.";
1136#endif1136#endif
1137 1137
1138 // set the OCULUS_STORE property so the oculus plugin can know if we ran from the Oculus Store1138 bool isStore = property(hifi::properties::OCULUS_STORE).toBool();
1139 static const QString OCULUS_STORE_ARG = "--oculus-store";1139
1140 bool isStore = arguments().indexOf(OCULUS_STORE_ARG) != -1;
1141 setProperty(hifi::properties::OCULUS_STORE, isStore);
1142 DependencyManager::get<WalletScriptingInterface>()->setLimitedCommerce(isStore); // Or we could make it a separate arg, or if either arg is set, etc. And should this instead by a hifi::properties?1140 DependencyManager::get<WalletScriptingInterface>()->setLimitedCommerce(isStore); // Or we could make it a separate arg, or if either arg is set, etc. And should this instead by a hifi::properties?
1143 1141
1144 updateHeartbeat();1142 updateHeartbeat();
@@ -1204,9 +1202,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 59 unmodified lines
1204 connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));1202 connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
1205 connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));1203 connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
1206 connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() {1204 connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() {
1207 getOverlays().deleteOverlay(getTabletScreenID());1205 auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
1208 getOverlays().deleteOverlay(getTabletHomeButtonID());1206 if (tabletScriptingInterface) {
1209 getOverlays().deleteOverlay(getTabletFrameID());1207 tabletScriptingInterface->setQmlTabletRoot(SYSTEM_TABLET, nullptr);
1208 }
1209 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
1210 entityScriptingInterface->deleteEntity(getTabletScreenID());
1211 entityScriptingInterface->deleteEntity(getTabletHomeButtonID());
1212 entityScriptingInterface->deleteEntity(getTabletFrameID());
1210 _failedToConnectToEntityServer = false;1213 _failedToConnectToEntityServer = false;
1211 });1214 });
1212 1215
@@ -1296,10 +1299,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 83 unmodified lines
1296 if (isHMDMode()) {1299 if (isHMDMode()) {
1297 emit loginDialogFocusDisabled();1300 emit loginDialogFocusDisabled();
1298 dialogsManager->hideLoginDialog();1301 dialogsManager->hideLoginDialog();
1299 createLoginDialogOverlay();1302 createLoginDialog();
1300 } else {1303 } else {
1301 getOverlays().deleteOverlay(_loginDialogOverlayID);1304 DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_loginDialogID);
1302 _loginDialogOverlayID = OverlayID();1305 _loginDialogID = QUuid();
1303 _loginStateManager.tearDown();1306 _loginStateManager.tearDown();
1304 dialogsManager->showLoginDialog();1307 dialogsManager->showLoginDialog();
1305 emit loginDialogFocusEnabled();1308 emit loginDialogFocusEnabled();
@@ -1896,66 +1899,56 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 590 unmodified lines
1896 SpacemouseManager::getInstance().init();1899 SpacemouseManager::getInstance().init();
1897#endif1900#endif
1898 1901
1899 // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it1902 // If the user clicks on an object, we will check that it's a web surface, and if so, set the focus to it
1900 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();1903 auto pointerManager = DependencyManager::get<PointerManager>();
1901 connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity,1904 auto keyboardFocusOperator = [this](const QUuid& id, const PointerEvent& event) {
1902 [this](const EntityItemID& entityItemID, const PointerEvent& event) {
1903 if (event.shouldFocus()) {1905 if (event.shouldFocus()) {
1904 if (getEntities()->wantsKeyboardFocus(entityItemID)) {1906 auto keyboard = DependencyManager::get<Keyboard>();
1905 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);1907 if (getEntities()->wantsKeyboardFocus(id)) {
1906 setKeyboardFocusEntity(entityItemID);1908 setKeyboardFocusEntity(id);
1907 } else {1909 } else if (!keyboard->containsID(id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus
1908 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);1910 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
1909 }1911 }
1910 }1912 }
1911 });1913 };
1914 connect(pointerManager.data(), &PointerManager::triggerBeginEntity, keyboardFocusOperator);
1915 connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, keyboardFocusOperator);
1912 1916
1913 connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) {1917 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
1918 connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityItemID) {
1914 if (entityItemID == _keyboardFocusedEntity.get()) {1919 if (entityItemID == _keyboardFocusedEntity.get()) {
1915 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);1920 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
1916 }1921 }
1917 });1922 }, Qt::QueuedConnection);
1918 1923
1919 EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {1924 EntityTreeRenderer::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
1920 if (_aboutToQuit) {1925 if (_aboutToQuit) {
1921 return false;1926 return false;
1922 }1927 }
1923 1928
1924 // try to find the renderable
1925 auto renderable = getEntities()->renderableForEntityId(entityID);1929 auto renderable = getEntities()->renderableForEntityId(entityID);
1926 if (renderable) {1930 if (renderable) {
1927 renderable->addMaterial(material, parentMaterialName);1931 renderable->addMaterial(material, parentMaterialName);
1928 }
1929
1930 // even if we don't find it, try to find the entity
1931 auto entity = getEntities()->getEntity(entityID);
1932 if (entity) {
1933 entity->addMaterial(material, parentMaterialName);
1934 return true;1932 return true;
1935 }1933 }
1934
1936 return false;1935 return false;
1937 });1936 });
1938 EntityTree::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {1937 EntityTreeRenderer::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
1939 if (_aboutToQuit) {1938 if (_aboutToQuit) {
1940 return false;1939 return false;
1941 }1940 }
1942 1941
1943 // try to find the renderable
1944 auto renderable = getEntities()->renderableForEntityId(entityID);1942 auto renderable = getEntities()->renderableForEntityId(entityID);
1945 if (renderable) {1943 if (renderable) {
1946 renderable->removeMaterial(material, parentMaterialName);1944 renderable->removeMaterial(material, parentMaterialName);
1947 }
1948
1949 // even if we don't find it, try to find the entity
1950 auto entity = getEntities()->getEntity(entityID);
1951 if (entity) {
1952 entity->removeMaterial(material, parentMaterialName);
1953 return true;1945 return true;
1954 }1946 }
1947
1955 return false;1948 return false;
1956 });1949 });
1957 1950
1958 EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) {1951 EntityTreeRenderer::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
1959 auto avatarManager = DependencyManager::get<AvatarManager>();1952 auto avatarManager = DependencyManager::get<AvatarManager>();
1960 auto avatar = avatarManager->getAvatarBySessionID(avatarID);1953 auto avatar = avatarManager->getAvatarBySessionID(avatarID);
1961 if (avatar) {1954 if (avatar) {
@@ -1964,7 +1957,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 2 unmodified lines
1964 }1957 }
1965 return false;1958 return false;
1966 });1959 });
1967 EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) {1960 EntityTreeRenderer::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
1968 auto avatarManager = DependencyManager::get<AvatarManager>();1961 auto avatarManager = DependencyManager::get<AvatarManager>();
1969 auto avatar = avatarManager->getAvatarBySessionID(avatarID);1962 auto avatar = avatarManager->getAvatarBySessionID(avatarID);
1970 if (avatar) {1963 if (avatar) {
@@ -1974,33 +1967,25 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 3 unmodified lines
1974 return false;1967 return false;
1975 });1968 });
1976 1969
1977 EntityTree::setAddMaterialToOverlayOperator([this](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) {1970 EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* {
1978 auto overlay = _overlays.getOverlay(overlayID);1971 auto entities = getEntities();
1979 if (overlay) {1972 if (auto entity = entities->renderableForEntityId(id)) {
1980 overlay->addMaterial(material, parentMaterialName);1973 return qobject_cast<QObject*>(entity.get());
1981 return true;
1982 }
1983 return false;
1984 });
1985 EntityTree::setRemoveMaterialFromOverlayOperator([this](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
1986 auto overlay = _overlays.getOverlay(overlayID);
1987 if (overlay) {
1988 overlay->removeMaterial(material, parentMaterialName);
1989 return true;
1990 }1974 }
1991 return false;1975 return nullptr;
1992 });1976 });
1993 1977
1994 // Keyboard focus handling for Web overlays.1978 EntityTree::setTextSizeOperator([this](const QUuid& id, const QString& text) {
1995 auto overlays = &(qApp->getOverlays());1979 auto entities = getEntities();
1996 connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) {1980 if (auto entity = entities->renderableForEntityId(id)) {
1997 if (overlayID == _keyboardFocusedOverlay.get()) {1981 if (auto renderable = std::dynamic_pointer_cast<render::entities::TextEntityRenderer>(entity)) {
1998 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);1982 return renderable->textSize(text);
1983 }
1999 }1984 }
1985 return QSizeF(0.0f, 0.0f);
2000 });1986 });
2001 1987
2002 connect(this, &Application::aboutToQuit, [this]() {1988 connect(this, &Application::aboutToQuit, [this]() {
2003 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
2004 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);1989 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
2005 });1990 });
2006 1991
@@ -2211,7 +2196,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 204 unmodified lines
2211 || ((rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose));2196 || ((rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose));
2212 lastLeftHandPose = leftHandPose;2197 lastLeftHandPose = leftHandPose;
2213 lastRightHandPose = rightHandPose;2198 lastRightHandPose = rightHandPose;
2214 properties["avatar_identity_requests_sent"] = DependencyManager::get<AvatarManager>()->getIdentityRequestsSent();
2215 2199
2216 UserActivityLogger::getInstance().logAction("stats", properties);2200 UserActivityLogger::getInstance().logAction("stats", properties);
2217 });2201 });
@@ -2296,7 +2280,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 78 unmodified lines
2296 2280
2297 // Setup the mouse ray pick and related operators2281 // Setup the mouse ray pick and related operators
2298 {2282 {
2299 auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES()), 0.0f, true);2283 auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_LOCAL_ENTITIES()), 0.0f, true);
2300 mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();2284 mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();
2301 mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);2285 mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);
2302 auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);2286 auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);
@@ -2322,11 +2306,104 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 19 unmodified lines
2322 DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);2306 DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
2323 });2307 });
2324 2308
2325 EntityTreeRenderer::setGetAvatarUpOperator([] {2309 EntityItem::setBillboardRotationOperator([this](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode) {
2326 return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;2310 if (billboardMode == BillboardMode::YAW) {
2311 //rotate about vertical to face the camera
2312 ViewFrustum frustum;
2313 copyViewFrustum(frustum);
2314 glm::vec3 dPosition = frustum.getPosition() - position;
2315 // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
2316 float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
2317 return glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
2318 } else if (billboardMode == BillboardMode::FULL) {
2319 ViewFrustum frustum;
2320 copyViewFrustum(frustum);
2321 glm::vec3 cameraPos = frustum.getPosition();
2322 // use the referencial from the avatar, y isn't always up
2323 glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
2324 // check to see if glm::lookAt will work / using glm::lookAt variable name
2325 glm::highp_vec3 s(glm::cross(position - cameraPos, avatarUP));
2326
2327 // make sure s is not NaN for any component
2328 if (glm::length2(s) > 0.0f) {
2329 return glm::conjugate(glm::toQuat(glm::lookAt(cameraPos, position, avatarUP)));
2330 }
2331 }
2332 return rotation;
2333 });
2334
2335 render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
2336 bool isTablet = url == TabletScriptingInterface::QML;
2337 if (htmlContent) {
2338 webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML);
2339 cachedWebSurface = true;
2340 auto rootItemLoadedFunctor = [url, webSurface] {
2341 webSurface->getRootItem()->setProperty(render::entities::WebEntityRenderer::URL_PROPERTY, url);
2342 };
2343 if (webSurface->getRootItem()) {
2344 rootItemLoadedFunctor();
2345 } else {
2346 QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
2347 }
2348 } else {
2349 // FIXME: the tablet should use the OffscreenQmlSurfaceCache
2350 webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), [](OffscreenQmlSurface* webSurface) {
2351 AbstractViewStateInterface::instance()->sendLambdaEvent([webSurface] {
2352 // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown
2353 // if the application has already stopped its event loop, delete must be explicit
2354 delete webSurface;
2355 });
2356 });
2357 auto rootItemLoadedFunctor = [webSurface, url, isTablet] {
2358 Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == LOGIN_DIALOG.toString());
2359 };
2360 if (webSurface->getRootItem()) {
2361 rootItemLoadedFunctor();
2362 } else {
2363 QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
2364 }
2365 webSurface->load(url);
2366 cachedWebSurface = false;
2367 }
2368 const uint8_t DEFAULT_MAX_FPS = 10;
2369 const uint8_t TABLET_FPS = 90;
2370 webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS);
2371 });
2372 render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([this](QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface, std::vector<QMetaObject::Connection>& connections) {
2373 QQuickItem* rootItem = webSurface->getRootItem();
2374
2375 // Fix for crash in QtWebEngineCore when rapidly switching domains
2376 // Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
2377 if (rootItem && !cachedWebSurface) {
2378 // stop loading
2379 QMetaObject::invokeMethod(rootItem, "stop");
2380 }
2381
2382 webSurface->pause();
2383
2384 for (auto& connection : connections) {
2385 QObject::disconnect(connection);
2386 }
2387 connections.clear();
2388
2389 // If the web surface was fetched out of the cache, release it back into the cache
2390 if (cachedWebSurface) {
2391 // If it's going back into the cache make sure to explicitly set the URL to a blank page
2392 // in order to stop any resource consumption or audio related to the page.
2393 if (rootItem) {
2394 rootItem->setProperty("url", "about:blank");
2395 }
2396 auto offscreenCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
2397 if (offscreenCache) {
2398 offscreenCache->release(render::entities::WebEntityRenderer::QML, webSurface);
2399 }
2400 cachedWebSurface = false;
2401 }
2402 webSurface.reset();
2327 });2403 });
2328 2404
2329 // Preload Tablet sounds2405 // Preload Tablet sounds
2406 DependencyManager::get<EntityScriptingInterface>()->setEntityTree(qApp->getEntities()->getTree());
2330 DependencyManager::get<TabletScriptingInterface>()->preloadSounds();2407 DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
2331 DependencyManager::get<Keyboard>()->createKeyboard();2408 DependencyManager::get<Keyboard>()->createKeyboard();
2332 2409
@@ -2352,7 +2429,6 @@ void Application::updateVerboseLogging() { · 19 unmodified lines
2352 bool enable = menu->isOptionChecked(MenuOption::VerboseLogging);2429 bool enable = menu->isOptionChecked(MenuOption::VerboseLogging);
2353 2430
2354 QString rules =2431 QString rules =
2355 "hifi.*.debug=%1\n"
2356 "hifi.*.info=%1\n"2432 "hifi.*.info=%1\n"
2357 "hifi.audio-stream.debug=false\n"2433 "hifi.audio-stream.debug=false\n"
2358 "hifi.audio-stream.info=false";2434 "hifi.audio-stream.info=false";
@@ -2535,11 +2611,10 @@ void Application::cleanupBeforeQuit() { · 176 unmodified lines
2535 _applicationStateDevice.reset();2611 _applicationStateDevice.reset();
2536 2612
2537 {2613 {
2538 if (_keyboardFocusHighlightID != UNKNOWN_OVERLAY_ID) {2614 if (_keyboardFocusHighlightID != UNKNOWN_ENTITY_ID) {
2539 getOverlays().deleteOverlay(_keyboardFocusHighlightID);2615 DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_keyboardFocusHighlightID);
2540 _keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID;2616 _keyboardFocusHighlightID = UNKNOWN_ENTITY_ID;
2541 }2617 }
2542 _keyboardFocusHighlight = nullptr;
2543 }2618 }
2544 2619
2545 {2620 {
@@ -2609,6 +2684,7 @@ void Application::cleanupBeforeQuit() { · 63 unmodified lines
2609 DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface2684 DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface
2610 2685
2611 // stop QML2686 // stop QML
2687 DependencyManager::destroy<QmlCommerce>();
2612 DependencyManager::destroy<TabletScriptingInterface>();2688 DependencyManager::destroy<TabletScriptingInterface>();
2613 DependencyManager::destroy<ToolbarScriptingInterface>();2689 DependencyManager::destroy<ToolbarScriptingInterface>();
2614 DependencyManager::destroy<OffscreenUi>();2690 DependencyManager::destroy<OffscreenUi>();
@@ -2648,7 +2724,14 @@ Application::~Application() { · 33 unmodified lines
2648 avatarManager->handleProcessedPhysicsTransaction(transaction);2724 avatarManager->handleProcessedPhysicsTransaction(transaction);
2649 2725
2650 avatarManager->deleteAllAvatars();2726 avatarManager->deleteAllAvatars();
2651 2727
2728 auto myCharacterController = getMyAvatar()->getCharacterController();
2729 myCharacterController->clearDetailedMotionStates();
2730
2731 myCharacterController->buildPhysicsTransaction(transaction);
2732 _physicsEngine->processTransaction(transaction);
2733 myCharacterController->handleProcessedPhysicsTransaction(transaction);
2734
2652 _physicsEngine->setCharacterController(nullptr);2735 _physicsEngine->setCharacterController(nullptr);
2653 2736
2654 // the _shapeManager should have zero references2737 // the _shapeManager should have zero references
@@ -2671,6 +2754,11 @@ Application::~Application() { · 16 unmodified lines
2671 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {2754 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
2672 steamClient->shutdown();2755 steamClient->shutdown();
2673 }2756 }
2757
2758 if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) {
2759 oculusPlatform->shutdown();
2760 }
2761
2674 DependencyManager::destroy<PluginManager>();2762 DependencyManager::destroy<PluginManager>();
2675 2763
2676 DependencyManager::destroy<CompositorHelper>(); // must be destroyed before the FramebufferCache2764 DependencyManager::destroy<CompositorHelper>(); // must be destroyed before the FramebufferCache
@@ -2897,7 +2985,7 @@ void Application::initializeUi() { · 220 unmodified lines
2897 Tooltip::registerType();2985 Tooltip::registerType();
2898 UpdateDialog::registerType();2986 UpdateDialog::registerType();
2899 QmlContextCallback commerceCallback = [](QQmlContext* context) {2987 QmlContextCallback commerceCallback = [](QQmlContext* context) {
2900 context->setContextProperty("Commerce", new QmlCommerce());2988 context->setContextProperty("Commerce", DependencyManager::get<QmlCommerce>().data());
2901 };2989 };
2902 OffscreenQmlSurface::addWhitelistContextHandler({2990 OffscreenQmlSurface::addWhitelistContextHandler({
2903 QUrl{ "hifi/commerce/checkout/Checkout.qml" },2991 QUrl{ "hifi/commerce/checkout/Checkout.qml" },
@@ -2922,7 +3010,24 @@ void Application::initializeUi() { · 18 unmodified lines
2922 QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" },3010 QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" },
2923 QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },3011 QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },
2924 QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },3012 QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },
3013 QUrl{ "hifi/tablet/TabletMenu.qml" },
3014 QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },
2925 }, commerceCallback);3015 }, commerceCallback);
3016
3017 QmlContextCallback marketplaceCallback = [](QQmlContext* context) {
3018 context->setContextProperty("MarketplaceScriptingInterface", new QmlMarketplace());
3019 };
3020 OffscreenQmlSurface::addWhitelistContextHandler({
3021 QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },
3022 }, marketplaceCallback);
3023
3024 QmlContextCallback platformInfoCallback = [](QQmlContext* context) {
3025 context->setContextProperty("PlatformInfo", new PlatformInfoScriptingInterface());
3026 };
3027 OffscreenQmlSurface::addWhitelistContextHandler({
3028 QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },
3029 }, platformInfoCallback);
3030
2926 QmlContextCallback ttsCallback = [](QQmlContext* context) {3031 QmlContextCallback ttsCallback = [](QQmlContext* context) {
2927 context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());3032 context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
2928 };3033 };
@@ -3013,7 +3118,7 @@ void Application::initializeUi() { · 84 unmodified lines
3013 });3118 });
3014 3119
3015#if !defined(DISABLE_QML)3120#if !defined(DISABLE_QML)
3016 // Pre-create a couple of Web3D overlays to speed up tablet UI3121 // Pre-create a couple of offscreen surfaces to speed up tablet UI
3017 auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();3122 auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
3018 offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) {3123 offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) {
3019 if (rootObject == TabletScriptingInterface::QML) {3124 if (rootObject == TabletScriptingInterface::QML) {
@@ -3025,7 +3130,7 @@ void Application::initializeUi() { · 5 unmodified lines
3025 });3130 });
3026 3131
3027 offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);3132 offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
3028 offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);3133 offscreenSurfaceCache->reserve(render::entities::WebEntityRenderer::QML, 2);
3029#endif3134#endif
3030 3135
3031 flushMenuUpdates();3136 flushMenuUpdates();
@@ -3165,6 +3270,61 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { · 133 unmodified lines
3165#endif3270#endif
3166}3271}
3167 3272
3273void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditionalContextProperties) {
3274 surfaceContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
3275 surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
3276 surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
3277 surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
3278 surfaceContext->setContextProperty("Vec3", new Vec3());
3279 surfaceContext->setContextProperty("Quat", new Quat());
3280 surfaceContext->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
3281 surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
3282 surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
3283
3284 if (setAdditionalContextProperties) {
3285 auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
3286 auto flags = tabletScriptingInterface->getFlags();
3287
3288 surfaceContext->setContextProperty("offscreenFlags", flags);
3289 surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
3290
3291 surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
3292 surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
3293 surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
3294
3295 surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
3296 surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
3297 surfaceContext->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
3298
3299 // in Qt 5.10.0 there is already an "Audio" object in the QML context
3300 // though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
3301 surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data());
3302
3303 surfaceContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
3304 surfaceContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
3305 surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
3306 surfaceContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
3307 surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
3308 surfaceContext->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
3309 surfaceContext->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
3310 surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
3311 surfaceContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
3312 surfaceContext->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
3313 surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
3314 surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
3315 surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
3316 surfaceContext->setContextProperty("Render", AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get());
3317 surfaceContext->setContextProperty("Workload", qApp->getGameWorkload()._engine->getConfiguration().get());
3318 surfaceContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
3319 surfaceContext->setContextProperty("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
3320 surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
3321 surfaceContext->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
3322 surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
3323 surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
3324 surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
3325 }
3326}
3327
3168void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {3328void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
3169 PROFILE_RANGE(render, __FUNCTION__);3329 PROFILE_RANGE(render, __FUNCTION__);
3170 PerformanceTimer perfTimer("updateCamera");3330 PerformanceTimer perfTimer("updateCamera");
@@ -3421,8 +3581,10 @@ void Application::resizeGL() { · 250 unmodified lines
3421 auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();3581 auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
3422 assert(renderConfig);3582 assert(renderConfig);
3423 auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");3583 auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
3424 assert(mainView);3584 // mainView can be null if we're rendering in forward mode
3425 mainView->setProperty("resolutionScale", renderResolutionScale);3585 if (mainView) {
3586 mainView->setProperty("resolutionScale", renderResolutionScale);
3587 }
3426 displayPlugin->setRenderResolutionScale(renderResolutionScale);3588 displayPlugin->setRenderResolutionScale(renderResolutionScale);
3427 }3589 }
3428 3590
@@ -3677,8 +3839,8 @@ static inline bool isKeyEvent(QEvent::Type type) { · 248 unmodified lines
3677 return type == QEvent::KeyPress || type == QEvent::KeyRelease;3839 return type == QEvent::KeyPress || type == QEvent::KeyRelease;
3678}3840}
3679 3841
3680bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) {3842bool Application::handleKeyEventForFocusedEntity(QEvent* event) {
3681 if (!_keyboardFocusedEntity.get().isInvalidID()) {3843 if (_keyboardFocusedEntity.get() != UNKNOWN_ENTITY_ID) {
3682 switch (event->type()) {3844 switch (event->type()) {
3683 case QEvent::KeyPress:3845 case QEvent::KeyPress:
3684 case QEvent::KeyRelease:3846 case QEvent::KeyRelease:
@@ -3699,28 +3861,6 @@ bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) { · 14 unmodified lines
3699 }3861 }
3700 }3862 }
3701 3863
3702 if (_keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) {
3703 switch (event->type()) {
3704 case QEvent::KeyPress:
3705 case QEvent::KeyRelease: {
3706 // Only Web overlays can have focus.
3707 auto overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
3708 if (overlay && overlay->getEventHandler()) {
3709 event->setAccepted(false);
3710 QCoreApplication::sendEvent(overlay->getEventHandler(), event);
3711 if (event->isAccepted()) {
3712 _lastAcceptedKeyPress = usecTimestampNow();
3713 return true;
3714 }
3715 }
3716 }
3717 break;
3718
3719 default:
3720 break;
3721 }
3722 }
3723
3724 return false;3864 return false;
3725}3865}
3726 3866
@@ -3763,8 +3903,8 @@ bool Application::event(QEvent* event) { · 36 unmodified lines
3763 return false;3903 return false;
3764 }3904 }
3765 3905
3766 // Allow focused Entities and Overlays to handle keyboard input3906 // Allow focused Entities to handle keyboard input
3767 if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event)) {3907 if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntity(event)) {
3768 return true;3908 return true;
3769 }3909 }
3770 3910
@@ -3970,6 +4110,19 @@ void Application::keyPressEvent(QKeyEvent* event) { · 199 unmodified lines
3970 }4110 }
3971 break;4111 break;
3972 4112
4113 case Qt::Key_G:
4114 if (isShifted && isMeta && Menu::getInstance() && Menu::getInstance()->getMenu("Developer")->isVisible()) {
4115 static const QString HIFI_FRAMES_FOLDER_VAR = "HIFI_FRAMES_FOLDER";
4116 static const QString GPU_FRAME_FOLDER = QProcessEnvironment::systemEnvironment().contains(HIFI_FRAMES_FOLDER_VAR)
4117 ? QProcessEnvironment::systemEnvironment().value(HIFI_FRAMES_FOLDER_VAR)
4118 : "hifiFrames";
4119 static QString GPU_FRAME_TEMPLATE = GPU_FRAME_FOLDER + "/{DATE}_{TIME}";
4120 QString fullPath = FileUtils::computeDocumentPath(FileUtils::replaceDateTimeTokens(GPU_FRAME_TEMPLATE));
4121 if (FileUtils::canCreateFile(fullPath)) {
4122 getActiveDisplayPlugin()->captureFrame(fullPath.toStdString());
4123 }
4124 }
4125 break;
3973 case Qt::Key_X:4126 case Qt::Key_X:
3974 if (isShifted && isMeta) {4127 if (isShifted && isMeta) {
3975 auto offscreenUi = getOffscreenUI();4128 auto offscreenUi = getOffscreenUI();
@@ -4041,7 +4194,9 @@ void Application::keyPressEvent(QKeyEvent* event) { · 65 unmodified lines
4041 if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) {4194 if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) {
4042 AudioInjectorOptions options;4195 AudioInjectorOptions options;
4043 options.localOnly = true;4196 options.localOnly = true;
4197 options.positionSet = false; // system sound
4044 options.stereo = true;4198 options.stereo = true;
4199
4045 Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true };4200 Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true };
4046 Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true };4201 Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true };
4047 if (notificationSounds.get() && notificationSoundSnapshot.get()) {4202 if (notificationSounds.get() && notificationSoundSnapshot.get()) {
@@ -4230,9 +4385,9 @@ void Application::mouseMoveEvent(QMouseEvent* event) { · 182 unmodified lines
4230 buttons, event->modifiers());4385 buttons, event->modifiers());
4231 4386
4232 if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||4387 if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||
4233 getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_OVERLAY_ID) {4388 getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) {
4234 getOverlays().mouseMoveEvent(&mappedEvent);
4235 getEntities()->mouseMoveEvent(&mappedEvent);4389 getEntities()->mouseMoveEvent(&mappedEvent);
4390 getOverlays().mouseMoveEvent(&mappedEvent);
4236 }4391 }
4237 4392
4238 _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts4393 _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts
@@ -4264,15 +4419,16 @@ void Application::mousePressEvent(QMouseEvent* event) { · 25 unmodified lines
4264#else4419#else
4265 QPointF transformedPos;4420 QPointF transformedPos;
4266#endif4421#endif
4267 QMouseEvent mappedEvent(event->type(),
4268 transformedPos,
4269 event->screenPos(), event->button(),
4270 event->buttons(), event->modifiers());
4271 4422
4272 getOverlays().mousePressEvent(&mappedEvent);4423 QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers());
4424 std::pair<float, QUuid> entityResult;
4273 if (!_controllerScriptingInterface->areEntityClicksCaptured()) {4425 if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
4274 getEntities()->mousePressEvent(&mappedEvent);4426 entityResult = getEntities()->mousePressEvent(&mappedEvent);
4275 }4427 }
4428 std::pair<float, QUuid> overlayResult = getOverlays().mousePressEvent(&mappedEvent);
4429
4430 QUuid focusedEntity = entityResult.first < overlayResult.first ? entityResult.second : overlayResult.second;
4431 setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(focusedEntity) ? focusedEntity : UNKNOWN_ENTITY_ID);
4276 4432
4277 _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts4433 _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
4278 4434
@@ -4312,10 +4468,10 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { · 33 unmodified lines
4312 event->screenPos(), event->button(),4468 event->screenPos(), event->button(),
4313 event->buttons(), event->modifiers());4469 event->buttons(), event->modifiers());
4314 4470
4315 getOverlays().mouseDoublePressEvent(&mappedEvent);
4316 if (!_controllerScriptingInterface->areEntityClicksCaptured()) {4471 if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
4317 getEntities()->mouseDoublePressEvent(&mappedEvent);4472 getEntities()->mouseDoublePressEvent(&mappedEvent);
4318 }4473 }
4474 getOverlays().mouseDoublePressEvent(&mappedEvent);
4319 4475
4320 // if one of our scripts have asked to capture this event, then stop processing it4476 // if one of our scripts have asked to capture this event, then stop processing it
4321 if (_controllerScriptingInterface->isMouseCaptured()) {4477 if (_controllerScriptingInterface->isMouseCaptured()) {
@@ -4339,8 +4495,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { · 17 unmodified lines
4339 event->screenPos(), event->button(),4495 event->screenPos(), event->button(),
4340 event->buttons(), event->modifiers());4496 event->buttons(), event->modifiers());
4341 4497
4342 getOverlays().mouseReleaseEvent(&mappedEvent);
4343 getEntities()->mouseReleaseEvent(&mappedEvent);4498 getEntities()->mouseReleaseEvent(&mappedEvent);
4499 getOverlays().mouseReleaseEvent(&mappedEvent);
4344 4500
4345 _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts4501 _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
4346 4502
@@ -4751,6 +4907,10 @@ void Application::idle() { · 404 unmodified lines
4751 steamClient->runCallbacks();4907 steamClient->runCallbacks();
4752 }4908 }
4753 4909
4910 if (auto oculusPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) {
4911 oculusPlugin->handleOVREvents();
4912 }
4913
4754 float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND;4914 float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND;
4755 _lastTimeUpdated.start();4915 _lastTimeUpdated.start();
4756 4916
@@ -4784,7 +4944,11 @@ void Application::idle() { · 27 unmodified lines
4784 // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing4944 // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing
4785 // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing4945 // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing
4786 // details normally.4946 // details normally.
4947#ifdef Q_OS_ANDROID
4948 bool showWarnings = false;
4949#else
4787 bool showWarnings = getLogger()->extraDebugging();4950 bool showWarnings = getLogger()->extraDebugging();
4951#endif
4788 PerformanceWarning warn(showWarnings, "idle()");4952 PerformanceWarning warn(showWarnings, "idle()");
4789 4953
4790 {4954 {
@@ -4798,31 +4962,19 @@ void Application::idle() { · 7 unmodified lines
4798 update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS));4962 update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS));
4799 }4963 }
4800 4964
4801 4965 { // Update keyboard focus highlight
4802 // Update focus highlight for entity or overlay.4966 if (!_keyboardFocusedEntity.get().isInvalidID()) {
4803 {
4804 if (!_keyboardFocusedEntity.get().isInvalidID() || _keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) {
4805 const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus4967 const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus
4806 quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress;4968 quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress;
4807 if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) {4969 if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) {
4808 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);4970 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
4809 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
4810 } else {4971 } else {
4811 // update position of highlight overlay4972 if (auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get())) {
4812 if (!_keyboardFocusedEntity.get().isInvalidID()) {4973 EntityItemProperties properties;
4813 auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get());4974 properties.setPosition(entity->getWorldPosition());
4814 if (entity && _keyboardFocusHighlight) {4975 properties.setRotation(entity->getWorldOrientation());
4815 _keyboardFocusHighlight->setWorldOrientation(entity->getWorldOrientation());4976 properties.setDimensions(entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
4816 _keyboardFocusHighlight->setWorldPosition(entity->getWorldPosition());4977 DependencyManager::get<EntityScriptingInterface>()->editEntity(_keyboardFocusHighlightID, properties);
4817 }
4818 } else {
4819 // Only Web overlays can have focus.
4820 auto overlay =
4821 std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
4822 if (overlay && _keyboardFocusHighlight) {
4823 _keyboardFocusHighlight->setWorldOrientation(overlay->getWorldOrientation());
4824 _keyboardFocusHighlight->setWorldPosition(overlay->getWorldPosition());
4825 }
4826 }4978 }
4827 }4979 }
4828 }4980 }
@@ -5620,118 +5772,80 @@ void Application::rotationModeChanged() const { · 791 unmodified lines
5620}5772}
5621 5773
5622void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) {5774void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) {
5623 // Create focus
5624 if (qApp->getLoginDialogPoppedUp()) {5775 if (qApp->getLoginDialogPoppedUp()) {
5625 return;5776 return;
5626 }5777 }
5627 if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) {5778
5628 _keyboardFocusHighlight = std::make_shared<Cube3DOverlay>();5779 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
5629 _keyboardFocusHighlight->setAlpha(1.0f);5780 if (_keyboardFocusHighlightID == UNKNOWN_ENTITY_ID || !entityScriptingInterface->isAddedEntity(_keyboardFocusHighlightID)) {
5630 _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 });5781 EntityItemProperties properties;
5631 _keyboardFocusHighlight->setIsSolid(false);5782 properties.setType(EntityTypes::Box);
5632 _keyboardFocusHighlight->setPulseMin(0.5);5783 properties.setAlpha(1.0f);
5633 _keyboardFocusHighlight->setPulseMax(1.0);5784 properties.setColor({ 0xFF, 0xEF, 0x00 });
5634 _keyboardFocusHighlight->setColorPulse(1.0);5785 properties.setPrimitiveMode(PrimitiveMode::LINES);
5635 _keyboardFocusHighlight->setIgnorePickIntersection(true);5786 properties.getPulse().setMin(0.5);
5636 _keyboardFocusHighlight->setDrawInFront(false);5787 properties.getPulse().setMax(1.0f);
5637 _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight);5788 properties.getPulse().setColorMode(PulseMode::IN_PHASE);
5789 properties.setIgnorePickIntersection(true);
5790 _keyboardFocusHighlightID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
5638 }5791 }
5639 5792
5640 // Position focus5793 // Position focus
5641 _keyboardFocusHighlight->setWorldOrientation(rotation);5794 EntityItemProperties properties;
5642 _keyboardFocusHighlight->setWorldPosition(position);5795 properties.setPosition(position);
5643 _keyboardFocusHighlight->setDimensions(dimensions);5796 properties.setRotation(rotation);
5644 _keyboardFocusHighlight->setVisible(true);5797 properties.setDimensions(dimensions);
5798 properties.setVisible(true);
5799 entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties);
5645}5800}
5646 5801
5647QUuid Application::getKeyboardFocusEntity() const {5802QUuid Application::getKeyboardFocusEntity() const {
5648 return _keyboardFocusedEntity.get();5803 return _keyboardFocusedEntity.get();
5649}5804}
5650 5805
5651static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;5806void Application::setKeyboardFocusEntity(const QUuid& id) {
5652 5807 if (_keyboardFocusedEntity.get() != id) {
5653void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {5808 if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) {
5654 if (qApp->getLoginDialogPoppedUp()) {5809 if (id == _loginDialogID) {
5655 return;
5656 }
5657 if (_keyboardFocusedEntity.get() != entityItemID) {
5658 _keyboardFocusedEntity.set(entityItemID);
5659
5660 if (_keyboardFocusHighlight && _keyboardFocusedOverlay.get() == UNKNOWN_OVERLAY_ID) {
5661 _keyboardFocusHighlight->setVisible(false);
5662 }
5663
5664 if (entityItemID == UNKNOWN_ENTITY_ID) {
5665 return;
5666 }
5667
5668 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
5669 auto properties = entityScriptingInterface->getEntityProperties(entityItemID);
5670 if (!properties.getLocked() && properties.getVisible()) {
5671
5672 auto entities = getEntities();
5673 auto entityId = _keyboardFocusedEntity.get();
5674 if (entities->wantsKeyboardFocus(entityId)) {
5675 entities->setProxyWindow(entityId, _window->windowHandle());
5676 if (_keyboardMouseDevice->isActive()) {
5677 _keyboardMouseDevice->pluginFocusOutEvent();
5678 }
5679 _lastAcceptedKeyPress = usecTimestampNow();
5680
5681 auto entity = getEntities()->getEntity(entityId);
5682 if (entity) {
5683 setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
5684 entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
5685 }
5686 }
5687 }
5688 }
5689}
5690
5691OverlayID Application::getKeyboardFocusOverlay() {
5692 return _keyboardFocusedOverlay.get();
5693}
5694
5695void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
5696 if (overlayID != _keyboardFocusedOverlay.get()) {
5697 if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) {
5698 if (overlayID == _loginDialogOverlayID) {
5699 emit loginDialogFocusEnabled();5810 emit loginDialogFocusEnabled();
5700 } else {5811 } else {
5701 // that's the only overlay we want in focus;5812 // that's the only entity we want in focus;
5702 return;5813 return;
5703 }5814 }
5704 }5815 }
5705 5816
5706 _keyboardFocusedOverlay.set(overlayID);5817 _keyboardFocusedEntity.set(id);
5707
5708 if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) {
5709 _keyboardFocusHighlight->setVisible(false);
5710 }
5711
5712 if (overlayID == UNKNOWN_OVERLAY_ID) {
5713 return;
5714 }
5715 5818
5716 auto overlayType = getOverlays().getOverlayType(overlayID);5819 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
5717 auto isVisible = getOverlays().getProperty(overlayID, "visible").value.toBool();5820 if (id != UNKNOWN_ENTITY_ID) {
5718 if (overlayType == Web3DOverlay::TYPE && isVisible) {5821 EntityPropertyFlags desiredProperties;
5719 auto overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(overlayID));5822 desiredProperties += PROP_VISIBLE;
5720 overlay->setProxyWindow(_window->windowHandle());5823 desiredProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT;
5824 auto properties = entityScriptingInterface->getEntityProperties(id);
5825 if (properties.getVisible()) {
5826 auto entities = getEntities();
5827 auto entityId = _keyboardFocusedEntity.get();
5828 if (entities->wantsKeyboardFocus(entityId)) {
5829 entities->setProxyWindow(entityId, _window->windowHandle());
5830 if (_keyboardMouseDevice->isActive()) {
5831 _keyboardMouseDevice->pluginFocusOutEvent();
5832 }
5833 _lastAcceptedKeyPress = usecTimestampNow();
5721 5834
5722 if (_keyboardMouseDevice->isActive()) {5835 if (properties.getShowKeyboardFocusHighlight()) {
5723 _keyboardMouseDevice->pluginFocusOutEvent();5836 if (auto entity = entities->getEntity(entityId)) {
5724 }5837 setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
5725 _lastAcceptedKeyPress = usecTimestampNow();5838 entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
5726 5839 return;
5727 if (overlay->getProperty("showKeyboardFocusHighlight").toBool()) {5840 }
5728 auto size = overlay->getSize() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR;5841 }
5729 const float OVERLAY_DEPTH = 0.0105f;5842 }
5730 setKeyboardFocusHighlight(overlay->getWorldPosition(), overlay->getWorldOrientation(), glm::vec3(size.x, size.y, OVERLAY_DEPTH));
5731 } else if (_keyboardFocusHighlight) {
5732 _keyboardFocusHighlight->setVisible(false);
5733 }5843 }
5734 }5844 }
5845
5846 EntityItemProperties properties;
5847 properties.setVisible(false);
5848 entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties);
5735 }5849 }
5736}5850}
5737 5851
@@ -5935,6 +6049,13 @@ void Application::update(float deltaTime) { · 197 unmodified lines
5935 6049
5936 auto userInputMapper = DependencyManager::get<UserInputMapper>();6050 auto userInputMapper = DependencyManager::get<UserInputMapper>();
5937 6051
6052 controller::HmdAvatarAlignmentType hmdAvatarAlignmentType;
6053 if (myAvatar->getHmdAvatarAlignmentType() == "eyes") {
6054 hmdAvatarAlignmentType = controller::HmdAvatarAlignmentType::Eyes;
6055 } else {
6056 hmdAvatarAlignmentType = controller::HmdAvatarAlignmentType::Head;
6057 }
6058
5938 controller::InputCalibrationData calibrationData = {6059 controller::InputCalibrationData calibrationData = {
5939 myAvatar->getSensorToWorldMatrix(),6060 myAvatar->getSensorToWorldMatrix(),
5940 createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()),6061 createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()),
@@ -5948,7 +6069,8 @@ void Application::update(float deltaTime) { · 7 unmodified lines
5948 myAvatar->getRightArmCalibrationMat(),6069 myAvatar->getRightArmCalibrationMat(),
5949 myAvatar->getLeftArmCalibrationMat(),6070 myAvatar->getLeftArmCalibrationMat(),
5950 myAvatar->getRightHandCalibrationMat(),6071 myAvatar->getRightHandCalibrationMat(),
5951 myAvatar->getLeftHandCalibrationMat()6072 myAvatar->getLeftHandCalibrationMat(),
6073 hmdAvatarAlignmentType
5952 };6074 };
5953 6075
5954 InputPluginPointer keyboardMousePlugin;6076 InputPluginPointer keyboardMousePlugin;
@@ -6100,6 +6222,19 @@ void Application::update(float deltaTime) { · 145 unmodified lines
6100 auto grabManager = DependencyManager::get<GrabManager>();6222 auto grabManager = DependencyManager::get<GrabManager>();
6101 grabManager->simulateGrabs();6223 grabManager->simulateGrabs();
6102 6224
6225 // TODO: break these out into distinct perfTimers when they prove interesting
6226 {
6227 PROFILE_RANGE(app, "PickManager");
6228 PerformanceTimer perfTimer("pickManager");
6229 DependencyManager::get<PickManager>()->update();
6230 }
6231
6232 {
6233 PROFILE_RANGE(app, "PointerManager");
6234 PerformanceTimer perfTimer("pointerManager");
6235 DependencyManager::get<PointerManager>()->update();
6236 }
6237
6103 QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();6238 QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
6104 6239
6105 {6240 {
@@ -6113,36 +6248,57 @@ void Application::update(float deltaTime) { · 7 unmodified lines
6113 PROFILE_RANGE(simulation_physics, "PrePhysics");6248 PROFILE_RANGE(simulation_physics, "PrePhysics");
6114 PerformanceTimer perfTimer("prePhysics)");6249 PerformanceTimer perfTimer("prePhysics)");
6115 {6250 {
6251 PROFILE_RANGE(simulation_physics, "RemoveEntities");
6116 const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics();6252 const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics();
6117 _physicsEngine->removeObjects(motionStates);6253 {
6254 PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size());
6255 _physicsEngine->removeObjects(motionStates);
6256 }
6118 _entitySimulation->deleteObjectsRemovedFromPhysics();6257 _entitySimulation->deleteObjectsRemovedFromPhysics();
6119 }6258 }
6120 6259
6121 VectorOfMotionStates motionStates;6260 {
6122 getEntities()->getTree()->withReadLock([&] {6261 PROFILE_RANGE(simulation_physics, "AddEntities");
6123 _entitySimulation->getObjectsToAddToPhysics(motionStates);6262 VectorOfMotionStates motionStates;
6124 _physicsEngine->addObjects(motionStates);6263 getEntities()->getTree()->withReadLock([&] {
6125 6264 _entitySimulation->getObjectsToAddToPhysics(motionStates);
6126 });6265 PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size());
6127 getEntities()->getTree()->withReadLock([&] {6266 _physicsEngine->addObjects(motionStates);
6128 _entitySimulation->getObjectsToChange(motionStates);6267 });
6129 VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);6268 }
6130 _entitySimulation->setObjectsToChange(stillNeedChange);6269 {
6131 });6270 VectorOfMotionStates motionStates;
6271 PROFILE_RANGE(simulation_physics, "ChangeEntities");
6272 getEntities()->getTree()->withReadLock([&] {
6273 _entitySimulation->getObjectsToChange(motionStates);
6274 VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
6275 _entitySimulation->setObjectsToChange(stillNeedChange);
6276 });
6277 }
6132 6278
6133 _entitySimulation->applyDynamicChanges();6279 _entitySimulation->applyDynamicChanges();
6134 6280
6135 t1 = std::chrono::high_resolution_clock::now();6281 t1 = std::chrono::high_resolution_clock::now();
6136 6282
6137 PhysicsEngine::Transaction transaction;6283 {
6138 avatarManager->buildPhysicsTransaction(transaction);6284 PROFILE_RANGE(simulation_physics, "Avatars");
6139 _physicsEngine->processTransaction(transaction);6285 PhysicsEngine::Transaction transaction;
6140 avatarManager->handleProcessedPhysicsTransaction(transaction);6286 avatarManager->buildPhysicsTransaction(transaction);
6287 _physicsEngine->processTransaction(transaction);
6288 avatarManager->handleProcessedPhysicsTransaction(transaction);
6289 myAvatar->getCharacterController()->buildPhysicsTransaction(transaction);
6290 _physicsEngine->processTransaction(transaction);
6291 myAvatar->getCharacterController()->handleProcessedPhysicsTransaction(transaction);
6292 myAvatar->prepareForPhysicsSimulation();
6293 _physicsEngine->enableGlobalContactAddedCallback(myAvatar->isFlying());
6294 }
6141 6295
6142 myAvatar->prepareForPhysicsSimulation();6296 {
6143 _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) {6297 PROFILE_RANGE(simulation_physics, "PrepareActions");
6144 dynamic->prepareForPhysicsSimulation();6298 _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) {
6145 });6299 dynamic->prepareForPhysicsSimulation();
6300 });
6301 }
6146 }6302 }
6147 auto t2 = std::chrono::high_resolution_clock::now();6303 auto t2 = std::chrono::high_resolution_clock::now();
6148 {6304 {
@@ -6245,22 +6401,9 @@ void Application::update(float deltaTime) { · 96 unmodified lines
6245 6401
6246 updateLOD(deltaTime);6402 updateLOD(deltaTime);
6247 6403
6248 if (!_loginDialogOverlayID.isNull()) {6404 if (!_loginDialogID.isNull()) {
6249 _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogOverlayID);6405 _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogID);
6250 updateLoginDialogOverlayPosition();6406 updateLoginDialogPosition();
6251 }
6252
6253 // TODO: break these out into distinct perfTimers when they prove interesting
6254 {
6255 PROFILE_RANGE(app, "PickManager");
6256 PerformanceTimer perfTimer("pickManager");
6257 DependencyManager::get<PickManager>()->update();
6258 }
6259
6260 {
6261 PROFILE_RANGE(app, "PointerManager");
6262 PerformanceTimer perfTimer("pointerManager");
6263 DependencyManager::get<PointerManager>()->update();
6264 }6407 }
6265 6408
6266 {6409 {
@@ -6284,7 +6427,7 @@ void Application::update(float deltaTime) { · 17 unmodified lines
6284 // TODO: Fix this by modeling the way the secondary camera works on how the main camera works6427 // TODO: Fix this by modeling the way the secondary camera works on how the main camera works
6285 // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary6428 // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
6286 // camera should be.6429 // camera should be.
6287 // updateSecondaryCameraViewFrustum();6430 updateSecondaryCameraViewFrustum();
6288 }6431 }
6289 6432
6290 quint64 now = usecTimestampNow();6433 quint64 now = usecTimestampNow();
@@ -6843,17 +6986,19 @@ void Application::nodeActivated(SharedNodePointer node) { · 552 unmodified lines
6843 6986
6844#if !defined(DISABLE_QML)6987#if !defined(DISABLE_QML)
6845 auto offscreenUi = getOffscreenUI();6988 auto offscreenUi = getOffscreenUI();
6846 auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer") : nullptr;
6847 6989
6848 if (assetDialog) {6990 if (offscreenUi) {
6849 auto nodeList = DependencyManager::get<NodeList>();6991 auto nodeList = DependencyManager::get<NodeList>();
6850 6992
6851 if (nodeList->getThisNodeCanWriteAssets()) {6993 if (nodeList->getThisNodeCanWriteAssets()) {
6852 // call reload on the shown asset browser dialog to get the mappings (if permissions allow)6994 // call reload on the shown asset browser dialog to get the mappings (if permissions allow)
6853 QMetaObject::invokeMethod(assetDialog, "reload");6995 auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer") : nullptr;
6996 if (assetDialog) {
6997 QMetaObject::invokeMethod(assetDialog, "reload");
6998 }
6854 } else {6999 } else {
6855 // we switched to an Asset Server that we can't modify, hide the Asset Browser7000 // we switched to an Asset Server that we can't modify, hide the Asset Browser
6856 assetDialog->setVisible(false);7001 offscreenUi->hide("AssetServer");
6857 }7002 }
6858 }7003 }
6859#endif7004#endif
@@ -7026,7 +7171,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 166 unmodified lines
7026 connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);7171 connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);
7027 7172
7028 scriptEngine->registerGlobalObject("Overlays", &_overlays);7173 scriptEngine->registerGlobalObject("Overlays", &_overlays);
7029 qScriptRegisterMetaType(scriptEngine.data(), OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
7030 qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue,7174 qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue,
7031 RayToOverlayIntersectionResultFromScriptValue);7175 RayToOverlayIntersectionResultFromScriptValue);
7032 7176
@@ -7143,8 +7287,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 110 unmodified lines
7143 scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());7287 scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
7144 scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());7288 scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
7145 7289
7146 qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
7147
7148 registerInteractiveWindowMetaType(scriptEngine.data());7290 registerInteractiveWindowMetaType(scriptEngine.data());
7149 7291
7150 auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();7292 auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();
@@ -8025,8 +8167,7 @@ void Application::openUrl(const QUrl& url) const { · 874 unmodified lines
8025 if (url.scheme() == URL_SCHEME_HIFI) {8167 if (url.scheme() == URL_SCHEME_HIFI) {
8026 DependencyManager::get<AddressManager>()->handleLookupString(url.toString());8168 DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
8027 } else if (url.scheme() == URL_SCHEME_HIFIAPP) {8169 } else if (url.scheme() == URL_SCHEME_HIFIAPP) {
8028 QmlCommerce commerce;8170 DependencyManager::get<QmlCommerce>()->openSystemApp(url.path());
8029 commerce.openSystemApp(url.path());
8030 } else {8171 } else {
8031 // address manager did not handle - ask QDesktopServices to handle8172 // address manager did not handle - ask QDesktopServices to handle
8032 QDesktopServices::openUrl(url);8173 QDesktopServices::openUrl(url);
@@ -8112,7 +8253,18 @@ void Application::toggleLogDialog() { · 79 unmodified lines
8112 return;8253 return;
8113 }8254 }
8114 if (! _logDialog) {8255 if (! _logDialog) {
8256
8257 bool keepOnTop =_keepLogWindowOnTop.get();
8258#ifdef Q_OS_WIN
8259 _logDialog = new LogDialog(keepOnTop ? qApp->getWindow() : nullptr, getLogger());
8260#elif !defined(Q_OS_ANDROID)
8115 _logDialog = new LogDialog(nullptr, getLogger());8261 _logDialog = new LogDialog(nullptr, getLogger());
8262
8263 if (keepOnTop) {
8264 Qt::WindowFlags flags = _logDialog->windowFlags() | Qt::Tool;
8265 _logDialog->setWindowFlags(flags);
8266 }
8267#endif
8116 }8268 }
8117 8269
8118 if (_logDialog->isVisible()) {8270 if (_logDialog->isVisible()) {
@@ -8122,6 +8274,19 @@ void Application::toggleLogDialog() { · 3 unmodified lines
8122 }8274 }
8123}8275}
8124 8276
8277 void Application::recreateLogWindow(int keepOnTop) {
8278 _keepLogWindowOnTop.set(keepOnTop != 0);
8279 if (_logDialog) {
8280 bool toggle = _logDialog->isVisible();
8281 _logDialog->close();
8282 _logDialog = nullptr;
8283
8284 if (toggle) {
8285 toggleLogDialog();
8286 }
8287 }
8288 }
8289
8125void Application::toggleEntityScriptServerLogDialog() {8290void Application::toggleEntityScriptServerLogDialog() {
8126 if (! _entityScriptServerLogDialog) {8291 if (! _entityScriptServerLogDialog) {
8127 _entityScriptServerLogDialog = new EntityScriptServerLogDialog(nullptr);8292 _entityScriptServerLogDialog = new EntityScriptServerLogDialog(nullptr);
@@ -8643,45 +8808,47 @@ void Application::setShowBulletConstraintLimits(bool value) { · 515 unmodified lines
8643 _physicsEngine->setShowBulletConstraintLimits(value);8808 _physicsEngine->setShowBulletConstraintLimits(value);
8644}8809}
8645 8810
8646void Application::createLoginDialogOverlay() {8811void Application::createLoginDialog() {
8647 const glm::vec2 LOGIN_OVERLAY_DIMENSIONS{ 0.89f, 0.5f };8812 const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f };
8648 const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f);8813 const auto OFFSET = glm::vec2(0.7f, -0.1f);
8649 auto cameraPosition = _myCamera.getPosition();8814 auto cameraPosition = _myCamera.getPosition();
8650 auto cameraOrientation = _myCamera.getOrientation();8815 auto cameraOrientation = _myCamera.getOrientation();
8651 auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;8816 auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;
8652 auto headLookVec = (cameraOrientation * Vectors::FRONT);8817 auto headLookVec = (cameraOrientation * Vectors::FRONT);
8653 // DEFAULT_DPI / tablet scale percentage8818 // DEFAULT_DPI / tablet scale percentage
8654 const float OVERLAY_DPI = 31.0f / (75.0f / 100.0f);8819 const float DPI = 31.0f / (75.0f / 100.0f);
8655 auto offset = headLookVec * OVERLAY_OFFSET.x;8820 auto offset = headLookVec * OFFSET.x;
8656 auto overlayPosition = (cameraPosition + offset) + (upVec * OVERLAY_OFFSET.y);8821 auto position = (cameraPosition + offset) + (upVec * OFFSET.y);
8657 QVariantMap overlayProperties = {8822
8658 { "name", "LoginDialogOverlay" },8823 EntityItemProperties properties;
8659 { "url", OVERLAY_LOGIN_DIALOG },8824 properties.setType(EntityTypes::Web);
8660 { "position", vec3toVariant(overlayPosition) },8825 properties.setName("LoginDialogEntity");
8661 { "orientation", quatToVariant(cameraOrientation) },8826 properties.setSourceUrl(LOGIN_DIALOG.toString());
8662 { "isSolid", true },8827 properties.setPosition(position);
8663 { "grabbable", false },8828 properties.setRotation(cameraOrientation);
8664 { "ignorePickIntersection", false },8829 properties.setDimensions(LOGIN_DIMENSIONS);
8665 { "alpha", 1.0 },8830 properties.setPrimitiveMode(PrimitiveMode::SOLID);
8666 { "dimensions", vec2ToVariant(LOGIN_OVERLAY_DIMENSIONS)},8831 properties.getGrab().setGrabbable(false);
8667 { "dpi", OVERLAY_DPI },8832 properties.setIgnorePickIntersection(false);
8668 { "visible", true }8833 properties.setAlpha(1.0f);
8669 };8834 properties.setDPI(DPI);
8670 auto& overlays = getOverlays();8835 properties.setVisible(true);
8671 _loginDialogOverlayID = overlays.addOverlay("web3d", overlayProperties);8836
8672 auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID));8837 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
8838 _loginDialogID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
8839
8673 auto keyboard = DependencyManager::get<Keyboard>().data();8840 auto keyboard = DependencyManager::get<Keyboard>().data();
8674 if (!keyboard->getAnchorID().isNull() && !_loginDialogOverlayID.isNull()) {8841 if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) {
8675 const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f);
8676 auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);8842 auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
8677 QVariantMap properties {8843
8678 { "position", vec3toVariant(overlayPosition + keyboardLocalOffset) },8844 EntityItemProperties properties;
8679 { "orientation", quatToVariant(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION) },8845 properties.setPosition(position + keyboardLocalOffset);
8680 };8846 properties.setRotation(cameraOrientation * Quaternions::Y_180);
8681 overlays.editOverlay(keyboard->getAnchorID(), properties);8847
8848 entityScriptingInterface->editEntity(keyboard->getAnchorID(), properties);
8682 keyboard->setResetKeyboardPositionOnRaise(false);8849 keyboard->setResetKeyboardPositionOnRaise(false);
8683 }8850 }
8684 setKeyboardFocusOverlay(_loginDialogOverlayID);8851 setKeyboardFocusEntity(_loginDialogID);
8685 emit loginDialogFocusEnabled();8852 emit loginDialogFocusEnabled();
8686 getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false);8853 getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false);
8687 getApplicationCompositor().getReticleInterface()->setVisible(false);8854 getApplicationCompositor().getReticleInterface()->setVisible(false);
@@ -8690,38 +8857,43 @@ void Application::createLoginDialogOverlay() { · 2 unmodified lines
8690 }8857 }
8691}8858}
8692 8859
8693void Application::updateLoginDialogOverlayPosition() {8860void Application::updateLoginDialogPosition() {
8694 const float LOOK_AWAY_THRESHOLD_ANGLE = 70.0f;8861 const float LOOK_AWAY_THRESHOLD_ANGLE = 70.0f;
8695 const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f);8862 const auto OFFSET = glm::vec2(0.7f, -0.1f);
8696 auto& overlays = getOverlays();8863
8697 auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID));8864 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
8698 auto overlayPositionVec = loginOverlay->getWorldPosition();8865 EntityPropertyFlags desiredProperties;
8866 desiredProperties += PROP_POSITION;
8867 auto properties = entityScriptingInterface->getEntityProperties(_loginDialogID, desiredProperties);
8868 auto positionVec = properties.getPosition();
8699 auto cameraPositionVec = _myCamera.getPosition();8869 auto cameraPositionVec = _myCamera.getPosition();
8700 auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation());8870 auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation());
8701 auto headLookVec = (cameraOrientation * Vectors::FRONT);8871 auto headLookVec = (cameraOrientation * Vectors::FRONT);
8702 auto overlayToHeadVec = overlayPositionVec - cameraPositionVec;8872 auto entityToHeadVec = positionVec - cameraPositionVec;
8703 auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI);8873 auto pointAngle = (glm::acos(glm::dot(glm::normalize(entityToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI);
8704 auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;8874 auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;
8705 auto offset = headLookVec * OVERLAY_OFFSET.x;8875 auto offset = headLookVec * OFFSET.x;
8706 auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * OVERLAY_OFFSET.y);8876 auto newPositionVec = (cameraPositionVec + offset) + (upVec * OFFSET.y);
8707 auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180;
8708 8877
8709 bool overlayOutOfBounds = glm::distance(overlayPositionVec, cameraPositionVec) > 1.0f;8878 bool outOfBounds = glm::distance(positionVec, cameraPositionVec) > 1.0f;
8710 8879
8711 if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || overlayOutOfBounds) {8880 if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || outOfBounds) {
8712 QVariantMap properties {8881 {
8713 {"position", vec3toVariant(newOverlayPositionVec)},8882 EntityItemProperties properties;
8714 {"orientation", quatToVariant(newOverlayOrientation)}8883 properties.setPosition(newPositionVec);
8715 };8884 properties.setRotation(cameraOrientation);
8716 overlays.editOverlay(_loginDialogOverlayID, properties);8885 entityScriptingInterface->editEntity(_loginDialogID, properties);
8717 const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f);8886 }
8718 auto keyboardLocalOffset = newOverlayOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);8887
8719 QVariantMap keyboardProperties {8888 {
8720 { "position", vec3toVariant(newOverlayPositionVec + keyboardLocalOffset) },8889 glm::vec3 keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
8721 { "orientation", quatToVariant(newOverlayOrientation * KEYBOARD_LOCAL_ORIENTATION) },8890 glm::quat keyboardOrientation = cameraOrientation * glm::quat(glm::radians(glm::vec3(-30.0f, 180.0f, 0.0f)));
8722 };8891
8723 auto keyboard = DependencyManager::get<Keyboard>().data();8892 EntityItemProperties properties;
8724 overlays.editOverlay(keyboard->getAnchorID(), keyboardProperties);8893 properties.setPosition(newPositionVec + keyboardLocalOffset);
8894 properties.setRotation(keyboardOrientation);
8895 entityScriptingInterface->editEntity(DependencyManager::get<Keyboard>()->getAnchorID(), properties);
8896 }
8725 }8897 }
8726}8898}
8727 8899
@@ -8738,10 +8910,9 @@ void Application::onDismissedLoginDialog() { · 10 unmodified lines
8738 loginDialogPoppedUp.set(false);8910 loginDialogPoppedUp.set(false);
8739 auto keyboard = DependencyManager::get<Keyboard>().data();8911 auto keyboard = DependencyManager::get<Keyboard>().data();
8740 keyboard->setResetKeyboardPositionOnRaise(true);8912 keyboard->setResetKeyboardPositionOnRaise(true);
8741 if (!_loginDialogOverlayID.isNull()) {8913 if (!_loginDialogID.isNull()) {
8742 // deleting overlay.8914 DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_loginDialogID);
8743 getOverlays().deleteOverlay(_loginDialogOverlayID);8915 _loginDialogID = QUuid();
8744 _loginDialogOverlayID = OverlayID();
8745 _loginStateManager.tearDown();8916 _loginStateManager.tearDown();
8746 }8917 }
8747 resumeAfterLoginDialogActionTaken();8918 resumeAfterLoginDialogActionTaken();
@@ -8907,12 +9078,12 @@ void Application::updateSystemTabletMode() { · 159 unmodified lines
8907 }9078 }
8908}9079}
8909 9080
8910OverlayID Application::getTabletScreenID() const {9081QUuid Application::getTabletScreenID() const {
8911 auto HMD = DependencyManager::get<HMDScriptingInterface>();9082 auto HMD = DependencyManager::get<HMDScriptingInterface>();
8912 return HMD->getCurrentTabletScreenID();9083 return HMD->getCurrentTabletScreenID();
8913}9084}
8914 9085
8915OverlayID Application::getTabletHomeButtonID() const {9086QUuid Application::getTabletHomeButtonID() const {
8916 auto HMD = DependencyManager::get<HMDScriptingInterface>();9087 auto HMD = DependencyManager::get<HMDScriptingInterface>();
8917 return HMD->getCurrentHomeButtonID();9088 return HMD->getCurrentHomeButtonID();
8918}9089}
@@ -8923,7 +9094,7 @@ QUuid Application::getTabletFrameID() const { · 4 unmodified lines
8923}9094}
8924 9095
8925QVector<QUuid> Application::getTabletIDs() const {9096QVector<QUuid> Application::getTabletIDs() const {
8926 // Most important overlays first.9097 // Most important first.
8927 QVector<QUuid> result;9098 QVector<QUuid> result;
8928 auto HMD = DependencyManager::get<HMDScriptingInterface>();9099 auto HMD = DependencyManager::get<HMDScriptingInterface>();
8929 result << HMD->getCurrentTabletScreenID();9100 result << HMD->getCurrentTabletScreenID();