Showing the changes to interface/src/Application.cpp (1 of 1002 files). Show all
Unified · Split
| @@ -102,7 +102,7 @@ · 101 unmodified lines | ||
| 102 | 102 | #include <MessagesClient.h> |
| 103 | 103 | #include <hfm/ModelFormatRegistry.h> |
| 104 | 104 | #include <model-networking/ModelCacheScriptingInterface.h> |
| 105 | −#include <model-networking/TextureCacheScriptingInterface.h> | |
| 105 | +#include <material-networking/TextureCacheScriptingInterface.h> | |
| 106 | 106 | #include <ModelEntityItem.h> |
| 107 | 107 | #include <NetworkAccessManager.h> |
| 108 | 108 | #include <NetworkingConstants.h> |
| @@ -120,6 +120,7 @@ · 11 unmodified lines | ||
| 120 | 120 | #include <plugins/PluginManager.h> |
| 121 | 121 | #include <plugins/PluginUtils.h> |
| 122 | 122 | #include <plugins/SteamClientPlugin.h> |
| 123 | +#include <plugins/OculusPlatformPlugin.h> | |
| 123 | 124 | #include <plugins/InputConfiguration.h> |
| 124 | 125 | #include <RecordingScriptingInterface.h> |
| 125 | 126 | #include <render/EngineStats.h> |
| @@ -151,7 +152,9 @@ · 25 unmodified lines | ||
| 151 | 152 | #include <trackers/EyeTracker.h> |
| 152 | 153 | #include <avatars-renderer/ScriptAvatar.h> |
| 153 | 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 | 158 | #include "recording/ClipCache.h" |
| 156 | 159 | |
| 157 | 160 | #include "AudioClient.h" |
| @@ -159,6 +162,7 @@ · 1 unmodified line | ||
| 159 | 162 | #include "avatar/AvatarManager.h" |
| 160 | 163 | #include "avatar/MyHead.h" |
| 161 | 164 | #include "avatar/AvatarPackager.h" |
| 165 | +#include "avatar/MyCharacterController.h" | |
| 162 | 166 | #include "CrashRecoveryHandler.h" |
| 163 | 167 | #include "CrashHandler.h" |
| 164 | 168 | #include "devices/DdeFaceTracker.h" |
| @@ -195,15 +199,12 @@ · 30 unmodified lines | ||
| 195 | 199 | #include "ui/AvatarInputs.h" |
| 196 | 200 | #include "ui/DialogsManager.h" |
| 197 | 201 | #include "ui/LoginDialog.h" |
| 198 | −#include "ui/overlays/Cube3DOverlay.h" | |
| 199 | −#include "ui/overlays/Web3DOverlay.h" | |
| 200 | 202 | #include "ui/Snapshot.h" |
| 201 | 203 | #include "ui/SnapshotAnimated.h" |
| 202 | 204 | #include "ui/StandAloneJSConsole.h" |
| 203 | 205 | #include "ui/Stats.h" |
| 204 | 206 | #include "ui/AnimStats.h" |
| 205 | 207 | #include "ui/UpdateDialog.h" |
| 206 | −#include "ui/overlays/Overlays.h" | |
| 207 | 208 | #include "ui/DomainConnectionModel.h" |
| 208 | 209 | #include "ui/Keyboard.h" |
| 209 | 210 | #include "Util.h" |
| @@ -232,6 +233,7 @@ · 22 unmodified lines | ||
| 232 | 233 | #include "commerce/Ledger.h" |
| 233 | 234 | #include "commerce/Wallet.h" |
| 234 | 235 | #include "commerce/QmlCommerce.h" |
| 236 | +#include "commerce/QmlMarketplace.h" | |
| 235 | 237 | #include "ResourceRequestObserver.h" |
| 236 | 238 | |
| 237 | 239 | #include "webbrowser/WebBrowserSuggestionsEngine.h" |
| @@ -347,6 +349,8 @@ static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin"; · 109 unmodified lines | ||
| 347 | 349 | static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; |
| 348 | 350 | static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn"; |
| 349 | 351 | |
| 352 | +static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; | |
| 353 | + | |
| 350 | 354 | #if defined(Q_OS_ANDROID) |
| 351 | 355 | static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt"; |
| 352 | 356 | #endif |
| @@ -599,8 +603,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt · 246 unmodified lines | ||
| 599 | 603 | __android_log_write(ANDROID_LOG_FATAL,"Interface",local); |
| 600 | 604 | abort(); |
| 601 | 605 | } |
| 602 | −#endif | |
| 606 | +#else | |
| 603 | 607 | qApp->getLogger()->addMessage(qPrintable(logMessage)); |
| 608 | +#endif | |
| 604 | 609 | } |
| 605 | 610 | } |
| 606 | 611 | |
| @@ -618,7 +623,7 @@ public: · 11 unmodified lines | ||
| 618 | 623 | case NestableType::Entity: |
| 619 | 624 | return getEntityModelProvider(static_cast<EntityItemID>(uuid)); |
| 620 | 625 | case NestableType::Overlay: |
| 621 | − return getOverlayModelProvider(static_cast<OverlayID>(uuid)); | |
| 626 | + return nullptr; | |
| 622 | 627 | case NestableType::Avatar: |
| 623 | 628 | return getAvatarModelProvider(uuid); |
| 624 | 629 | } |
| @@ -642,22 +647,6 @@ private: · 17 unmodified lines | ||
| 642 | 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 | 650 | scriptable::ModelProviderPointer getAvatarModelProvider(QUuid sessionUUID) { |
| 662 | 651 | scriptable::ModelProviderPointer provider; |
| 663 | 652 | auto avatarManager = DependencyManager::get<AvatarManager>(); |
| @@ -762,6 +751,11 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 98 unmodified lines | ||
| 762 | 751 | static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset"; |
| 763 | 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 | 759 | // Ignore any previous crashes if running from command line with a test script. |
| 766 | 760 | bool inTestMode { false }; |
| 767 | 761 | for (int i = 0; i < argc; ++i) { |
| @@ -803,6 +797,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 35 unmodified lines | ||
| 803 | 797 | if (auto steamClient = pluginManager->getSteamClientPlugin()) { |
| 804 | 798 | steamClient->init(); |
| 805 | 799 | } |
| 800 | + if (auto oculusPlatform = pluginManager->getOculusPlatformPlugin()) { | |
| 801 | + oculusPlatform->init(); | |
| 802 | + } | |
| 806 | 803 | |
| 807 | 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 | 920 | DependencyManager::set<Wallet>(); |
| 924 | 921 | DependencyManager::set<WalletScriptingInterface>(); |
| 925 | 922 | DependencyManager::set<TTSScriptingInterface>(); |
| 923 | + DependencyManager::set<QmlCommerce>(); | |
| 926 | 924 | |
| 927 | 925 | DependencyManager::set<FadeEffect>(); |
| 928 | 926 | DependencyManager::set<ResourceRequestObserver>(); |
| @@ -937,9 +935,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 8 unmodified lines | ||
| 937 | 935 | // FIXME move to header, or better yet, design some kind of UI manager |
| 938 | 936 | // to take care of highlighting keyboard focused items, rather than |
| 939 | 937 | // continuing to overburden Application.cpp |
| 940 | −std::shared_ptr<Cube3DOverlay> _keyboardFocusHighlight{ nullptr }; | |
| 941 | −OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID }; | |
| 942 | − | |
| 938 | +QUuid _keyboardFocusHighlightID; | |
| 943 | 939 | |
| 944 | 940 | OffscreenGLCanvas* _qmlShareContext { nullptr }; |
| 945 | 941 | |
| @@ -980,7 +976,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 34 unmodified lines | ||
| 980 | 976 | QApplication(argc, argv), |
| 981 | 977 | _window(new MainWindow(desktop())), |
| 982 | 978 | _sessionRunTimer(startupTimer), |
| 979 | +#ifndef Q_OS_ANDROID | |
| 983 | 980 | _logger(new FileLogger(this)), |
| 981 | +#endif | |
| 984 | 982 | _previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)), |
| 985 | 983 | _entitySimulation(new PhysicalEntitySimulation()), |
| 986 | 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 | 1113 | auto accountManager = DependencyManager::get<AccountManager>(); |
| 1116 | 1114 | |
| 1115 | +#ifndef Q_OS_ANDROID | |
| 1117 | 1116 | _logger->setSessionID(accountManager->getSessionID()); |
| 1117 | +#endif | |
| 1118 | 1118 | |
| 1119 | 1119 | setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString()); |
| 1120 | 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 | 1135 | qCDebug(interfaceapp) << "[VERSION] We will use DEVELOPMENT global services."; |
| 1136 | 1136 | #endif |
| 1137 | 1137 | |
| 1138 | − // set the OCULUS_STORE property so the oculus plugin can know if we ran from the Oculus Store | |
| 1139 | − static const QString OCULUS_STORE_ARG = "--oculus-store"; | |
| 1140 | − bool isStore = arguments().indexOf(OCULUS_STORE_ARG) != -1; | |
| 1141 | − setProperty(hifi::properties::OCULUS_STORE, isStore); | |
| 1138 | + bool isStore = property(hifi::properties::OCULUS_STORE).toBool(); | |
| 1139 | + | |
| 1142 | 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 | 1142 | updateHeartbeat(); |
| @@ -1204,9 +1202,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 59 unmodified lines | ||
| 1204 | 1202 | connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle())); |
| 1205 | 1203 | connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle())); |
| 1206 | 1204 | connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() { |
| 1207 | − getOverlays().deleteOverlay(getTabletScreenID()); | |
| 1208 | − getOverlays().deleteOverlay(getTabletHomeButtonID()); | |
| 1209 | − getOverlays().deleteOverlay(getTabletFrameID()); | |
| 1205 | + auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); | |
| 1206 | + if (tabletScriptingInterface) { | |
| 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 | 1213 | _failedToConnectToEntityServer = false; |
| 1211 | 1214 | }); |
| 1212 | 1215 | |
| @@ -1296,10 +1299,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 83 unmodified lines | ||
| 1296 | 1299 | if (isHMDMode()) { |
| 1297 | 1300 | emit loginDialogFocusDisabled(); |
| 1298 | 1301 | dialogsManager->hideLoginDialog(); |
| 1299 | − createLoginDialogOverlay(); | |
| 1302 | + createLoginDialog(); | |
| 1300 | 1303 | } else { |
| 1301 | − getOverlays().deleteOverlay(_loginDialogOverlayID); | |
| 1302 | − _loginDialogOverlayID = OverlayID(); | |
| 1304 | + DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_loginDialogID); | |
| 1305 | + _loginDialogID = QUuid(); | |
| 1303 | 1306 | _loginStateManager.tearDown(); |
| 1304 | 1307 | dialogsManager->showLoginDialog(); |
| 1305 | 1308 | emit loginDialogFocusEnabled(); |
| @@ -1896,66 +1899,56 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 590 unmodified lines | ||
| 1896 | 1899 | SpacemouseManager::getInstance().init(); |
| 1897 | 1900 | #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 it | |
| 1900 | − auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | |
| 1901 | − connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, | |
| 1902 | − [this](const EntityItemID& entityItemID, const PointerEvent& event) { | |
| 1902 | + // If the user clicks on an object, we will check that it's a web surface, and if so, set the focus to it | |
| 1903 | + auto pointerManager = DependencyManager::get<PointerManager>(); | |
| 1904 | + auto keyboardFocusOperator = [this](const QUuid& id, const PointerEvent& event) { | |
| 1903 | 1905 | if (event.shouldFocus()) { |
| 1904 | − if (getEntities()->wantsKeyboardFocus(entityItemID)) { | |
| 1905 | − setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); | |
| 1906 | − setKeyboardFocusEntity(entityItemID); | |
| 1907 | − } else { | |
| 1906 | + auto keyboard = DependencyManager::get<Keyboard>(); | |
| 1907 | + if (getEntities()->wantsKeyboardFocus(id)) { | |
| 1908 | + setKeyboardFocusEntity(id); | |
| 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 | 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 | 1919 | if (entityItemID == _keyboardFocusedEntity.get()) { |
| 1915 | 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 | 1925 | if (_aboutToQuit) { |
| 1921 | 1926 | return false; |
| 1922 | 1927 | } |
| 1923 | 1928 | |
| 1924 | − // try to find the renderable | |
| 1925 | 1929 | auto renderable = getEntities()->renderableForEntityId(entityID); |
| 1926 | 1930 | if (renderable) { |
| 1927 | 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 | 1932 | return true; |
| 1935 | 1933 | } |
| 1934 | + | |
| 1936 | 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 | 1938 | if (_aboutToQuit) { |
| 1940 | 1939 | return false; |
| 1941 | 1940 | } |
| 1942 | 1941 | |
| 1943 | − // try to find the renderable | |
| 1944 | 1942 | auto renderable = getEntities()->renderableForEntityId(entityID); |
| 1945 | 1943 | if (renderable) { |
| 1946 | 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 | 1945 | return true; |
| 1954 | 1946 | } |
| 1947 | + | |
| 1955 | 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 | 1952 | auto avatarManager = DependencyManager::get<AvatarManager>(); |
| 1960 | 1953 | auto avatar = avatarManager->getAvatarBySessionID(avatarID); |
| 1961 | 1954 | if (avatar) { |
| @@ -1964,7 +1957,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 2 unmodified lines | ||
| 1964 | 1957 | } |
| 1965 | 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 | 1961 | auto avatarManager = DependencyManager::get<AvatarManager>(); |
| 1969 | 1962 | auto avatar = avatarManager->getAvatarBySessionID(avatarID); |
| 1970 | 1963 | if (avatar) { |
| @@ -1974,33 +1967,25 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 3 unmodified lines | ||
| 1974 | 1967 | return false; |
| 1975 | 1968 | }); |
| 1976 | 1969 | |
| 1977 | − EntityTree::setAddMaterialToOverlayOperator([this](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) { | |
| 1978 | − auto overlay = _overlays.getOverlay(overlayID); | |
| 1979 | − if (overlay) { | |
| 1980 | − overlay->addMaterial(material, parentMaterialName); | |
| 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; | |
| 1970 | + EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* { | |
| 1971 | + auto entities = getEntities(); | |
| 1972 | + if (auto entity = entities->renderableForEntityId(id)) { | |
| 1973 | + return qobject_cast<QObject*>(entity.get()); | |
| 1990 | 1974 | } |
| 1991 | − return false; | |
| 1975 | + return nullptr; | |
| 1992 | 1976 | }); |
| 1993 | 1977 | |
| 1994 | − // Keyboard focus handling for Web overlays. | |
| 1995 | − auto overlays = &(qApp->getOverlays()); | |
| 1996 | − connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) { | |
| 1997 | − if (overlayID == _keyboardFocusedOverlay.get()) { | |
| 1998 | − setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); | |
| 1978 | + EntityTree::setTextSizeOperator([this](const QUuid& id, const QString& text) { | |
| 1979 | + auto entities = getEntities(); | |
| 1980 | + if (auto entity = entities->renderableForEntityId(id)) { | |
| 1981 | + if (auto renderable = std::dynamic_pointer_cast<render::entities::TextEntityRenderer>(entity)) { | |
| 1982 | + return renderable->textSize(text); | |
| 1983 | + } | |
| 1999 | 1984 | } |
| 1985 | + return QSizeF(0.0f, 0.0f); | |
| 2000 | 1986 | }); |
| 2001 | 1987 | |
| 2002 | 1988 | connect(this, &Application::aboutToQuit, [this]() { |
| 2003 | − setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); | |
| 2004 | 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 | 2196 | || ((rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose)); |
| 2212 | 2197 | lastLeftHandPose = leftHandPose; |
| 2213 | 2198 | lastRightHandPose = rightHandPose; |
| 2214 | − properties["avatar_identity_requests_sent"] = DependencyManager::get<AvatarManager>()->getIdentityRequestsSent(); | |
| 2215 | 2199 | |
| 2216 | 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 | 2281 | // 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 | 2284 | mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>(); |
| 2301 | 2285 | mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE); |
| 2302 | 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 | 2306 | DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value); |
| 2323 | 2307 | }); |
| 2324 | 2308 | |
| 2325 | − EntityTreeRenderer::setGetAvatarUpOperator([] { | |
| 2326 | − return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP; | |
| 2309 | + EntityItem::setBillboardRotationOperator([this](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode) { | |
| 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 | 2405 | // Preload Tablet sounds |
| 2406 | + DependencyManager::get<EntityScriptingInterface>()->setEntityTree(qApp->getEntities()->getTree()); | |
| 2330 | 2407 | DependencyManager::get<TabletScriptingInterface>()->preloadSounds(); |
| 2331 | 2408 | DependencyManager::get<Keyboard>()->createKeyboard(); |
| 2332 | 2409 | |
| @@ -2352,7 +2429,6 @@ void Application::updateVerboseLogging() { · 19 unmodified lines | ||
| 2352 | 2429 | bool enable = menu->isOptionChecked(MenuOption::VerboseLogging); |
| 2353 | 2430 | |
| 2354 | 2431 | QString rules = |
| 2355 | − "hifi.*.debug=%1\n" | |
| 2356 | 2432 | "hifi.*.info=%1\n" |
| 2357 | 2433 | "hifi.audio-stream.debug=false\n" |
| 2358 | 2434 | "hifi.audio-stream.info=false"; |
| @@ -2535,11 +2611,10 @@ void Application::cleanupBeforeQuit() { · 176 unmodified lines | ||
| 2535 | 2611 | _applicationStateDevice.reset(); |
| 2536 | 2612 | |
| 2537 | 2613 | { |
| 2538 | − if (_keyboardFocusHighlightID != UNKNOWN_OVERLAY_ID) { | |
| 2539 | − getOverlays().deleteOverlay(_keyboardFocusHighlightID); | |
| 2540 | − _keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID; | |
| 2614 | + if (_keyboardFocusHighlightID != UNKNOWN_ENTITY_ID) { | |
| 2615 | + DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_keyboardFocusHighlightID); | |
| 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 | 2684 | DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface |
| 2610 | 2685 | |
| 2611 | 2686 | // stop QML |
| 2687 | + DependencyManager::destroy<QmlCommerce>(); | |
| 2612 | 2688 | DependencyManager::destroy<TabletScriptingInterface>(); |
| 2613 | 2689 | DependencyManager::destroy<ToolbarScriptingInterface>(); |
| 2614 | 2690 | DependencyManager::destroy<OffscreenUi>(); |
| @@ -2648,7 +2724,14 @@ Application::~Application() { · 33 unmodified lines | ||
| 2648 | 2724 | avatarManager->handleProcessedPhysicsTransaction(transaction); |
| 2649 | 2725 | |
| 2650 | 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 | 2735 | _physicsEngine->setCharacterController(nullptr); |
| 2653 | 2736 | |
| 2654 | 2737 | // the _shapeManager should have zero references |
| @@ -2671,6 +2754,11 @@ Application::~Application() { · 16 unmodified lines | ||
| 2671 | 2754 | if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { |
| 2672 | 2755 | steamClient->shutdown(); |
| 2673 | 2756 | } |
| 2757 | + | |
| 2758 | + if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 2759 | + oculusPlatform->shutdown(); | |
| 2760 | + } | |
| 2761 | + | |
| 2674 | 2762 | DependencyManager::destroy<PluginManager>(); |
| 2675 | 2763 | |
| 2676 | 2764 | DependencyManager::destroy<CompositorHelper>(); // must be destroyed before the FramebufferCache |
| @@ -2897,7 +2985,7 @@ void Application::initializeUi() { · 220 unmodified lines | ||
| 2897 | 2985 | Tooltip::registerType(); |
| 2898 | 2986 | UpdateDialog::registerType(); |
| 2899 | 2987 | QmlContextCallback commerceCallback = [](QQmlContext* context) { |
| 2900 | − context->setContextProperty("Commerce", new QmlCommerce()); | |
| 2988 | + context->setContextProperty("Commerce", DependencyManager::get<QmlCommerce>().data()); | |
| 2901 | 2989 | }; |
| 2902 | 2990 | OffscreenQmlSurface::addWhitelistContextHandler({ |
| 2903 | 2991 | QUrl{ "hifi/commerce/checkout/Checkout.qml" }, |
| @@ -2922,7 +3010,24 @@ void Application::initializeUi() { · 18 unmodified lines | ||
| 2922 | 3010 | QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" }, |
| 2923 | 3011 | QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" }, |
| 2924 | 3012 | QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" }, |
| 3013 | + QUrl{ "hifi/tablet/TabletMenu.qml" }, | |
| 3014 | + QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, | |
| 2925 | 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 | 3031 | QmlContextCallback ttsCallback = [](QQmlContext* context) { |
| 2927 | 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 | 3120 | #if !defined(DISABLE_QML) |
| 3016 | − // Pre-create a couple of Web3D overlays to speed up tablet UI | |
| 3121 | + // Pre-create a couple of offscreen surfaces to speed up tablet UI | |
| 3017 | 3122 | auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>(); |
| 3018 | 3123 | offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) { |
| 3019 | 3124 | if (rootObject == TabletScriptingInterface::QML) { |
| @@ -3025,7 +3130,7 @@ void Application::initializeUi() { · 5 unmodified lines | ||
| 3025 | 3130 | }); |
| 3026 | 3131 | |
| 3027 | 3132 | offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); |
| 3028 | − offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); | |
| 3133 | + offscreenSurfaceCache->reserve(render::entities::WebEntityRenderer::QML, 2); | |
| 3029 | 3134 | #endif |
| 3030 | 3135 | |
| 3031 | 3136 | flushMenuUpdates(); |
| @@ -3165,6 +3270,61 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { · 133 unmodified lines | ||
| 3165 | 3270 | #endif |
| 3166 | 3271 | } |
| 3167 | 3272 | |
| 3273 | +void 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 | + | |
| 3168 | 3328 | void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { |
| 3169 | 3329 | PROFILE_RANGE(render, __FUNCTION__); |
| 3170 | 3330 | PerformanceTimer perfTimer("updateCamera"); |
| @@ -3421,8 +3581,10 @@ void Application::resizeGL() { · 250 unmodified lines | ||
| 3421 | 3581 | auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); |
| 3422 | 3582 | assert(renderConfig); |
| 3423 | 3583 | auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask"); |
| 3424 | − assert(mainView); | |
| 3425 | − mainView->setProperty("resolutionScale", renderResolutionScale); | |
| 3584 | + // mainView can be null if we're rendering in forward mode | |
| 3585 | + if (mainView) { | |
| 3586 | + mainView->setProperty("resolutionScale", renderResolutionScale); | |
| 3587 | + } | |
| 3426 | 3588 | displayPlugin->setRenderResolutionScale(renderResolutionScale); |
| 3427 | 3589 | } |
| 3428 | 3590 | |
| @@ -3677,8 +3839,8 @@ static inline bool isKeyEvent(QEvent::Type type) { · 248 unmodified lines | ||
| 3677 | 3839 | return type == QEvent::KeyPress || type == QEvent::KeyRelease; |
| 3678 | 3840 | } |
| 3679 | 3841 | |
| 3680 | −bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) { | |
| 3681 | − if (!_keyboardFocusedEntity.get().isInvalidID()) { | |
| 3842 | +bool Application::handleKeyEventForFocusedEntity(QEvent* event) { | |
| 3843 | + if (_keyboardFocusedEntity.get() != UNKNOWN_ENTITY_ID) { | |
| 3682 | 3844 | switch (event->type()) { |
| 3683 | 3845 | case QEvent::KeyPress: |
| 3684 | 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 | 3864 | return false; |
| 3725 | 3865 | } |
| 3726 | 3866 | |
| @@ -3763,8 +3903,8 @@ bool Application::event(QEvent* event) { · 36 unmodified lines | ||
| 3763 | 3903 | return false; |
| 3764 | 3904 | } |
| 3765 | 3905 | |
| 3766 | − // Allow focused Entities and Overlays to handle keyboard input | |
| 3767 | − if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event)) { | |
| 3906 | + // Allow focused Entities to handle keyboard input | |
| 3907 | + if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntity(event)) { | |
| 3768 | 3908 | return true; |
| 3769 | 3909 | } |
| 3770 | 3910 | |
| @@ -3970,6 +4110,19 @@ void Application::keyPressEvent(QKeyEvent* event) { · 199 unmodified lines | ||
| 3970 | 4110 | } |
| 3971 | 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 | 4126 | case Qt::Key_X: |
| 3974 | 4127 | if (isShifted && isMeta) { |
| 3975 | 4128 | auto offscreenUi = getOffscreenUI(); |
| @@ -4041,7 +4194,9 @@ void Application::keyPressEvent(QKeyEvent* event) { · 65 unmodified lines | ||
| 4041 | 4194 | if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) { |
| 4042 | 4195 | AudioInjectorOptions options; |
| 4043 | 4196 | options.localOnly = true; |
| 4197 | + options.positionSet = false; // system sound | |
| 4044 | 4198 | options.stereo = true; |
| 4199 | + | |
| 4045 | 4200 | Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true }; |
| 4046 | 4201 | Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true }; |
| 4047 | 4202 | if (notificationSounds.get() && notificationSoundSnapshot.get()) { |
| @@ -4230,9 +4385,9 @@ void Application::mouseMoveEvent(QMouseEvent* event) { · 182 unmodified lines | ||
| 4230 | 4385 | buttons, event->modifiers()); |
| 4231 | 4386 | |
| 4232 | 4387 | if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || |
| 4233 | − getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_OVERLAY_ID) { | |
| 4234 | − getOverlays().mouseMoveEvent(&mappedEvent); | |
| 4388 | + getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) { | |
| 4235 | 4389 | getEntities()->mouseMoveEvent(&mappedEvent); |
| 4390 | + getOverlays().mouseMoveEvent(&mappedEvent); | |
| 4236 | 4391 | } |
| 4237 | 4392 | |
| 4238 | 4393 | _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts |
| @@ -4264,15 +4419,16 @@ void Application::mousePressEvent(QMouseEvent* event) { · 25 unmodified lines | ||
| 4264 | 4419 | #else |
| 4265 | 4420 | QPointF transformedPos; |
| 4266 | 4421 | #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 | 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 | 4433 | _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts |
| 4278 | 4434 | |
| @@ -4312,10 +4468,10 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { · 33 unmodified lines | ||
| 4312 | 4468 | event->screenPos(), event->button(), |
| 4313 | 4469 | event->buttons(), event->modifiers()); |
| 4314 | 4470 | |
| 4315 | − getOverlays().mouseDoublePressEvent(&mappedEvent); | |
| 4316 | 4471 | if (!_controllerScriptingInterface->areEntityClicksCaptured()) { |
| 4317 | 4472 | getEntities()->mouseDoublePressEvent(&mappedEvent); |
| 4318 | 4473 | } |
| 4474 | + getOverlays().mouseDoublePressEvent(&mappedEvent); | |
| 4319 | 4475 | |
| 4320 | 4476 | // if one of our scripts have asked to capture this event, then stop processing it |
| 4321 | 4477 | if (_controllerScriptingInterface->isMouseCaptured()) { |
| @@ -4339,8 +4495,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { · 17 unmodified lines | ||
| 4339 | 4495 | event->screenPos(), event->button(), |
| 4340 | 4496 | event->buttons(), event->modifiers()); |
| 4341 | 4497 | |
| 4342 | − getOverlays().mouseReleaseEvent(&mappedEvent); | |
| 4343 | 4498 | getEntities()->mouseReleaseEvent(&mappedEvent); |
| 4499 | + getOverlays().mouseReleaseEvent(&mappedEvent); | |
| 4344 | 4500 | |
| 4345 | 4501 | _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts |
| 4346 | 4502 | |
| @@ -4751,6 +4907,10 @@ void Application::idle() { · 404 unmodified lines | ||
| 4751 | 4907 | steamClient->runCallbacks(); |
| 4752 | 4908 | } |
| 4753 | 4909 | |
| 4910 | + if (auto oculusPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 4911 | + oculusPlugin->handleOVREvents(); | |
| 4912 | + } | |
| 4913 | + | |
| 4754 | 4914 | float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND; |
| 4755 | 4915 | _lastTimeUpdated.start(); |
| 4756 | 4916 | |
| @@ -4784,7 +4944,11 @@ void Application::idle() { · 27 unmodified lines | ||
| 4784 | 4944 | // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing |
| 4785 | 4945 | // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing |
| 4786 | 4946 | // details normally. |
| 4947 | +#ifdef Q_OS_ANDROID | |
| 4948 | + bool showWarnings = false; | |
| 4949 | +#else | |
| 4787 | 4950 | bool showWarnings = getLogger()->extraDebugging(); |
| 4951 | +#endif | |
| 4788 | 4952 | PerformanceWarning warn(showWarnings, "idle()"); |
| 4789 | 4953 | |
| 4790 | 4954 | { |
| @@ -4798,31 +4962,19 @@ void Application::idle() { · 7 unmodified lines | ||
| 4798 | 4962 | update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); |
| 4799 | 4963 | } |
| 4800 | 4964 | |
| 4801 | − | |
| 4802 | − // Update focus highlight for entity or overlay. | |
| 4803 | − { | |
| 4804 | − if (!_keyboardFocusedEntity.get().isInvalidID() || _keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) { | |
| 4965 | + { // Update keyboard focus highlight | |
| 4966 | + if (!_keyboardFocusedEntity.get().isInvalidID()) { | |
| 4805 | 4967 | const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus |
| 4806 | 4968 | quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; |
| 4807 | 4969 | if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { |
| 4808 | 4970 | setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); |
| 4809 | − setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); | |
| 4810 | 4971 | } else { |
| 4811 | − // update position of highlight overlay | |
| 4812 | − if (!_keyboardFocusedEntity.get().isInvalidID()) { | |
| 4813 | − auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get()); | |
| 4814 | − if (entity && _keyboardFocusHighlight) { | |
| 4815 | − _keyboardFocusHighlight->setWorldOrientation(entity->getWorldOrientation()); | |
| 4816 | − _keyboardFocusHighlight->setWorldPosition(entity->getWorldPosition()); | |
| 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 | − } | |
| 4972 | + if (auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get())) { | |
| 4973 | + EntityItemProperties properties; | |
| 4974 | + properties.setPosition(entity->getWorldPosition()); | |
| 4975 | + properties.setRotation(entity->getWorldOrientation()); | |
| 4976 | + properties.setDimensions(entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); | |
| 4977 | + DependencyManager::get<EntityScriptingInterface>()->editEntity(_keyboardFocusHighlightID, properties); | |
| 4826 | 4978 | } |
| 4827 | 4979 | } |
| 4828 | 4980 | } |
| @@ -5620,118 +5772,80 @@ void Application::rotationModeChanged() const { · 791 unmodified lines | ||
| 5620 | 5772 | } |
| 5621 | 5773 | |
| 5622 | 5774 | void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) { |
| 5623 | − // Create focus | |
| 5624 | 5775 | if (qApp->getLoginDialogPoppedUp()) { |
| 5625 | 5776 | return; |
| 5626 | 5777 | } |
| 5627 | − if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { | |
| 5628 | − _keyboardFocusHighlight = std::make_shared<Cube3DOverlay>(); | |
| 5629 | − _keyboardFocusHighlight->setAlpha(1.0f); | |
| 5630 | − _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 }); | |
| 5631 | − _keyboardFocusHighlight->setIsSolid(false); | |
| 5632 | − _keyboardFocusHighlight->setPulseMin(0.5); | |
| 5633 | − _keyboardFocusHighlight->setPulseMax(1.0); | |
| 5634 | − _keyboardFocusHighlight->setColorPulse(1.0); | |
| 5635 | − _keyboardFocusHighlight->setIgnorePickIntersection(true); | |
| 5636 | − _keyboardFocusHighlight->setDrawInFront(false); | |
| 5637 | − _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight); | |
| 5778 | + | |
| 5779 | + auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | |
| 5780 | + if (_keyboardFocusHighlightID == UNKNOWN_ENTITY_ID || !entityScriptingInterface->isAddedEntity(_keyboardFocusHighlightID)) { | |
| 5781 | + EntityItemProperties properties; | |
| 5782 | + properties.setType(EntityTypes::Box); | |
| 5783 | + properties.setAlpha(1.0f); | |
| 5784 | + properties.setColor({ 0xFF, 0xEF, 0x00 }); | |
| 5785 | + properties.setPrimitiveMode(PrimitiveMode::LINES); | |
| 5786 | + properties.getPulse().setMin(0.5); | |
| 5787 | + properties.getPulse().setMax(1.0f); | |
| 5788 | + properties.getPulse().setColorMode(PulseMode::IN_PHASE); | |
| 5789 | + properties.setIgnorePickIntersection(true); | |
| 5790 | + _keyboardFocusHighlightID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); | |
| 5638 | 5791 | } |
| 5639 | 5792 | |
| 5640 | 5793 | // Position focus |
| 5641 | − _keyboardFocusHighlight->setWorldOrientation(rotation); | |
| 5642 | − _keyboardFocusHighlight->setWorldPosition(position); | |
| 5643 | − _keyboardFocusHighlight->setDimensions(dimensions); | |
| 5644 | − _keyboardFocusHighlight->setVisible(true); | |
| 5794 | + EntityItemProperties properties; | |
| 5795 | + properties.setPosition(position); | |
| 5796 | + properties.setRotation(rotation); | |
| 5797 | + properties.setDimensions(dimensions); | |
| 5798 | + properties.setVisible(true); | |
| 5799 | + entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); | |
| 5645 | 5800 | } |
| 5646 | 5801 | |
| 5647 | 5802 | QUuid Application::getKeyboardFocusEntity() const { |
| 5648 | 5803 | return _keyboardFocusedEntity.get(); |
| 5649 | 5804 | } |
| 5650 | 5805 | |
| 5651 | −static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; | |
| 5652 | − | |
| 5653 | −void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { | |
| 5654 | − if (qApp->getLoginDialogPoppedUp()) { | |
| 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 | − | |
| 5691 | −OverlayID Application::getKeyboardFocusOverlay() { | |
| 5692 | − return _keyboardFocusedOverlay.get(); | |
| 5693 | −} | |
| 5694 | − | |
| 5695 | −void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) { | |
| 5696 | − if (overlayID != _keyboardFocusedOverlay.get()) { | |
| 5697 | − if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) { | |
| 5698 | − if (overlayID == _loginDialogOverlayID) { | |
| 5806 | +void Application::setKeyboardFocusEntity(const QUuid& id) { | |
| 5807 | + if (_keyboardFocusedEntity.get() != id) { | |
| 5808 | + if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { | |
| 5809 | + if (id == _loginDialogID) { | |
| 5699 | 5810 | emit loginDialogFocusEnabled(); |
| 5700 | 5811 | } else { |
| 5701 | − // that's the only overlay we want in focus; | |
| 5812 | + // that's the only entity we want in focus; | |
| 5702 | 5813 | return; |
| 5703 | 5814 | } |
| 5704 | 5815 | } |
| 5705 | 5816 | |
| 5706 | − _keyboardFocusedOverlay.set(overlayID); | |
| 5707 | − | |
| 5708 | − if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) { | |
| 5709 | − _keyboardFocusHighlight->setVisible(false); | |
| 5710 | − } | |
| 5711 | − | |
| 5712 | − if (overlayID == UNKNOWN_OVERLAY_ID) { | |
| 5713 | − return; | |
| 5714 | − } | |
| 5817 | + _keyboardFocusedEntity.set(id); | |
| 5715 | 5818 | |
| 5716 | − auto overlayType = getOverlays().getOverlayType(overlayID); | |
| 5717 | − auto isVisible = getOverlays().getProperty(overlayID, "visible").value.toBool(); | |
| 5718 | − if (overlayType == Web3DOverlay::TYPE && isVisible) { | |
| 5719 | − auto overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(overlayID)); | |
| 5720 | − overlay->setProxyWindow(_window->windowHandle()); | |
| 5819 | + auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | |
| 5820 | + if (id != UNKNOWN_ENTITY_ID) { | |
| 5821 | + EntityPropertyFlags desiredProperties; | |
| 5822 | + desiredProperties += PROP_VISIBLE; | |
| 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()) { | |
| 5723 | − _keyboardMouseDevice->pluginFocusOutEvent(); | |
| 5724 | − } | |
| 5725 | − _lastAcceptedKeyPress = usecTimestampNow(); | |
| 5726 | − | |
| 5727 | − if (overlay->getProperty("showKeyboardFocusHighlight").toBool()) { | |
| 5728 | − auto size = overlay->getSize() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR; | |
| 5729 | − const float OVERLAY_DEPTH = 0.0105f; | |
| 5730 | − setKeyboardFocusHighlight(overlay->getWorldPosition(), overlay->getWorldOrientation(), glm::vec3(size.x, size.y, OVERLAY_DEPTH)); | |
| 5731 | − } else if (_keyboardFocusHighlight) { | |
| 5732 | − _keyboardFocusHighlight->setVisible(false); | |
| 5835 | + if (properties.getShowKeyboardFocusHighlight()) { | |
| 5836 | + if (auto entity = entities->getEntity(entityId)) { | |
| 5837 | + setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), | |
| 5838 | + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); | |
| 5839 | + return; | |
| 5840 | + } | |
| 5841 | + } | |
| 5842 | + } | |
| 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 | 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 | 6059 | controller::InputCalibrationData calibrationData = { |
| 5939 | 6060 | myAvatar->getSensorToWorldMatrix(), |
| 5940 | 6061 | createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()), |
| @@ -5948,7 +6069,8 @@ void Application::update(float deltaTime) { · 7 unmodified lines | ||
| 5948 | 6069 | myAvatar->getRightArmCalibrationMat(), |
| 5949 | 6070 | myAvatar->getLeftArmCalibrationMat(), |
| 5950 | 6071 | myAvatar->getRightHandCalibrationMat(), |
| 5951 | − myAvatar->getLeftHandCalibrationMat() | |
| 6072 | + myAvatar->getLeftHandCalibrationMat(), | |
| 6073 | + hmdAvatarAlignmentType | |
| 5952 | 6074 | }; |
| 5953 | 6075 | |
| 5954 | 6076 | InputPluginPointer keyboardMousePlugin; |
| @@ -6100,6 +6222,19 @@ void Application::update(float deltaTime) { · 145 unmodified lines | ||
| 6100 | 6222 | auto grabManager = DependencyManager::get<GrabManager>(); |
| 6101 | 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 | 6238 | QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>(); |
| 6104 | 6239 | |
| 6105 | 6240 | { |
| @@ -6113,36 +6248,57 @@ void Application::update(float deltaTime) { · 7 unmodified lines | ||
| 6113 | 6248 | PROFILE_RANGE(simulation_physics, "PrePhysics"); |
| 6114 | 6249 | PerformanceTimer perfTimer("prePhysics)"); |
| 6115 | 6250 | { |
| 6251 | + PROFILE_RANGE(simulation_physics, "RemoveEntities"); | |
| 6116 | 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 | 6257 | _entitySimulation->deleteObjectsRemovedFromPhysics(); |
| 6119 | 6258 | } |
| 6120 | 6259 | |
| 6121 | − VectorOfMotionStates motionStates; | |
| 6122 | − getEntities()->getTree()->withReadLock([&] { | |
| 6123 | − _entitySimulation->getObjectsToAddToPhysics(motionStates); | |
| 6124 | − _physicsEngine->addObjects(motionStates); | |
| 6125 | − | |
| 6126 | − }); | |
| 6127 | − getEntities()->getTree()->withReadLock([&] { | |
| 6128 | − _entitySimulation->getObjectsToChange(motionStates); | |
| 6129 | − VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); | |
| 6130 | − _entitySimulation->setObjectsToChange(stillNeedChange); | |
| 6131 | − }); | |
| 6260 | + { | |
| 6261 | + PROFILE_RANGE(simulation_physics, "AddEntities"); | |
| 6262 | + VectorOfMotionStates motionStates; | |
| 6263 | + getEntities()->getTree()->withReadLock([&] { | |
| 6264 | + _entitySimulation->getObjectsToAddToPhysics(motionStates); | |
| 6265 | + PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size()); | |
| 6266 | + _physicsEngine->addObjects(motionStates); | |
| 6267 | + }); | |
| 6268 | + } | |
| 6269 | + { | |
| 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 | 6279 | _entitySimulation->applyDynamicChanges(); |
| 6134 | 6280 | |
| 6135 | 6281 | t1 = std::chrono::high_resolution_clock::now(); |
| 6136 | 6282 | |
| 6137 | − PhysicsEngine::Transaction transaction; | |
| 6138 | − avatarManager->buildPhysicsTransaction(transaction); | |
| 6139 | − _physicsEngine->processTransaction(transaction); | |
| 6140 | − avatarManager->handleProcessedPhysicsTransaction(transaction); | |
| 6283 | + { | |
| 6284 | + PROFILE_RANGE(simulation_physics, "Avatars"); | |
| 6285 | + PhysicsEngine::Transaction 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(); | |
| 6143 | − _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { | |
| 6144 | − dynamic->prepareForPhysicsSimulation(); | |
| 6145 | − }); | |
| 6296 | + { | |
| 6297 | + PROFILE_RANGE(simulation_physics, "PrepareActions"); | |
| 6298 | + _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { | |
| 6299 | + dynamic->prepareForPhysicsSimulation(); | |
| 6300 | + }); | |
| 6301 | + } | |
| 6146 | 6302 | } |
| 6147 | 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 | 6402 | updateLOD(deltaTime); |
| 6247 | 6403 | |
| 6248 | − if (!_loginDialogOverlayID.isNull()) { | |
| 6249 | − _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogOverlayID); | |
| 6250 | − updateLoginDialogOverlayPosition(); | |
| 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(); | |
| 6404 | + if (!_loginDialogID.isNull()) { | |
| 6405 | + _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogID); | |
| 6406 | + updateLoginDialogPosition(); | |
| 6264 | 6407 | } |
| 6265 | 6408 | |
| 6266 | 6409 | { |
| @@ -6284,7 +6427,7 @@ void Application::update(float deltaTime) { · 17 unmodified lines | ||
| 6284 | 6427 | // TODO: Fix this by modeling the way the secondary camera works on how the main camera works |
| 6285 | 6428 | // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary |
| 6286 | 6429 | // camera should be. |
| 6287 | − // updateSecondaryCameraViewFrustum(); | |
| 6430 | + updateSecondaryCameraViewFrustum(); | |
| 6288 | 6431 | } |
| 6289 | 6432 | |
| 6290 | 6433 | quint64 now = usecTimestampNow(); |
| @@ -6843,17 +6986,19 @@ void Application::nodeActivated(SharedNodePointer node) { · 552 unmodified lines | ||
| 6843 | 6986 | |
| 6844 | 6987 | #if !defined(DISABLE_QML) |
| 6845 | 6988 | auto offscreenUi = getOffscreenUI(); |
| 6846 | − auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer") : nullptr; | |
| 6847 | 6989 | |
| 6848 | − if (assetDialog) { | |
| 6990 | + if (offscreenUi) { | |
| 6849 | 6991 | auto nodeList = DependencyManager::get<NodeList>(); |
| 6850 | 6992 | |
| 6851 | 6993 | if (nodeList->getThisNodeCanWriteAssets()) { |
| 6852 | 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 | 6999 | } else { |
| 6855 | 7000 | // 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 | 7004 | #endif |
| @@ -7026,7 +7171,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 166 unmodified lines | ||
| 7026 | 7171 | connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater); |
| 7027 | 7172 | |
| 7028 | 7173 | scriptEngine->registerGlobalObject("Overlays", &_overlays); |
| 7029 | − qScriptRegisterMetaType(scriptEngine.data(), OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); | |
| 7030 | 7174 | qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue, |
| 7031 | 7175 | RayToOverlayIntersectionResultFromScriptValue); |
| 7032 | 7176 | |
| @@ -7143,8 +7287,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 110 unmodified lines | ||
| 7143 | 7287 | scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance()); |
| 7144 | 7288 | scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data()); |
| 7145 | 7289 | |
| 7146 | − qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue); | |
| 7147 | − | |
| 7148 | 7290 | registerInteractiveWindowMetaType(scriptEngine.data()); |
| 7149 | 7291 | |
| 7150 | 7292 | auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>(); |
| @@ -8025,8 +8167,7 @@ void Application::openUrl(const QUrl& url) const { · 874 unmodified lines | ||
| 8025 | 8167 | if (url.scheme() == URL_SCHEME_HIFI) { |
| 8026 | 8168 | DependencyManager::get<AddressManager>()->handleLookupString(url.toString()); |
| 8027 | 8169 | } else if (url.scheme() == URL_SCHEME_HIFIAPP) { |
| 8028 | − QmlCommerce commerce; | |
| 8029 | − commerce.openSystemApp(url.path()); | |
| 8170 | + DependencyManager::get<QmlCommerce>()->openSystemApp(url.path()); | |
| 8030 | 8171 | } else { |
| 8031 | 8172 | // address manager did not handle - ask QDesktopServices to handle |
| 8032 | 8173 | QDesktopServices::openUrl(url); |
| @@ -8112,7 +8253,18 @@ void Application::toggleLogDialog() { · 79 unmodified lines | ||
| 8112 | 8253 | return; |
| 8113 | 8254 | } |
| 8114 | 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 | 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 | 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 | + | |
| 8125 | 8290 | void Application::toggleEntityScriptServerLogDialog() { |
| 8126 | 8291 | if (! _entityScriptServerLogDialog) { |
| 8127 | 8292 | _entityScriptServerLogDialog = new EntityScriptServerLogDialog(nullptr); |
| @@ -8643,45 +8808,47 @@ void Application::setShowBulletConstraintLimits(bool value) { · 515 unmodified lines | ||
| 8643 | 8808 | _physicsEngine->setShowBulletConstraintLimits(value); |
| 8644 | 8809 | } |
| 8645 | 8810 | |
| 8646 | −void Application::createLoginDialogOverlay() { | |
| 8647 | − const glm::vec2 LOGIN_OVERLAY_DIMENSIONS{ 0.89f, 0.5f }; | |
| 8648 | − const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f); | |
| 8811 | +void Application::createLoginDialog() { | |
| 8812 | + const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f }; | |
| 8813 | + const auto OFFSET = glm::vec2(0.7f, -0.1f); | |
| 8649 | 8814 | auto cameraPosition = _myCamera.getPosition(); |
| 8650 | 8815 | auto cameraOrientation = _myCamera.getOrientation(); |
| 8651 | 8816 | auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; |
| 8652 | 8817 | auto headLookVec = (cameraOrientation * Vectors::FRONT); |
| 8653 | 8818 | // DEFAULT_DPI / tablet scale percentage |
| 8654 | − const float OVERLAY_DPI = 31.0f / (75.0f / 100.0f); | |
| 8655 | − auto offset = headLookVec * OVERLAY_OFFSET.x; | |
| 8656 | − auto overlayPosition = (cameraPosition + offset) + (upVec * OVERLAY_OFFSET.y); | |
| 8657 | − QVariantMap overlayProperties = { | |
| 8658 | − { "name", "LoginDialogOverlay" }, | |
| 8659 | − { "url", OVERLAY_LOGIN_DIALOG }, | |
| 8660 | − { "position", vec3toVariant(overlayPosition) }, | |
| 8661 | − { "orientation", quatToVariant(cameraOrientation) }, | |
| 8662 | − { "isSolid", true }, | |
| 8663 | − { "grabbable", false }, | |
| 8664 | − { "ignorePickIntersection", false }, | |
| 8665 | − { "alpha", 1.0 }, | |
| 8666 | − { "dimensions", vec2ToVariant(LOGIN_OVERLAY_DIMENSIONS)}, | |
| 8667 | − { "dpi", OVERLAY_DPI }, | |
| 8668 | − { "visible", true } | |
| 8669 | − }; | |
| 8670 | − auto& overlays = getOverlays(); | |
| 8671 | − _loginDialogOverlayID = overlays.addOverlay("web3d", overlayProperties); | |
| 8672 | − auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID)); | |
| 8819 | + const float DPI = 31.0f / (75.0f / 100.0f); | |
| 8820 | + auto offset = headLookVec * OFFSET.x; | |
| 8821 | + auto position = (cameraPosition + offset) + (upVec * OFFSET.y); | |
| 8822 | + | |
| 8823 | + EntityItemProperties properties; | |
| 8824 | + properties.setType(EntityTypes::Web); | |
| 8825 | + properties.setName("LoginDialogEntity"); | |
| 8826 | + properties.setSourceUrl(LOGIN_DIALOG.toString()); | |
| 8827 | + properties.setPosition(position); | |
| 8828 | + properties.setRotation(cameraOrientation); | |
| 8829 | + properties.setDimensions(LOGIN_DIMENSIONS); | |
| 8830 | + properties.setPrimitiveMode(PrimitiveMode::SOLID); | |
| 8831 | + properties.getGrab().setGrabbable(false); | |
| 8832 | + properties.setIgnorePickIntersection(false); | |
| 8833 | + properties.setAlpha(1.0f); | |
| 8834 | + properties.setDPI(DPI); | |
| 8835 | + properties.setVisible(true); | |
| 8836 | + | |
| 8837 | + auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | |
| 8838 | + _loginDialogID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); | |
| 8839 | + | |
| 8673 | 8840 | auto keyboard = DependencyManager::get<Keyboard>().data(); |
| 8674 | − if (!keyboard->getAnchorID().isNull() && !_loginDialogOverlayID.isNull()) { | |
| 8675 | − const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); | |
| 8841 | + if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) { | |
| 8676 | 8842 | auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); |
| 8677 | − QVariantMap properties { | |
| 8678 | − { "position", vec3toVariant(overlayPosition + keyboardLocalOffset) }, | |
| 8679 | − { "orientation", quatToVariant(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION) }, | |
| 8680 | − }; | |
| 8681 | − overlays.editOverlay(keyboard->getAnchorID(), properties); | |
| 8843 | + | |
| 8844 | + EntityItemProperties properties; | |
| 8845 | + properties.setPosition(position + keyboardLocalOffset); | |
| 8846 | + properties.setRotation(cameraOrientation * Quaternions::Y_180); | |
| 8847 | + | |
| 8848 | + entityScriptingInterface->editEntity(keyboard->getAnchorID(), properties); | |
| 8682 | 8849 | keyboard->setResetKeyboardPositionOnRaise(false); |
| 8683 | 8850 | } |
| 8684 | − setKeyboardFocusOverlay(_loginDialogOverlayID); | |
| 8851 | + setKeyboardFocusEntity(_loginDialogID); | |
| 8685 | 8852 | emit loginDialogFocusEnabled(); |
| 8686 | 8853 | getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); |
| 8687 | 8854 | getApplicationCompositor().getReticleInterface()->setVisible(false); |
| @@ -8690,38 +8857,43 @@ void Application::createLoginDialogOverlay() { · 2 unmodified lines | ||
| 8690 | 8857 | } |
| 8691 | 8858 | } |
| 8692 | 8859 | |
| 8693 | −void Application::updateLoginDialogOverlayPosition() { | |
| 8860 | +void Application::updateLoginDialogPosition() { | |
| 8694 | 8861 | const float LOOK_AWAY_THRESHOLD_ANGLE = 70.0f; |
| 8695 | − const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f); | |
| 8696 | − auto& overlays = getOverlays(); | |
| 8697 | − auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID)); | |
| 8698 | − auto overlayPositionVec = loginOverlay->getWorldPosition(); | |
| 8862 | + const auto OFFSET = glm::vec2(0.7f, -0.1f); | |
| 8863 | + | |
| 8864 | + auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | |
| 8865 | + EntityPropertyFlags desiredProperties; | |
| 8866 | + desiredProperties += PROP_POSITION; | |
| 8867 | + auto properties = entityScriptingInterface->getEntityProperties(_loginDialogID, desiredProperties); | |
| 8868 | + auto positionVec = properties.getPosition(); | |
| 8699 | 8869 | auto cameraPositionVec = _myCamera.getPosition(); |
| 8700 | 8870 | auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation()); |
| 8701 | 8871 | auto headLookVec = (cameraOrientation * Vectors::FRONT); |
| 8702 | − auto overlayToHeadVec = overlayPositionVec - cameraPositionVec; | |
| 8703 | − auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI); | |
| 8872 | + auto entityToHeadVec = positionVec - cameraPositionVec; | |
| 8873 | + auto pointAngle = (glm::acos(glm::dot(glm::normalize(entityToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI); | |
| 8704 | 8874 | auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; |
| 8705 | − auto offset = headLookVec * OVERLAY_OFFSET.x; | |
| 8706 | − auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * OVERLAY_OFFSET.y); | |
| 8707 | − auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; | |
| 8875 | + auto offset = headLookVec * OFFSET.x; | |
| 8876 | + auto newPositionVec = (cameraPositionVec + offset) + (upVec * OFFSET.y); | |
| 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) { | |
| 8712 | − QVariantMap properties { | |
| 8713 | − {"position", vec3toVariant(newOverlayPositionVec)}, | |
| 8714 | − {"orientation", quatToVariant(newOverlayOrientation)} | |
| 8715 | − }; | |
| 8716 | − overlays.editOverlay(_loginDialogOverlayID, properties); | |
| 8717 | − const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); | |
| 8718 | − auto keyboardLocalOffset = newOverlayOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); | |
| 8719 | − QVariantMap keyboardProperties { | |
| 8720 | − { "position", vec3toVariant(newOverlayPositionVec + keyboardLocalOffset) }, | |
| 8721 | − { "orientation", quatToVariant(newOverlayOrientation * KEYBOARD_LOCAL_ORIENTATION) }, | |
| 8722 | − }; | |
| 8723 | − auto keyboard = DependencyManager::get<Keyboard>().data(); | |
| 8724 | − overlays.editOverlay(keyboard->getAnchorID(), keyboardProperties); | |
| 8880 | + if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || outOfBounds) { | |
| 8881 | + { | |
| 8882 | + EntityItemProperties properties; | |
| 8883 | + properties.setPosition(newPositionVec); | |
| 8884 | + properties.setRotation(cameraOrientation); | |
| 8885 | + entityScriptingInterface->editEntity(_loginDialogID, properties); | |
| 8886 | + } | |
| 8887 | + | |
| 8888 | + { | |
| 8889 | + glm::vec3 keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); | |
| 8890 | + glm::quat keyboardOrientation = cameraOrientation * glm::quat(glm::radians(glm::vec3(-30.0f, 180.0f, 0.0f))); | |
| 8891 | + | |
| 8892 | + EntityItemProperties properties; | |
| 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 | 8910 | loginDialogPoppedUp.set(false); |
| 8739 | 8911 | auto keyboard = DependencyManager::get<Keyboard>().data(); |
| 8740 | 8912 | keyboard->setResetKeyboardPositionOnRaise(true); |
| 8741 | − if (!_loginDialogOverlayID.isNull()) { | |
| 8742 | − // deleting overlay. | |
| 8743 | − getOverlays().deleteOverlay(_loginDialogOverlayID); | |
| 8744 | − _loginDialogOverlayID = OverlayID(); | |
| 8913 | + if (!_loginDialogID.isNull()) { | |
| 8914 | + DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_loginDialogID); | |
| 8915 | + _loginDialogID = QUuid(); | |
| 8745 | 8916 | _loginStateManager.tearDown(); |
| 8746 | 8917 | } |
| 8747 | 8918 | resumeAfterLoginDialogActionTaken(); |
| @@ -8907,12 +9078,12 @@ void Application::updateSystemTabletMode() { · 159 unmodified lines | ||
| 8907 | 9078 | } |
| 8908 | 9079 | } |
| 8909 | 9080 | |
| 8910 | −OverlayID Application::getTabletScreenID() const { | |
| 9081 | +QUuid Application::getTabletScreenID() const { | |
| 8911 | 9082 | auto HMD = DependencyManager::get<HMDScriptingInterface>(); |
| 8912 | 9083 | return HMD->getCurrentTabletScreenID(); |
| 8913 | 9084 | } |
| 8914 | 9085 | |
| 8915 | −OverlayID Application::getTabletHomeButtonID() const { | |
| 9086 | +QUuid Application::getTabletHomeButtonID() const { | |
| 8916 | 9087 | auto HMD = DependencyManager::get<HMDScriptingInterface>(); |
| 8917 | 9088 | return HMD->getCurrentHomeButtonID(); |
| 8918 | 9089 | } |
| @@ -8923,7 +9094,7 @@ QUuid Application::getTabletFrameID() const { · 4 unmodified lines | ||
| 8923 | 9094 | } |
| 8924 | 9095 | |
| 8925 | 9096 | QVector<QUuid> Application::getTabletIDs() const { |
| 8926 | − // Most important overlays first. | |
| 9097 | + // Most important first. | |
| 8927 | 9098 | QVector<QUuid> result; |
| 8928 | 9099 | auto HMD = DependencyManager::get<HMDScriptingInterface>(); |
| 8929 | 9100 | result << HMD->getCurrentTabletScreenID(); |