History

Merge branch 'master' into lod

Sam Gondelman committed 8 years ago

Commit 57275422 parents e9ab2b8 d8c30ff1116 files · +34862 −17271Browse files

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

Unified · Split

interface/src/Application.cpp+331−267
@@ -63,6 +63,7 @@ · 62 unmodified lines
6363 #include <AddressManager.h>
6464 #include <AnimDebugDraw.h>
6565 #include <BuildInfo.h>
66+#include <AnimationCacheScriptingInterface.h>
6667 #include <AssetClient.h>
6768 #include <AssetUpload.h>
6869 #include <AutoUpdater.h>
@@ -98,6 +99,8 @@ · 29 unmodified lines
9899 #include <MainWindow.h>
99100 #include <MappingRequest.h>
100101 #include <MessagesClient.h>
102+#include <model-networking/ModelCacheScriptingInterface.h>
103+#include <model-networking/TextureCacheScriptingInterface.h>
101104 #include <ModelEntityItem.h>
102105 #include <NetworkAccessManager.h>
103106 #include <NetworkingConstants.h>
@@ -127,7 +130,7 @@ · 23 unmodified lines
127130 #include <ScriptEngines.h>
128131 #include <ScriptCache.h>
129132 #include <ShapeEntityItem.h>
130−#include <SoundCache.h>
133+#include <SoundCacheScriptingInterface.h>
131134 #include <ui/TabletScriptingInterface.h>
132135 #include <ui/ToolbarScriptingInterface.h>
133136 #include <InteractiveWindow.h>
@@ -143,6 +146,7 @@ · 9 unmodified lines
143146 #include <QmlFragmentClass.h>
144147 #include <Preferences.h>
145148 #include <display-plugins/CompositorHelper.h>
149+#include <display-plugins/hmd/HmdDisplayPlugin.h>
146150 #include <trackers/EyeTracker.h>
147151 #include <avatars-renderer/ScriptAvatar.h>
148152 #include <RenderableEntityItem.h>
@@ -262,19 +266,10 @@ class RenderEventHandler : public QObject { · 113 unmodified lines
262266 using Parent = QObject;
263267 Q_OBJECT
264268 public:
265− RenderEventHandler(QOpenGLContext* context) {
266− _renderContext = new OffscreenGLCanvas();
267− _renderContext->setObjectName("RenderContext");
268− _renderContext->create(context);
269− if (!_renderContext->makeCurrent()) {
270− qFatal("Unable to make rendering context current");
271− }
272− _renderContext->doneCurrent();
273−
269+ RenderEventHandler() {
274270 // Transfer to a new thread
275271 moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) {
276272 hifi::qt::addBlockingForbiddenThread("Render", renderThread);
277− _renderContext->moveToThreadWithContext(renderThread);
278273 qApp->_lastTimeRendered.start();
279274 }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority);
280275 }
@@ -284,9 +279,6 @@ private: · 3 unmodified lines
284279 setObjectName("Render");
285280 PROFILE_SET_THREAD_NAME("Render");
286281 setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
287− if (!_renderContext->makeCurrent()) {
288− qFatal("Unable to make rendering context current on render thread");
289− }
290282 }
291283
292284 void render() {
@@ -307,8 +299,6 @@ private: · 14 unmodified lines
307299 }
308300 return Parent::event(event);
309301 }
310−
311− OffscreenGLCanvas* _renderContext { nullptr };
312302 };
313303
314304
@@ -374,6 +364,7 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI · 59 unmodified lines
374364 static const uint32_t INVALID_FRAME = UINT32_MAX;
375365
376366 static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation
367+static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entities before physics enabled
377368
378369 static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
379370
@@ -384,6 +375,7 @@ static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds · 4 unmodified lines
384375 static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
385376 static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
386377 static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
378+static const QString AUTO_LOGOUT_SETTING_NAME = "wallet/autoLogout";
387379
388380 const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
389381 { SVO_EXTENSION, &Application::importSVOFromURL },
@@ -734,6 +726,9 @@ static const QString STATE_SNAP_TURN = "SnapTurn"; · 344 unmodified lines
734726 static const QString STATE_ADVANCED_MOVEMENT_CONTROLS = "AdvancedMovement";
735727 static const QString STATE_GROUNDED = "Grounded";
736728 static const QString STATE_NAV_FOCUSED = "NavigationFocused";
729+static const QString STATE_PLATFORM_WINDOWS = "PlatformWindows";
730+static const QString STATE_PLATFORM_MAC = "PlatformMac";
731+static const QString STATE_PLATFORM_ANDROID = "PlatformAndroid";
737732
738733 // Statically provided display and input plugins
739734 extern DisplayPluginList getDisplayPlugins();
@@ -866,16 +861,20 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 126 unmodified lines
866861 DependencyManager::set<recording::ClipCache>();
867862 DependencyManager::set<GeometryCache>();
868863 DependencyManager::set<ModelCache>();
864+ DependencyManager::set<ModelCacheScriptingInterface>();
869865 DependencyManager::set<ScriptCache>();
870866 DependencyManager::set<SoundCache>();
867+ DependencyManager::set<SoundCacheScriptingInterface>();
871868 DependencyManager::set<DdeFaceTracker>();
872869 DependencyManager::set<EyeTracker>();
873870 DependencyManager::set<AudioClient>();
874871 DependencyManager::set<AudioScope>();
875872 DependencyManager::set<DeferredLightingEffect>();
876873 DependencyManager::set<TextureCache>();
874+ DependencyManager::set<TextureCacheScriptingInterface>();
877875 DependencyManager::set<FramebufferCache>();
878876 DependencyManager::set<AnimationCache>();
877+ DependencyManager::set<AnimationCacheScriptingInterface>();
879878 DependencyManager::set<ModelBlender>();
880879 DependencyManager::set<UsersScriptingInterface>();
881880 DependencyManager::set<AvatarManager>();
@@ -913,7 +912,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 31 unmodified lines
913912 DependencyManager::set<MessagesClient>();
914913 controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR,
915914 STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT,
916− STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED } });
915+ STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED,
916+ STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID } });
917917 DependencyManager::set<UserInputMapper>();
918918 DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>();
919919 DependencyManager::set<InterfaceParentFinder>();
@@ -1018,7 +1018,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 98 unmodified lines
10181018 // This is done so as not break previous command line scripts
10191019 if (testScriptPath.left(URL_SCHEME_HTTP.length()) == URL_SCHEME_HTTP ||
10201020 testScriptPath.left(URL_SCHEME_FTP.length()) == URL_SCHEME_FTP) {
1021−
1021+
10221022 setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath));
10231023 } else if (QFileInfo(testScriptPath).exists()) {
10241024 setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath));
@@ -1099,6 +1099,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 74 unmodified lines
10991099 // Set File Logger Session UUID
11001100 auto avatarManager = DependencyManager::get<AvatarManager>();
11011101 auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
1102+ if (avatarManager) {
1103+ workload::SpacePointer space = getEntities()->getWorkloadSpace();
1104+ avatarManager->setSpace(space);
1105+ }
11021106 auto accountManager = DependencyManager::get<AccountManager>();
11031107
11041108 _logger->setSessionID(accountManager->getSessionID());
@@ -1130,8 +1134,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 25 unmodified lines
11301134
11311135 // setup a timer for domain-server check ins
11321136 QTimer* domainCheckInTimer = new QTimer(this);
1133− connect(domainCheckInTimer, &QTimer::timeout, [this, nodeList] {
1134− if (!isServerlessMode()) {
1137+ QWeakPointer<NodeList> nodeListWeak = nodeList;
1138+ connect(domainCheckInTimer, &QTimer::timeout, [this, nodeListWeak] {
1139+ auto nodeList = nodeListWeak.lock();
1140+ if (!isServerlessMode() && nodeList) {
11351141 nodeList->sendDomainServerCheckIn();
11361142 }
11371143 });
@@ -1141,33 +1147,34 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 3 unmodified lines
11411147 domainCheckInTimer->deleteLater();
11421148 });
11431149
1150+ {
1151+ auto audioIO = DependencyManager::get<AudioClient>().data();
1152+ audioIO->setPositionGetter([] {
1153+ auto avatarManager = DependencyManager::get<AvatarManager>();
1154+ auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
11441155
1145− auto audioIO = DependencyManager::get<AudioClient>();
1146− audioIO->setPositionGetter([]{
1147− auto avatarManager = DependencyManager::get<AvatarManager>();
1148− auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
1149−
1150− return myAvatar ? myAvatar->getPositionForAudio() : Vectors::ZERO;
1151− });
1152− audioIO->setOrientationGetter([]{
1153− auto avatarManager = DependencyManager::get<AvatarManager>();
1154− auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
1156+ return myAvatar ? myAvatar->getPositionForAudio() : Vectors::ZERO;
1157+ });
1158+ audioIO->setOrientationGetter([] {
1159+ auto avatarManager = DependencyManager::get<AvatarManager>();
1160+ auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
11551161
1156− return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;
1157− });
1162+ return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;
1163+ });
11581164
1159− recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) {
1160− audioIO->handleRecordedAudioInput(frame->data);
1161− });
1165+ recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [&audioIO](recording::Frame::ConstPointer frame) {
1166+ audioIO->handleRecordedAudioInput(frame->data);
1167+ });
11621168
1163− connect(audioIO.data(), &AudioClient::inputReceived, [](const QByteArray& audio){
1164− static auto recorder = DependencyManager::get<recording::Recorder>();
1165− if (recorder->isRecording()) {
1166− static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName());
1167− recorder->recordFrame(AUDIO_FRAME_TYPE, audio);
1168− }
1169− });
1170− audioIO->startThread();
1169+ connect(audioIO, &AudioClient::inputReceived, [](const QByteArray& audio) {
1170+ static auto recorder = DependencyManager::get<recording::Recorder>();
1171+ if (recorder->isRecording()) {
1172+ static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName());
1173+ recorder->recordFrame(AUDIO_FRAME_TYPE, audio);
1174+ }
1175+ });
1176+ audioIO->startThread();
1177+ }
11711178
11721179 // Make sure we don't time out during slow operations at startup
11731180 updateHeartbeat();
@@ -1238,7 +1245,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 64 unmodified lines
12381245 accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
12391246
12401247 // use our MyAvatar position and quat for address manager path
1241− addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldPosition(); });
1248+ addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldFeetPosition(); });
12421249 addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); });
12431250
12441251 connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
@@ -1266,27 +1273,29 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 21 unmodified lines
12661273 // Inititalize sample before registering
12671274 _sampleSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/sample.wav"));
12681275
1269− auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
1270− scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){
1271− registerScriptEngineWithApplicationServices(engine);
1272− });
1276+ {
1277+ auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
1278+ scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine) {
1279+ registerScriptEngineWithApplicationServices(engine);
1280+ });
12731281
1274− connect(scriptEngines, &ScriptEngines::scriptCountChanged, scriptEngines, [this] {
1275− auto scriptEngines = DependencyManager::get<ScriptEngines>();
1276− if (scriptEngines->getRunningScripts().isEmpty()) {
1277− getMyAvatar()->clearScriptableSettings();
1278− }
1279− }, Qt::QueuedConnection);
1282+ connect(scriptEngines, &ScriptEngines::scriptCountChanged, this, [this] {
1283+ auto scriptEngines = DependencyManager::get<ScriptEngines>();
1284+ if (scriptEngines->getRunningScripts().isEmpty()) {
1285+ getMyAvatar()->clearScriptableSettings();
1286+ }
1287+ }, Qt::QueuedConnection);
12801288
1281− connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] {
1282− getEntities()->reloadEntityScripts();
1283− loadAvatarScripts(getMyAvatar()->getScriptUrls());
1284− }, Qt::QueuedConnection);
1289+ connect(scriptEngines, &ScriptEngines::scriptsReloading, this, [this] {
1290+ getEntities()->reloadEntityScripts();
1291+ loadAvatarScripts(getMyAvatar()->getScriptUrls());
1292+ }, Qt::QueuedConnection);
12851293
1286− connect(scriptEngines, &ScriptEngines::scriptLoadError,
1287− scriptEngines, [](const QString& filename, const QString& error){
1288− OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load.");
1289− }, Qt::QueuedConnection);
1294+ connect(scriptEngines, &ScriptEngines::scriptLoadError,
1295+ this, [](const QString& filename, const QString& error) {
1296+ OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load.");
1297+ }, Qt::QueuedConnection);
1298+ }
12901299
12911300 #ifdef _WIN32
12921301 WSADATA WsaData;
@@ -1356,10 +1365,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 63 unmodified lines
13561365 // so we defer the setup of the `scripting::Audio` class until this point
13571366 {
13581367 auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface, scripting::Audio>();
1359− connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);
1360− connect(audioIO.data(), &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket);
1361− connect(audioIO.data(), &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected);
1362− connect(audioIO.data(), &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) {
1368+ auto audioIO = DependencyManager::get<AudioClient>().data();
1369+ connect(audioIO, &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);
1370+ connect(audioIO, &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket);
1371+ connect(audioIO, &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected);
1372+ connect(audioIO, &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) {
13631373 auto audioClient = DependencyManager::get<AudioClient>();
13641374 auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
13651375 auto myAvatarPosition = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldPosition();
@@ -1677,6 +1687,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 311 unmodified lines
16771687 _applicationStateDevice->setInputVariant(STATE_NAV_FOCUSED, []() -> float {
16781688 return DependencyManager::get<OffscreenUi>()->navigationFocused() ? 1 : 0;
16791689 });
1690+ _applicationStateDevice->setInputVariant(STATE_PLATFORM_WINDOWS, []() -> float {
1691+#if defined(Q_OS_WIN)
1692+ return 1;
1693+#else
1694+ return 0;
1695+#endif
1696+ });
1697+ _applicationStateDevice->setInputVariant(STATE_PLATFORM_MAC, []() -> float {
1698+#if defined(Q_OS_MAC)
1699+ return 1;
1700+#else
1701+ return 0;
1702+#endif
1703+ });
1704+ _applicationStateDevice->setInputVariant(STATE_PLATFORM_ANDROID, []() -> float {
1705+#if defined(Q_OS_ANDROID)
1706+ return 1;
1707+#else
1708+ return 0;
1709+#endif
1710+ });
16801711
16811712 // Setup the _keyboardMouseDevice, _touchscreenDevice, _touchscreenVirtualPadDevice and the user input mapper with the default bindings
16821713 userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice());
@@ -1688,23 +1719,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 5 unmodified lines
16881719 userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice());
16891720 }
16901721
1691− // this will force the model the look at the correct directory (weird order of operations issue)
1692− scriptEngines->reloadLocalFiles();
1693−
1694− // do this as late as possible so that all required subsystems are initialized
1695− // If we've overridden the default scripts location, just load default scripts
1696− // otherwise, load 'em all
1697−
1698− // we just want to see if --scripts was set, we've already parsed it and done
1699− // the change in PathUtils. Rather than pass that in the constructor, lets just
1700− // look (this could be debated)
1701− QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
1702− QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()));
1703− if (!defaultScriptsLocation.exists()) {
1704− scriptEngines->loadDefaultScripts();
1705− scriptEngines->defaultScriptsLocationOverridden(true);
1706− } else {
1707− scriptEngines->loadScripts();
1722+ {
1723+ auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
1724+ // this will force the model the look at the correct directory (weird order of operations issue)
1725+ scriptEngines->reloadLocalFiles();
1726+
1727+ // do this as late as possible so that all required subsystems are initialized
1728+ // If we've overridden the default scripts location, just load default scripts
1729+ // otherwise, load 'em all
1730+
1731+ // we just want to see if --scripts was set, we've already parsed it and done
1732+ // the change in PathUtils. Rather than pass that in the constructor, lets just
1733+ // look (this could be debated)
1734+ QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
1735+ QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()));
1736+ if (!defaultScriptsLocation.exists()) {
1737+ scriptEngines->loadDefaultScripts();
1738+ scriptEngines->defaultScriptsLocationOverridden(true);
1739+ } else {
1740+ scriptEngines->loadScripts();
1741+ }
17081742 }
17091743
17101744 // Make sure we don't time out during slow operations at startup
@@ -1754,13 +1788,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 43 unmodified lines
17541788 cameraMenuChanged();
17551789 }
17561790
1757− // set the local loopback interface for local sounds
1758− AudioInjector::setLocalAudioInterface(audioIO.data());
1759− auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
1760− audioScriptingInterface->setLocalAudioInterface(audioIO.data());
1761− connect(audioIO.data(), &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened);
1762− connect(audioIO.data(), &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed);
1763− connect(audioIO.data(), &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived);
1791+ {
1792+ auto audioIO = DependencyManager::get<AudioClient>().data();
1793+ // set the local loopback interface for local sounds
1794+ AudioInjector::setLocalAudioInterface(audioIO);
1795+ auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
1796+ audioScriptingInterface->setLocalAudioInterface(audioIO);
1797+ connect(audioIO, &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened);
1798+ connect(audioIO, &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed);
1799+ connect(audioIO, &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived);
1800+ }
17641801
17651802 this->installEventFilter(this);
17661803
@@ -1817,21 +1854,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 50 unmodified lines
18171854 }
18181855 });
18191856
1820− connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [=](const EntityItemID& entityItemID) {
1857+ connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) {
18211858 if (entityItemID == _keyboardFocusedEntity.get()) {
18221859 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
18231860 }
18241861 });
18251862
1826− connect(getEntities()->getTree().get(), &EntityTree::deletingEntity, [=](const EntityItemID& entityItemID) {
1827− auto avatarManager = DependencyManager::get<AvatarManager>();
1828− auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
1829− if (myAvatar) {
1830− myAvatar->clearAvatarEntity(entityItemID);
1863+ EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
1864+ if (_aboutToQuit) {
1865+ return false;
18311866 }
1832− });
18331867
1834− EntityTree::setAddMaterialToEntityOperator([&](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
18351868 // try to find the renderable
18361869 auto renderable = getEntities()->renderableForEntityId(entityID);
18371870 if (renderable) {
@@ -1846,7 +1879,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 8 unmodified lines
18461879 }
18471880 return false;
18481881 });
1849− EntityTree::setRemoveMaterialFromEntityOperator([&](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
1882+ EntityTree::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
1883+ if (_aboutToQuit) {
1884+ return false;
1885+ }
1886+
18501887 // try to find the renderable
18511888 auto renderable = getEntities()->renderableForEntityId(entityID);
18521889 if (renderable) {
@@ -1881,7 +1918,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 28 unmodified lines
18811918 return false;
18821919 });
18831920
1884− EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
1921+ EntityTree::setAddMaterialToOverlayOperator([this](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
18851922 auto overlay = _overlays.getOverlay(overlayID);
18861923 if (overlay) {
18871924 overlay->addMaterial(material, parentMaterialName);
@@ -1889,7 +1926,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 1 unmodified line
18891926 }
18901927 return false;
18911928 });
1892− EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
1929+ EntityTree::setRemoveMaterialFromOverlayOperator([this](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
18931930 auto overlay = _overlays.getOverlay(overlayID);
18941931 if (overlay) {
18951932 overlay->removeMaterial(material, parentMaterialName);
@@ -1900,13 +1937,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 4 unmodified lines
19001937
19011938 // Keyboard focus handling for Web overlays.
19021939 auto overlays = &(qApp->getOverlays());
1903− connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
1940+ connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) {
19041941 if (overlayID == _keyboardFocusedOverlay.get()) {
19051942 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
19061943 }
19071944 });
19081945
1909− connect(this, &Application::aboutToQuit, [=]() {
1946+ connect(this, &Application::aboutToQuit, [this]() {
19101947 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
19111948 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
19121949 });
@@ -2175,23 +2212,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 262 unmodified lines
21752212 QVariant testProperty = property(hifi::properties::TEST);
21762213 qDebug() << testProperty;
21772214 if (testProperty.isValid()) {
2178− auto scriptEngines = DependencyManager::get<ScriptEngines>();
21792215 const auto testScript = property(hifi::properties::TEST).toUrl();
21802216
21812217 // Set last parameter to exit interface when the test script finishes, if so requested
2182− scriptEngines->loadScript(testScript, false, false, false, false, quitWhenFinished);
2218+ DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
21832219
21842220 // This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
21852221 if (arguments().contains("--url")) {
21862222 auto reply = SandboxUtils::getStatus();
2187− connect(reply, &QNetworkReply::finished, this, [=] {
2223+ connect(reply, &QNetworkReply::finished, this, [this, reply] {
21882224 handleSandboxStatus(reply);
21892225 });
21902226 }
21912227 } else {
21922228 PROFILE_RANGE(render, "GetSandboxStatus");
21932229 auto reply = SandboxUtils::getStatus();
2194− connect(reply, &QNetworkReply::finished, this, [=] {
2230+ connect(reply, &QNetworkReply::finished, this, [this, reply] {
21952231 handleSandboxStatus(reply);
21962232 });
21972233 }
@@ -2218,8 +2254,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 20 unmodified lines
22182254
22192255 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
22202256
2221− DependencyManager::get<PickManager>()->setShouldPickHUDOperator([&]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
2222− DependencyManager::get<PickManager>()->setCalculatePos2DFromHUDOperator([&](const glm::vec3& intersection) {
2257+ DependencyManager::get<PickManager>()->setShouldPickHUDOperator([]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
2258+ DependencyManager::get<PickManager>()->setCalculatePos2DFromHUDOperator([this](const glm::vec3& intersection) {
22232259 const glm::vec2 MARGIN(25.0f);
22242260 glm::vec2 maxPos = _controllerScriptingInterface->getViewportDimensions() - MARGIN;
22252261 glm::vec2 pos2D = DependencyManager::get<HMDScriptingInterface>()->overlayFromWorldPoint(intersection);
@@ -2229,7 +2265,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 3 unmodified lines
22292265 // Setup the mouse ray pick and related operators
22302266 DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(
22312267 PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)));
2232− DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](unsigned int rayPickID) {
2268+ DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([](unsigned int rayPickID) {
22332269 RayToEntityIntersectionResult entityResult;
22342270 entityResult.intersects = false;
22352271 auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(rayPickID);
@@ -2245,7 +2281,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 9 unmodified lines
22452281 }
22462282 return entityResult;
22472283 });
2248− DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](unsigned int rayPickID, bool value) {
2284+ DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([](unsigned int rayPickID, bool value) {
22492285 DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
22502286 });
22512287
@@ -2444,23 +2480,42 @@ void Application::cleanupBeforeQuit() { · 192 unmodified lines
24442480 _keyboardFocusHighlight = nullptr;
24452481 }
24462482
2447− auto nodeList = DependencyManager::get<NodeList>();
2483+ {
2484+ auto nodeList = DependencyManager::get<NodeList>();
24482485
2449− // send the domain a disconnect packet, force stoppage of domain-server check-ins
2450− nodeList->getDomainHandler().disconnect();
2451− nodeList->setIsShuttingDown(true);
2486+ // send the domain a disconnect packet, force stoppage of domain-server check-ins
2487+ nodeList->getDomainHandler().disconnect();
2488+ nodeList->setIsShuttingDown(true);
24522489
2453− // tell the packet receiver we're shutting down, so it can drop packets
2454− nodeList->getPacketReceiver().setShouldDropPackets(true);
2490+ // tell the packet receiver we're shutting down, so it can drop packets
2491+ nodeList->getPacketReceiver().setShouldDropPackets(true);
2492+ }
24552493
24562494 getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
24572495
24582496 // Clear any queued processing (I/O, FBX/OBJ/Texture parsing)
24592497 QThreadPool::globalInstance()->clear();
24602498
2499+ DependencyManager::destroy<RecordingScriptingInterface>();
2500+
2501+ // FIXME: Something is still holding on to the ScriptEnginePointers contained in ScriptEngines, and they hold backpointers to ScriptEngines,
2502+ // so this doesn't shut down properly
24612503 DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts
2504+ // These classes hold ScriptEnginePointers, so they must be destroyed before ScriptEngines
2505+ // Must be done after shutdownScripting in case any scripts try to access these things
2506+ {
2507+ DependencyManager::destroy<StandAloneJSConsole>();
2508+ EntityTreePointer tree = getEntities()->getTree();
2509+ tree->setSimulation(nullptr);
2510+ DependencyManager::destroy<EntityTreeRenderer>();
2511+ }
24622512 DependencyManager::destroy<ScriptEngines>();
24632513
2514+ bool autoLogout = Setting::Handle<bool>(AUTO_LOGOUT_SETTING_NAME, false).get();
2515+ if (autoLogout) {
2516+ DependencyManager::get<AccountManager>()->removeAccountFromFile();
2517+ }
2518+
24642519 _displayPlugin.reset();
24652520 PluginManager::getInstance()->shutdown();
24662521
@@ -2495,6 +2550,8 @@ void Application::cleanupBeforeQuit() { · 28 unmodified lines
24952550 DependencyManager::destroy<EyeTracker>();
24962551 #endif
24972552
2553+ DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface
2554+
24982555 // stop QML
24992556 DependencyManager::destroy<TabletScriptingInterface>();
25002557 DependencyManager::destroy<ToolbarScriptingInterface>();
@@ -2506,10 +2563,6 @@ void Application::cleanupBeforeQuit() { · 5 unmodified lines
25062563 _snapshotSoundInjector->stop();
25072564 }
25082565
2509− // FIXME: something else is holding a reference to AudioClient,
2510− // so it must be explicitly synchronously stopped here
2511− DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
2512−
25132566 // destroy Audio so it and its threads have a chance to go down safely
25142567 // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
25152568 DependencyManager::destroy<AudioClient>();
@@ -2526,11 +2579,15 @@ void Application::cleanupBeforeQuit() { · 10 unmodified lines
25262579
25272580 Application::~Application() {
25282581 // remove avatars from physics engine
2529− DependencyManager::get<AvatarManager>()->clearOtherAvatars();
2530− VectorOfMotionStates motionStates;
2531− DependencyManager::get<AvatarManager>()->getObjectsToRemoveFromPhysics(motionStates);
2532− _physicsEngine->removeObjects(motionStates);
2533− DependencyManager::get<AvatarManager>()->deleteAllAvatars();
2582+ auto avatarManager = DependencyManager::get<AvatarManager>();
2583+ avatarManager->clearOtherAvatars();
2584+
2585+ PhysicsEngine::Transaction transaction;
2586+ avatarManager->buildPhysicsTransaction(transaction);
2587+ _physicsEngine->processTransaction(transaction);
2588+ avatarManager->handleProcessedPhysicsTransaction(transaction);
2589+
2590+ avatarManager->deleteAllAvatars();
25342591
25352592 _physicsEngine->setCharacterController(nullptr);
25362593
@@ -2549,9 +2606,6 @@ Application::~Application() { · 12 unmodified lines
25492606 _entityClipboard->eraseAllOctreeElements();
25502607 _entityClipboard.reset();
25512608
2552− EntityTreePointer tree = getEntities()->getTree();
2553− tree->setSimulation(nullptr);
2554−
25552609 _octreeProcessor.terminate();
25562610 _entityEditSender.terminate();
25572611
@@ -2562,12 +2616,18 @@ Application::~Application() { · 4 unmodified lines
25622616
25632617 DependencyManager::destroy<CompositorHelper>(); // must be destroyed before the FramebufferCache
25642618
2619+ DependencyManager::destroy<SoundCacheScriptingInterface>();
2620+
25652621 DependencyManager::destroy<AvatarManager>();
2622+ DependencyManager::destroy<AnimationCacheScriptingInterface>();
25662623 DependencyManager::destroy<AnimationCache>();
25672624 DependencyManager::destroy<FramebufferCache>();
2625+ DependencyManager::destroy<TextureCacheScriptingInterface>();
25682626 DependencyManager::destroy<TextureCache>();
2627+ DependencyManager::destroy<ModelCacheScriptingInterface>();
25692628 DependencyManager::destroy<ModelCache>();
25702629 DependencyManager::destroy<ScriptCache>();
2630+ DependencyManager::destroy<SoundCacheScriptingInterface>();
25712631 DependencyManager::destroy<SoundCache>();
25722632 DependencyManager::destroy<OctreeStatsProvider>();
25732633 DependencyManager::destroy<GeometryCache>();
@@ -2596,7 +2656,7 @@ Application::~Application() { · 22 unmodified lines
25962656
25972657 // Can't log to file passed this point, FileLogger about to be deleted
25982658 qInstallMessageHandler(LogHandler::verboseMessageHandler);
2599−
2659+
26002660 _renderEventHandler->deleteLater();
26012661 }
26022662
@@ -2660,26 +2720,14 @@ void Application::initializeGL() { · 57 unmodified lines
26602720 }
26612721 }
26622722
2663− // Build an offscreen GL context for the main thread.
2664− _offscreenContext = new OffscreenGLCanvas();
2665− _offscreenContext->setObjectName("MainThreadContext");
2666− _offscreenContext->create(_glWidget->qglContext());
2667− if (!_offscreenContext->makeCurrent()) {
2668− qFatal("Unable to make offscreen context current");
2669− }
2670− _offscreenContext->doneCurrent();
2671− _offscreenContext->setThreadContext();
2723+ _renderEventHandler = new RenderEventHandler();
26722724
2725+ // Build an offscreen GL context for the main thread.
26732726 _glWidget->makeCurrent();
26742727 glClearColor(0.2f, 0.2f, 0.2f, 1);
26752728 glClear(GL_COLOR_BUFFER_BIT);
26762729 _glWidget->swapBuffers();
26772730
2678− // Move the GL widget context to the render event handler thread
2679− _renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
2680− if (!_offscreenContext->makeCurrent()) {
2681− qFatal("Unable to make offscreen context current");
2682− }
26832731
26842732 // Create the GPU backend
26852733
@@ -2688,15 +2736,10 @@ void Application::initializeGL() { · 2 unmodified lines
26882736 // contexts
26892737 _glWidget->makeCurrent();
26902738 gpu::Context::init<gpu::gl::GLBackend>();
2691− qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
2692− QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
26932739 _glWidget->makeCurrent();
26942740 _gpuContext = std::make_shared<gpu::Context>();
26952741
26962742 DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
2697−
2698− // Restore the default main thread context
2699− _offscreenContext->makeCurrent();
27002743 }
27012744
27022745 static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" };
@@ -2717,6 +2760,10 @@ void Application::initializeDisplayPlugins() { · 14 unmodified lines
27172760 QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged,
27182761 [this](const QSize& size) { resizeGL(); });
27192762 QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset);
2763+ if (displayPlugin->isHmd()) {
2764+ QObject::connect(dynamic_cast<HmdDisplayPlugin*>(displayPlugin.get()), &HmdDisplayPlugin::hmdMountedChanged,
2765+ DependencyManager::get<HMDScriptingInterface>().data(), &HMDScriptingInterface::mountedChanged);
2766+ }
27202767 }
27212768
27222769 // The default display plugin needs to be activated first, otherwise the display plugin thread
@@ -2731,8 +2778,6 @@ void Application::initializeDisplayPlugins() { · 8 unmodified lines
27312778 // Submit a default frame to render until the engine starts up
27322779 updateRenderArgs(0.0f);
27332780
2734− _offscreenContext->makeCurrent();
2735−
27362781 #define ENABLE_SPLASH_FRAME 0
27372782 #if ENABLE_SPLASH_FRAME
27382783 {
@@ -2774,8 +2819,6 @@ void Application::initializeDisplayPlugins() { · 35 unmodified lines
27742819 }
27752820
27762821 void Application::initializeRenderEngine() {
2777− _offscreenContext->makeCurrent();
2778−
27792822 // FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
27802823 DeadlockWatchdogThread::withPause([&] {
27812824 // Set up the render engine
@@ -2907,6 +2950,15 @@ void Application::initializeUi() { · 125 unmodified lines
29072950
29082951 // Pre-create a couple of Web3D overlays to speed up tablet UI
29092952 auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
2953+ offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) {
2954+ if (rootObject == TabletScriptingInterface::QML) {
2955+ // in Qt 5.10.0 there is already an "Audio" object in the QML context
2956+ // though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
2957+ surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data());
2958+ surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
2959+ }
2960+ });
2961+
29102962 offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
29112963 offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
29122964
@@ -2989,10 +3041,11 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { · 76 unmodified lines
29893041 surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
29903042
29913043 // Caches
2992− surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
2993− surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
2994− surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
2995− surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
3044+ surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCacheScriptingInterface>().data());
3045+ surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCacheScriptingInterface>().data());
3046+ surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCacheScriptingInterface>().data());
3047+ surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
3048+
29963049 surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
29973050
29983051 surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
@@ -3247,8 +3300,7 @@ void Application::showHelp() { · 248 unmodified lines
32473300 QUrlQuery queryString;
32483301 queryString.addQueryItem("handControllerName", handControllerName);
32493302 queryString.addQueryItem("defaultTab", defaultTab);
3250− auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
3251− TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
3303+ TabletProxy* tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet(SYSTEM_TABLET));
32523304 tablet->gotoWebScreen(PathUtils::resourcesUrl() + INFO_HELP_PATH + "?" + queryString.toString());
32533305 DependencyManager::get<HMDScriptingInterface>()->openTablet();
32543306 //InfoView::show(INFO_HELP_PATH, false, queryString.toString());
@@ -3561,6 +3613,10 @@ static void dumpEventQueue(QThread* thread) { · 306 unmodified lines
35613613
35623614 bool Application::event(QEvent* event) {
35633615
3616+ if (_aboutToQuit) {
3617+ return false;
3618+ }
3619+
35643620 if (!Menu::getInstance()) {
35653621 return false;
35663622 }
@@ -3650,6 +3706,10 @@ bool Application::event(QEvent* event) { · 83 unmodified lines
36503706
36513707 bool Application::eventFilter(QObject* object, QEvent* event) {
36523708
3709+ if (_aboutToQuit && event->type() != QEvent::DeferredDelete && event->type() != QEvent::Destroy) {
3710+ return true;
3711+ }
3712+
36533713 if (event->type() == QEvent::Leave) {
36543714 getApplicationCompositor().handleLeaveEvent();
36553715 }
@@ -3674,7 +3734,10 @@ static bool _altPressed{ false }; · 18 unmodified lines
36743734
36753735 void Application::keyPressEvent(QKeyEvent* event) {
36763736 _altPressed = event->key() == Qt::Key_Alt;
3677− _keysPressed.insert(event->key());
3737+
3738+ if (!event->isAutoRepeat()) {
3739+ _keysPressed.insert(event->key(), *event);
3740+ }
36783741
36793742 _controllerScriptingInterface->emitKeyPressEvent(event); // send events to any registered scripts
36803743 // if one of our scripts have asked to capture this event, then stop processing it
@@ -3885,7 +3948,9 @@ void Application::keyPressEvent(QKeyEvent* event) { · 204 unmodified lines
38853948 }
38863949
38873950 void Application::keyReleaseEvent(QKeyEvent* event) {
3888− _keysPressed.remove(event->key());
3951+ if (!event->isAutoRepeat()) {
3952+ _keysPressed.remove(event->key());
3953+ }
38893954
38903955 #if defined(Q_OS_ANDROID)
38913956 if (event->key() == Qt::Key_Back) {
@@ -3921,11 +3986,14 @@ void Application::focusOutEvent(QFocusEvent* event) { · 29 unmodified lines
39213986 #endif
39223987
39233988 // synthesize events for keys currently pressed, since we may not get their release events
3924− foreach (int key, _keysPressed) {
3925− QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
3926− keyReleaseEvent(&keyEvent);
3989+ // Because our key event handlers may manipulate _keysPressed, lets swap the keys pressed into a local copy,
3990+ // clearing the existing list.
3991+ QHash<int, QKeyEvent> keysPressed;
3992+ std::swap(keysPressed, _keysPressed);
3993+ for (auto& ev : keysPressed) {
3994+ QKeyEvent synthesizedEvent { QKeyEvent::KeyRelease, ev.key(), Qt::NoModifier, ev.text() };
3995+ keyReleaseEvent(&synthesizedEvent);
39273996 }
3928− _keysPressed.clear();
39293997 }
39303998
39313999 void Application::maybeToggleMenuVisible(QMouseEvent* event) const {
@@ -3953,10 +4021,6 @@ void Application::maybeToggleMenuVisible(QMouseEvent* event) const { · 21 unmodified lines
39534021 void Application::mouseMoveEvent(QMouseEvent* event) {
39544022 PROFILE_RANGE(app_input_mouse, __FUNCTION__);
39554023
3956− if (_aboutToQuit) {
3957− return;
3958− }
3959−
39604024 maybeToggleMenuVisible(event);
39614025
39624026 auto& compositor = getApplicationCompositor();
@@ -4021,11 +4085,9 @@ void Application::mousePressEvent(QMouseEvent* event) { · 58 unmodified lines
40214085 event->screenPos(), event->button(),
40224086 event->buttons(), event->modifiers());
40234087
4024− if (!_aboutToQuit) {
4025− getOverlays().mousePressEvent(&mappedEvent);
4026− if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
4027− getEntities()->mousePressEvent(&mappedEvent);
4028− }
4088+ getOverlays().mousePressEvent(&mappedEvent);
4089+ if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
4090+ getEntities()->mousePressEvent(&mappedEvent);
40294091 }
40304092
40314093 _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
@@ -4062,14 +4124,11 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { · 30 unmodified lines
40624124 event->screenPos(), event->button(),
40634125 event->buttons(), event->modifiers());
40644126
4065− if (!_aboutToQuit) {
4066− getOverlays().mouseDoublePressEvent(&mappedEvent);
4067− if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
4068− getEntities()->mouseDoublePressEvent(&mappedEvent);
4069− }
4127+ getOverlays().mouseDoublePressEvent(&mappedEvent);
4128+ if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
4129+ getEntities()->mouseDoublePressEvent(&mappedEvent);
40704130 }
40714131
4072−
40734132 // if one of our scripts have asked to capture this event, then stop processing it
40744133 if (_controllerScriptingInterface->isMouseCaptured()) {
40754134 return;
@@ -4088,10 +4147,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { · 12 unmodified lines
40884147 event->screenPos(), event->button(),
40894148 event->buttons(), event->modifiers());
40904149
4091− if (!_aboutToQuit) {
4092− getOverlays().mouseReleaseEvent(&mappedEvent);
4093− getEntities()->mouseReleaseEvent(&mappedEvent);
4094− }
4150+ getOverlays().mouseReleaseEvent(&mappedEvent);
4151+ getEntities()->mouseReleaseEvent(&mappedEvent);
40954152
40964153 _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
40974154
@@ -4242,7 +4299,6 @@ bool Application::shouldPaint() const { · 144 unmodified lines
42424299 return false;
42434300 }
42444301
4245−
42464302 auto displayPlugin = getActiveDisplayPlugin();
42474303
42484304 #ifdef DEBUG_PAINT_DELAY
@@ -4512,7 +4568,6 @@ void Application::idle() { · 263 unmodified lines
45124568 if (offscreenUi->size() != fromGlm(uiSize)) {
45134569 qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
45144570 offscreenUi->resize(fromGlm(uiSize));
4515− _offscreenContext->makeCurrent();
45164571 }
45174572 }
45184573
@@ -4550,11 +4605,14 @@ void Application::idle() { · 31 unmodified lines
45504605 _lastTimeUpdated.start();
45514606
45524607 // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
4553− if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {
4554− _keyboardMouseDevice->pluginFocusOutEvent();
4555− _keyboardDeviceHasFocus = false;
4556− } else if (offscreenUi && offscreenUi->getWindow()->activeFocusItem() == offscreenUi->getRootItem()) {
4557− _keyboardDeviceHasFocus = true;
4608+ if (offscreenUi && offscreenUi->getWindow()) {
4609+ auto activeFocusItem = offscreenUi->getWindow()->activeFocusItem();
4610+ if (_keyboardDeviceHasFocus && activeFocusItem != offscreenUi->getRootItem()) {
4611+ _keyboardMouseDevice->pluginFocusOutEvent();
4612+ _keyboardDeviceHasFocus = false;
4613+ } else if (activeFocusItem == offscreenUi->getRootItem()) {
4614+ _keyboardDeviceHasFocus = true;
4615+ }
45584616 }
45594617
45604618 checkChangeCursor();
@@ -4567,10 +4625,6 @@ void Application::idle() { · 6 unmodified lines
45674625 bool showWarnings = getLogger()->extraDebugging();
45684626 PerformanceWarning warn(showWarnings, "idle()");
45694627
4570− if (!_offscreenContext->makeCurrent()) {
4571− qFatal("Unable to make main thread context current");
4572− }
4573−
45744628 {
45754629 _gameWorkload.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition());
45764630 _gameWorkload._engine->run();
@@ -4719,7 +4773,7 @@ bool Application::exportEntities(const QString& filename, · 142 unmodified lines
47194773 exportTree->createRootElement();
47204774 glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);
47214775 bool success = true;
4722− entityTree->withReadLock([&] {
4776+ entityTree->withReadLock([entityIDs, entityTree, givenOffset, myAvatarID, &root, &entities, &success, &exportTree] {
47234777 for (auto entityID : entityIDs) { // Gather entities and properties.
47244778 auto entityItem = entityTree->findEntityByEntityItemID(entityID);
47254779 if (!entityItem) {
@@ -4839,6 +4893,7 @@ void Application::loadSettings() { · 113 unmodified lines
48394893 }
48404894
48414895 isFirstPerson = (qApp->isHMDMode());
4896+
48424897 } else {
48434898 // if this is not the first run, the camera will be initialized differently depending on user settings
48444899
@@ -4897,7 +4952,6 @@ QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) { · 52 unmodified lines
48974952 }
48984953
48994954 void Application::init() {
4900− _offscreenContext->makeCurrent();
49014955 // Make sure Login state is up to date
49024956 DependencyManager::get<DialogsManager>()->toggleLoginDialog();
49034957 if (!DISABLE_DEFERRED) {
@@ -5007,8 +5061,9 @@ void Application::updateLOD(float deltaTime) const { · 103 unmodified lines
50075061 float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
50085062 float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
50095063 float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
5064+ float batchTime = getGPUContext()->getFrameTimerBatchAverage();
50105065 auto lodManager = DependencyManager::get<LODManager>();
5011− lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime);
5066+ lodManager->setRenderTimes(presentTime, engineRunTime, batchTime, gpuTime);
50125067 lodManager->autoAdjustLOD(deltaTime);
50135068 } else {
50145069 DependencyManager::get<LODManager>()->resetLODAdjust();
@@ -5246,6 +5301,7 @@ void Application::resetPhysicsReadyInformation() { · 231 unmodified lines
52465301 _nearbyEntitiesCountAtLastPhysicsCheck = 0;
52475302 _nearbyEntitiesStabilityCount = 0;
52485303 _physicsEnabled = false;
5304+ _octreeProcessor.startEntitySequence();
52495305 }
52505306
52515307
@@ -5259,6 +5315,7 @@ void Application::reloadResourceCaches() { · 7 unmodified lines
52595315 queryOctree(NodeType::EntityServer, PacketType::EntityQuery);
52605316
52615317 DependencyManager::get<AssetClient>()->clearCache();
5318+ DependencyManager::get<ScriptCache>()->clearCache();
52625319
52635320 DependencyManager::get<AnimationCache>()->refreshAll();
52645321 DependencyManager::get<ModelCache>()->refreshAll();
@@ -5286,7 +5343,7 @@ void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm · 21 unmodified lines
52865343 _keyboardFocusHighlight->setPulseMin(0.5);
52875344 _keyboardFocusHighlight->setPulseMax(1.0);
52885345 _keyboardFocusHighlight->setColorPulse(1.0);
5289− _keyboardFocusHighlight->setIgnoreRayIntersection(true);
5346+ _keyboardFocusHighlight->setIgnorePickIntersection(true);
52905347 _keyboardFocusHighlight->setDrawInFront(false);
52915348 _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight);
52925349 }
@@ -5466,6 +5523,10 @@ static bool domainLoadingInProgress = false; · 173 unmodified lines
54665523 void Application::update(float deltaTime) {
54675524 PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1);
54685525
5526+ if (_aboutToQuit) {
5527+ return;
5528+ }
5529+
54695530 if (!_physicsEnabled) {
54705531 if (!domainLoadingInProgress) {
54715532 PROFILE_ASYNC_BEGIN(app, "Scene Loading", "");
@@ -5475,17 +5536,16 @@ void Application::update(float deltaTime) { · 3 unmodified lines
54755536 // we haven't yet enabled physics. we wait until we think we have all the collision information
54765537 // for nearby entities before starting bullet up.
54775538 quint64 now = usecTimestampNow();
5478− const int PHYSICS_CHECK_TIMEOUT = 2 * USECS_PER_SECOND;
5479−
5480− if (now - _lastPhysicsCheckTime > PHYSICS_CHECK_TIMEOUT || _fullSceneReceivedCounter > _fullSceneCounterAtLastPhysicsCheck) {
5539+ if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) {
54815540 // we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
54825541 _lastPhysicsCheckTime = now;
54835542 _fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
5543+ _lastQueriedViews.clear(); // Force new view.
54845544
54855545 // process octree stats packets are sent in between full sends of a scene (this isn't currently true).
54865546 // We keep physics disabled until we've received a full scene and everything near the avatar in that
54875547 // scene is ready to compute its collision shape.
5488− if (nearbyEntitiesAreReadyForPhysics() && getMyAvatar()->isReadyForPhysics()) {
5548+ if (getMyAvatar()->isReadyForPhysics()) {
54895549 _physicsEnabled = true;
54905550 getMyAvatar()->updateMotionBehaviorFromMenu();
54915551 }
@@ -5690,12 +5750,10 @@ void Application::update(float deltaTime) { · 198 unmodified lines
56905750
56915751 t1 = std::chrono::high_resolution_clock::now();
56925752
5693− avatarManager->getObjectsToRemoveFromPhysics(motionStates);
5694− _physicsEngine->removeObjects(motionStates);
5695− avatarManager->getObjectsToAddToPhysics(motionStates);
5696− _physicsEngine->addObjects(motionStates);
5697− avatarManager->getObjectsToChange(motionStates);
5698− _physicsEngine->changeObjects(motionStates);
5753+ PhysicsEngine::Transaction transaction;
5754+ avatarManager->buildPhysicsTransaction(transaction);
5755+ _physicsEngine->processTransaction(transaction);
5756+ avatarManager->handleProcessedPhysicsTransaction(transaction);
56995757
57005758 myAvatar->prepareForPhysicsSimulation();
57015759 _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) {
@@ -5732,15 +5790,13 @@ void Application::update(float deltaTime) { · 30 unmodified lines
57325790 _entitySimulation->handleDeactivatedMotionStates(deactivations);
57335791 });
57345792
5735− if (!_aboutToQuit) {
5736− // handleCollisionEvents() AFTER handleChangedMotionStates()
5737− {
5738− PROFILE_RANGE(simulation_physics, "CollisionEvents");
5739− avatarManager->handleCollisionEvents(collisionEvents);
5740− // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
5741− // deadlock.)
5742− _entitySimulation->handleCollisionEvents(collisionEvents);
5743− }
5793+ // handleCollisionEvents() AFTER handleChangedMotionStates()
5794+ {
5795+ PROFILE_RANGE(simulation_physics, "CollisionEvents");
5796+ avatarManager->handleCollisionEvents(collisionEvents);
5797+ // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
5798+ // deadlock.)
5799+ _entitySimulation->handleCollisionEvents(collisionEvents);
57445800 }
57455801
57465802 {
@@ -5758,24 +5814,20 @@ void Application::update(float deltaTime) { · 11 unmodified lines
57585814 }
57595815 auto t4 = std::chrono::high_resolution_clock::now();
57605816
5761− if (!_aboutToQuit) {
5762− // NOTE: the getEntities()->update() call below will wait for lock
5763− // and will provide non-physical entity motion
5764− getEntities()->update(true); // update the models...
5765− }
5817+ // NOTE: the getEntities()->update() call below will wait for lock
5818+ // and will provide non-physical entity motion
5819+ getEntities()->update(true); // update the models...
57665820
57675821 auto t5 = std::chrono::high_resolution_clock::now();
57685822
57695823 workload::Timings timings(6);
5770− timings[0] = (t4 - t0);
5771− timings[1] = (t5 - t4);
5772− timings[2] = (t4 - t3);
5773− timings[3] = (t3 - t2);
5774− timings[4] = (t2 - t1);
5775− timings[5] = (t1 - t0);
5776−
5824+ timings[0] = t1 - t0; // prePhysics entities
5825+ timings[1] = t2 - t1; // prePhysics avatars
5826+ timings[2] = t3 - t2; // stepPhysics
5827+ timings[3] = t4 - t3; // postPhysics
5828+ timings[4] = t5 - t4; // non-physical kinematics
5829+ timings[5] = workload::Timing_ns((int32_t)(NSECS_PER_SECOND * deltaTime)); // game loop duration
57775830 _gameWorkload.updateSimulationTimings(timings);
5778−
57795831 }
57805832 }
57815833 } else {
@@ -5965,7 +6017,7 @@ void Application::updateRenderArgs(float deltaTime) { · 183 unmodified lines
59656017 _viewFrustum.calculate();
59666018 }
59676019 appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(),
5968− lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
6020+ lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE,
59696021 RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
59706022 appRenderArgs._renderArgs._scene = getMain3DScene();
59716023
@@ -6127,11 +6179,23 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { · 155 unmodified lines
61276179 return; // bail early if settings are not loaded
61286180 }
61296181
6130− _octreeQuery.setConicalViews(_conicalViews);
6182+ const bool isModifiedQuery = !_physicsEnabled;
6183+ if (isModifiedQuery) {
6184+ // Create modified view that is a simple sphere.
6185+ ConicalViewFrustum sphericalView;
6186+ sphericalView.setSimpleRadius(INITIAL_QUERY_RADIUS);
6187+ _octreeQuery.setConicalViews({ sphericalView });
6188+ _octreeQuery.setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
6189+ static constexpr float MIN_LOD_ADJUST = -20.0f;
6190+ _octreeQuery.setBoundaryLevelAdjust(MIN_LOD_ADJUST);
6191+ } else {
6192+ _octreeQuery.setConicalViews(_conicalViews);
6193+ auto lodManager = DependencyManager::get<LODManager>();
6194+ _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
6195+ _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
6196+ }
6197+ _octreeQuery.setReportInitialCompletion(isModifiedQuery);
61316198
6132− auto lodManager = DependencyManager::get<LODManager>();
6133− _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
6134− _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
61356199
61366200 auto nodeList = DependencyManager::get<NodeList>();
61376201
@@ -6156,6 +6220,10 @@ bool Application::isHMDMode() const { · 18 unmodified lines
61566220 return getActiveDisplayPlugin()->isHmd();
61576221 }
61586222
6223+float Application::getNumCollisionObjects() const {
6224+ return _physicsEngine ? _physicsEngine->getNumCollisionObjects() : 0;
6225+}
6226+
61596227 float Application::getTargetRenderFrameRate() const { return getActiveDisplayPlugin()->getTargetFrameRate(); }
61606228
61616229 QRect Application::getDesirableApplicationGeometry() const {
@@ -6188,6 +6256,9 @@ PickRay Application::computePickRay(float x, float y) const { · 26 unmodified lines
61886256 getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction);
61896257 } else {
61906258 pickPoint /= getCanvasSize();
6259+ if (_myCamera.getMode() == CameraMode::CAMERA_MODE_MIRROR) {
6260+ pickPoint.x = 1.0f - pickPoint.x;
6261+ }
61916262 QMutexLocker viewLocker(&_viewMutex);
61926263 _viewFrustum.computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction);
61936264 }
@@ -6292,7 +6363,6 @@ void Application::clearDomainOctreeDetails() { · 98 unmodified lines
62926363 }
62936364
62946365 void Application::clearDomainAvatars() {
6295− getMyAvatar()->setAvatarEntityDataChanged(true); // to recreate worn entities
62966366 DependencyManager::get<AvatarManager>()->clearOtherAvatars();
62976367 }
62986368
@@ -6310,7 +6380,6 @@ void Application::domainURLChanged(QUrl domainURL) { · 11 unmodified lines
63106380 void Application::resettingDomain() {
63116381 _notifiedPacketVersionMismatchThisDomain = false;
63126382
6313− auto nodeList = DependencyManager::get<NodeList>();
63146383 clearDomainOctreeDetails();
63156384 }
63166385
@@ -6358,8 +6427,8 @@ void Application::nodeActivated(SharedNodePointer node) { · 41 unmodified lines
63586427 if (_avatarOverrideUrl.isValid()) {
63596428 getMyAvatar()->useFullAvatarURL(_avatarOverrideUrl);
63606429 }
6361− static const QUrl empty{};
6362− if (getMyAvatar()->getFullAvatarURLFromPreferences() != getMyAvatar()->cannonicalSkeletonModelURL(empty)) {
6430+
6431+ if (getMyAvatar()->getFullAvatarURLFromPreferences() != getMyAvatar()->getSkeletonModelURL()) {
63636432 getMyAvatar()->resetFullAvatarURL();
63646433 }
63656434 getMyAvatar()->markIdentityDataChanged();
@@ -6523,9 +6592,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 157 unmodified lines
65236592 entityScriptingInterface->setPacketSender(&_entityEditSender);
65246593 entityScriptingInterface->setEntityTree(getEntities()->getTree());
65256594
6526− // give the script engine to the RecordingScriptingInterface for its callbacks
6527− DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(scriptEngine);
6528−
65296595 if (property(hifi::properties::TEST).isValid()) {
65306596 scriptEngine->registerGlobalObject("Test", TestScriptingInterface::getInstance());
65316597 }
@@ -6577,11 +6643,12 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 45 unmodified lines
65776643 scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
65786644 LocationScriptingInterface::locationSetter);
65796645
6646+ bool clientScript = scriptEngine->isClientScript();
6647+ scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor);
65806648 #if !defined(Q_OS_ANDROID)
6581− scriptEngine->registerFunction("OverlayWebWindow", QmlWebWindowClass::constructor);
6649+ scriptEngine->registerFunction("OverlayWebWindow", clientScript ? QmlWebWindowClass::constructor : QmlWebWindowClass::restricted_constructor);
65826650 #endif
6583− scriptEngine->registerFunction("OverlayWindow", QmlWindowClass::constructor);
6584− scriptEngine->registerFunction("QmlFragment", QmlFragmentClass::constructor);
6651+ scriptEngine->registerFunction("QmlFragment", clientScript ? QmlFragmentClass::constructor : QmlFragmentClass::restricted_constructor);
65856652
65866653 scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
65876654 scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get<DesktopPreviewProvider>().data());
@@ -6599,10 +6666,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 11 unmodified lines
65996666 scriptEngine->registerGlobalObject("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
66006667
66016668 // Caches
6602− scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
6603− scriptEngine->registerGlobalObject("TextureCache", DependencyManager::get<TextureCache>().data());
6604− scriptEngine->registerGlobalObject("ModelCache", DependencyManager::get<ModelCache>().data());
6605− scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());
6669+ scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCacheScriptingInterface>().data());
6670+ scriptEngine->registerGlobalObject("TextureCache", DependencyManager::get<TextureCacheScriptingInterface>().data());
6671+ scriptEngine->registerGlobalObject("ModelCache", DependencyManager::get<ModelCacheScriptingInterface>().data());
6672+ scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
66066673
66076674 scriptEngine->registerGlobalObject("DialogsManager", _dialogsManagerScriptingInterface);
66086675
@@ -6663,19 +6730,16 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 54 unmodified lines
66636730
66646731 registerInteractiveWindowMetaType(scriptEngine.data());
66656732
6666− DependencyManager::get<PickScriptingInterface>()->registerMetaTypes(scriptEngine.data());
6733+ auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();
6734+ pickScriptingInterface->registerMetaTypes(scriptEngine.data());
66676735
66686736 // connect this script engines printedMessage signal to the global ScriptEngines these various messages
6669− connect(scriptEngine.data(), &ScriptEngine::printedMessage,
6670− DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onPrintedMessage);
6671− connect(scriptEngine.data(), &ScriptEngine::errorMessage,
6672− DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onErrorMessage);
6673− connect(scriptEngine.data(), &ScriptEngine::warningMessage,
6674− DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onWarningMessage);
6675− connect(scriptEngine.data(), &ScriptEngine::infoMessage,
6676− DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onInfoMessage);
6677− connect(scriptEngine.data(), &ScriptEngine::clearDebugWindow,
6678− DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onClearDebugWindow);
6737+ auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
6738+ connect(scriptEngine.data(), &ScriptEngine::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage);
6739+ connect(scriptEngine.data(), &ScriptEngine::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage);
6740+ connect(scriptEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage);
6741+ connect(scriptEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage);
6742+ connect(scriptEngine.data(), &ScriptEngine::clearDebugWindow, scriptEngines, &ScriptEngines::onClearDebugWindow);
66796743
66806744 }
66816745
@@ -6983,10 +7047,9 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const · 301 unmodified lines
69837047 }
69847048
69857049 void Application::showScriptLogs() {
6986− auto scriptEngines = DependencyManager::get<ScriptEngines>();
69877050 QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
69887051 defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js");
6989− scriptEngines->loadScript(defaultScriptsLoc.toString());
7052+ DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
69907053 }
69917054
69927055 void Application::showAssetServerWidget(QString filePath) {
@@ -7239,6 +7302,8 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { · 246 unmodified lines
72397302 }
72407303 properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar.
72417304 properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions.
7305+ bool grabbable = (Menu::getInstance()->isOptionChecked(MenuOption::CreateEntitiesGrabbable));
7306+ properties.setUserData(grabbable ? GRABBABLE_USER_DATA : NOT_GRABBABLE_USER_DATA);
72427307 glm::vec3 positionOffset = getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f));
72437308 properties.setPosition(getMyAvatar()->getWorldPosition() + positionOffset);
72447309 properties.setRotation(getMyAvatar()->getWorldOrientation());
@@ -7281,7 +7346,6 @@ void Application::addAssetToWorldCheckModelSize() { · 36 unmodified lines
72817346 auto name = properties.getName();
72827347 auto dimensions = properties.getDimensions();
72837348
7284− const QString GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":true}}";
72857349 bool doResize = false;
72867350
72877351 const glm::vec3 DEFAULT_DIMENSIONS = glm::vec3(0.1f, 0.1f, 0.1f);
@@ -7325,7 +7389,8 @@ void Application::addAssetToWorldCheckModelSize() { · 37 unmodified lines
73257389 if (!name.toLower().endsWith(PNG_EXTENSION) && !name.toLower().endsWith(JPG_EXTENSION)) {
73267390 properties.setCollisionless(false);
73277391 }
7328− properties.setUserData(GRABBABLE_USER_DATA);
7392+ bool grabbable = (Menu::getInstance()->isOptionChecked(MenuOption::CreateEntitiesGrabbable));
7393+ properties.setUserData(grabbable ? GRABBABLE_USER_DATA : NOT_GRABBABLE_USER_DATA);
73297394 properties.setLastEdited(usecTimestampNow());
73307395 entityScriptingInterface->editEntity(entityID, properties);
73317396 }
@@ -7550,7 +7615,6 @@ void Application::openUrl(const QUrl& url) const { · 218 unmodified lines
75507615 }
75517616
75527617 void Application::loadDialog() {
7553− auto scriptEngines = DependencyManager::get<ScriptEngines>();
75547618 ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_glWidget, tr("Open Script"),
75557619 getPreviousScriptLocation(),
75567620 tr("JavaScript Files (*.js)"));
@@ -8273,7 +8337,7 @@ QOpenGLContext* Application::getPrimaryContext() { · 716 unmodified lines
82738337 }
82748338
82758339 bool Application::makeRenderingContextCurrent() {
8276− return _offscreenContext->makeCurrent();
8340+ return true;
82778341 }
82788342
82798343 bool Application::isForeground() const {