} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionTwoThird)) { return 0.666f; } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionHalf)) { return 0.5f; } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionThird)) { return 0.333f; } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionQuarter)) { return 0.25f; } else { return 1.0f; }} void Application::notifyPacketVersionMismatch() { if (!_notifiedPacketVersionMismatchThisDomain) { _notifiedPacketVersionMismatchThisDomain = true; QString message = "The location you are visiting is running an incompatible server version.\n"; message += "Content may not display properly."; OffscreenUi::warning("", message); }} void Application::checkSkeleton() const { if (getMyAvatar()->getSkeletonModel()->isActive() && !getMyAvatar()->getSkeletonModel()->hasSkeleton()) { qCDebug(interfaceapp) << "MyAvatar model has no skeleton"; QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded..."; OffscreenUi::warning("", message); getMyAvatar()->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME); } else { _physicsEngine->setCharacterController(getMyAvatar()->getCharacterController()); }} void Application::activeChanged(Qt::ApplicationState state) { switch (state) { case Qt::ApplicationActive: _isForeground = true; break; case Qt::ApplicationSuspended: case Qt::ApplicationHidden: case Qt::ApplicationInactive: default: _isForeground = false; break; }} void Application::postLambdaEvent(std::function<void()> f) { if (this->thread() == QThread::currentThread()) { f(); } else { QCoreApplication::postEvent(this, new LambdaEvent(f)); }} void Application::initPlugins(const QStringList& arguments) { QCommandLineOption display("display", "Preferred displays", "displays"); QCommandLineOption disableDisplays("disable-displays", "Displays to disable", "displays"); QCommandLineOption disableInputs("disable-inputs", "Inputs to disable", "inputs"); QCommandLineParser parser; parser.addOption(display); parser.addOption(disableDisplays); parser.addOption(disableInputs); parser.parse(arguments); if (parser.isSet(display)) { auto preferredDisplays = parser.value(display).split(',', QString::SkipEmptyParts); qInfo() << "Setting prefered display plugins:" << preferredDisplays; PluginManager::getInstance()->setPreferredDisplayPlugins(preferredDisplays); } if (parser.isSet(disableDisplays)) { auto disabledDisplays = parser.value(disableDisplays).split(',', QString::SkipEmptyParts); qInfo() << "Disabling following display plugins:" << disabledDisplays; PluginManager::getInstance()->disableDisplays(disabledDisplays); } if (parser.isSet(disableInputs)) { auto disabledInputs = parser.value(disableInputs).split(',', QString::SkipEmptyParts); qInfo() << "Disabling following input plugins:" << disabledInputs; PluginManager::getInstance()->disableInputs(disabledInputs); }} void Application::shutdownPlugins() {} glm::uvec2 Application::getCanvasSize() const { return glm::uvec2(_glWidget->width(), _glWidget->height());} QRect Application::getRenderingGeometry() const { auto geometry = _glWidget->geometry(); auto topLeft = geometry.topLeft(); auto topLeftScreen = _glWidget->mapToGlobal(topLeft); geometry.moveTopLeft(topLeftScreen); return geometry;} glm::uvec2 Application::getUiSize() const { static const uint MIN_SIZE = 1; glm::uvec2 result(MIN_SIZE); if (_displayPlugin) { result = getActiveDisplayPlugin()->getRecommendedUiSize(); } return result;} QRect Application::getRecommendedOverlayRect() const { auto uiSize = getUiSize(); QRect result(0, 0, uiSize.x, uiSize.y); if (_displayPlugin) { result = getActiveDisplayPlugin()->getRecommendedOverlayRect(); } return result;} QSize Application::getDeviceSize() const { static const int MIN_SIZE = 1; QSize result(MIN_SIZE, MIN_SIZE); if (_displayPlugin) { result = fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize()); } return result;} bool Application::isThrottleRendering() const { if (_displayPlugin) { return getActiveDisplayPlugin()->isThrottled(); } return false;} bool Application::hasFocus() const { if (_displayPlugin) { return getActiveDisplayPlugin()->hasFocus(); } return (QApplication::activeWindow() != nullptr);} glm::vec2 Application::getViewportDimensions() const { return toGlm(getDeviceSize());} void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) { if (maxOctreePPS != _maxOctreePPS) { _maxOctreePPS = maxOctreePPS; maxOctreePacketsPerSecond.set(_maxOctreePPS); }} int Application::getMaxOctreePacketsPerSecond() const { return _maxOctreePPS;} qreal Application::getDevicePixelRatio() { return (_window && _window->windowHandle()) ? _window->windowHandle()->devicePixelRatio() : 1.0;} DisplayPluginPointer Application::getActiveDisplayPlugin() const { if (QThread::currentThread() != thread()) { std::unique_lock<std::mutex> lock(_displayPluginLock); return _displayPlugin; } if (!_displayPlugin) { const_cast<Application*>(this)->updateDisplayMode(); Q_ASSERT(_displayPlugin); } return _displayPlugin;} static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { auto menu = Menu::getInstance(); QString name = displayPlugin->getName(); auto grouping = displayPlugin->getGrouping(); QString groupingMenu { "" }; Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); // assign the meny grouping based on plugin grouping switch (grouping) { case Plugin::ADVANCED: groupingMenu = "Advanced"; break; case Plugin::DEVELOPER: groupingMenu = "Developer"; break; default: groupingMenu = "Standard"; break; } static QActionGroup* displayPluginGroup = nullptr; if (!displayPluginGroup) { displayPluginGroup = new QActionGroup(menu); displayPluginGroup->setExclusive(true); } auto parent = menu->getMenu(MenuOption::OutputMenu); auto action = menu->addActionToQMenuAndActionHash(parent, name, 0, qApp, SLOT(updateDisplayMode()), QAction::NoRole, Menu::UNSPECIFIED_POSITION, groupingMenu); action->setCheckable(true); action->setChecked(active); displayPluginGroup->addAction(action); Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name));} void Application::updateDisplayMode() { // Unsafe to call this method from anything but the main thread if (QThread::currentThread() != thread()) { qFatal("Attempted to switch display plugins from a non-main thread"); } // Some plugins *cough* Oculus *cough* process message events from inside their // display function, and we don't want to change the display plugin underneath // the paintGL call, so we need to guard against that // The current oculus runtime doesn't do this anymore if (_inPaint) { qFatal("Attempted to switch display plugins while in painting"); } auto menu = Menu::getInstance(); auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); static std::once_flag once; std::call_once(once, [&] { bool first = true; // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; DisplayPluginList developer; foreach(auto displayPlugin, displayPlugins) { auto grouping = displayPlugin->getGrouping(); switch (grouping) { case Plugin::ADVANCED: advanced.push_back(displayPlugin); break; case Plugin::DEVELOPER: developer.push_back(displayPlugin); break; default: standard.push_back(displayPlugin); break; } } // concatenate the groupings into a single list in the order: standard, advanced, developer standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); foreach(auto displayPlugin, standard) { addDisplayPluginToMenu(displayPlugin, first); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); first = false; } // after all plugins have been added to the menu, add a separator to the menu auto menu = Menu::getInstance(); auto parent = menu->getMenu(MenuOption::OutputMenu); parent->addSeparator(); }); // Default to the first item on the list, in case none of the menu items match DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0); foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { QString name = displayPlugin->getName(); QAction* action = menu->getActionForOption(name); // Menu might have been removed if the display plugin lost if (!action) { continue; } if (action->isChecked()) { newDisplayPlugin = displayPlugin; break; } } if (newDisplayPlugin == _displayPlugin) { return; } UserActivityLogger::getInstance().logAction("changed_display_mode", { { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" } }); auto offscreenUi = DependencyManager::get<OffscreenUi>(); // Make the switch atomic from the perspective of other threads { std::unique_lock<std::mutex> lock(_displayPluginLock); auto oldDisplayPlugin = _displayPlugin; if (_displayPlugin) { _displayPlugin->deactivate(); } // FIXME probably excessive and useless context switching _offscreenContext->makeCurrent(); bool active = newDisplayPlugin->activate(); if (!active) { // If the new plugin fails to activate, fallback to last display qWarning() << "Failed to activate display: " << newDisplayPlugin->getName(); newDisplayPlugin = oldDisplayPlugin; if (newDisplayPlugin) { qWarning() << "Falling back to last display: " << newDisplayPlugin->getName(); active = newDisplayPlugin->activate(); } // If there is no last display, or // If the last display fails to activate, fallback to desktop if (!active) { newDisplayPlugin = displayPlugins.at(0); qWarning() << "Falling back to display: " << newDisplayPlugin->getName(); active = newDisplayPlugin->activate(); } if (!active) { qFatal("Failed to activate fallback plugin"); } } _offscreenContext->makeCurrent(); offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); _offscreenContext->makeCurrent(); getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; } emit activeDisplayPluginChanged(); // reset the avatar, to set head and hand palms back to a reasonable default pose. getMyAvatar()->reset(false); Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");} mat4 Application::getEyeProjection(int eye) const { QMutexLocker viewLocker(&_viewMutex); if (isHMDMode()) { return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection()); } return _viewFrustum.getProjection();} mat4 Application::getEyeOffset(int eye) const { // FIXME invert? return getActiveDisplayPlugin()->getEyeToHeadTransform((Eye)eye);} mat4 Application::getHMDSensorPose() const { if (isHMDMode()) { return getActiveDisplayPlugin()->getHeadPose(); } return mat4();} void Application::deadlockApplication() { qCDebug(interfaceapp) << "Intentionally deadlocked Interface"; // Using a loop that will *technically* eventually exit (in ~600 billion years) // to avoid compiler warnings about a loop that will never exit for (uint64_t i = 1; i != 0; ++i) { QThread::sleep(1); }} void Application::setActiveDisplayPlugin(const QString& pluginName) { auto menu = Menu::getInstance(); foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { QString name = displayPlugin->getName(); QAction* action = menu->getActionForOption(name); if (pluginName == name) { action->setChecked(true); } } updateDisplayMode();} void Application::handleLocalServerConnection() const { auto server = qobject_cast<QLocalServer*>(sender()); qDebug() << "Got connection on local server from additional instance - waiting for parameters"; auto socket = server->nextPendingConnection(); connect(socket, &QLocalSocket::readyRead, this, &Application::readArgumentsFromLocalSocket); qApp->getWindow()->raise(); qApp->getWindow()->activateWindow();} void Application::readArgumentsFromLocalSocket() const { auto socket = qobject_cast<QLocalSocket*>(sender()); auto message = socket->readAll(); socket->deleteLater(); qDebug() << "Read from connection: " << message; // If we received a message, try to open it as a URL if (message.length() > 0) { qApp->openUrl(QString::fromUtf8(message)); }} void Application::showDesktop() { Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, true);} CompositorHelper& Application::getApplicationCompositor() const { return *DependencyManager::get<CompositorHelper>();} // virtual functions required for PluginContainerui::Menu* Application::getPrimaryMenu() { auto appMenu = _window->menuBar(); auto uiMenu = dynamic_cast<ui::Menu*>(appMenu); return uiMenu;} void Application::showDisplayPluginsTools(bool show) { DependencyManager::get<DialogsManager>()->hmdTools(show);} GLWidget* Application::getPrimaryWidget() { return _glWidget;} MainWindow* Application::getPrimaryWindow() { return getWindow();} QOpenGLContext* Application::getPrimaryContext() { return _glWidget->context()->contextHandle();} bool Application::makeRenderingContextCurrent() { return _offscreenContext->makeCurrent();} void Application::releaseSceneTexture(const gpu::TexturePointer& texture) { Q_ASSERT(QThread::currentThread() == thread()); auto& framebufferMap = _lockedFramebufferMap; Q_ASSERT(framebufferMap.contains(texture)); auto framebufferPointer = framebufferMap[texture]; framebufferMap.remove(texture); auto framebufferCache = DependencyManager::get<FramebufferCache>(); framebufferCache->releaseFramebuffer(framebufferPointer);} void Application::releaseOverlayTexture(const gpu::TexturePointer& texture) { _applicationOverlay.releaseOverlay(texture);} bool Application::isForeground() const { return _isForeground && !_window->isMinimized(); }Lines 5001–5476 of 5476. Previous lines
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionTwoThird)) { return 0.666f; } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionHalf)) { return 0.5f; } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionThird)) { return 0.333f; } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionQuarter)) { return 0.25f; } else { return 1.0f; } } void Application::notifyPacketVersionMismatch() { if (!_notifiedPacketVersionMismatchThisDomain) { _notifiedPacketVersionMismatchThisDomain = true; QString message = "The location you are visiting is running an incompatible server version.\n"; message += "Content may not display properly."; OffscreenUi::warning("", message); } } void Application::checkSkeleton() const { if (getMyAvatar()->getSkeletonModel()->isActive() && !getMyAvatar()->getSkeletonModel()->hasSkeleton()) { qCDebug(interfaceapp) << "MyAvatar model has no skeleton"; QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded..."; OffscreenUi::warning("", message); getMyAvatar()->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME); } else { _physicsEngine->setCharacterController(getMyAvatar()->getCharacterController()); } } void Application::activeChanged(Qt::ApplicationState state) { switch (state) { case Qt::ApplicationActive: _isForeground = true; break; case Qt::ApplicationSuspended: case Qt::ApplicationHidden: case Qt::ApplicationInactive: default: _isForeground = false; break; } } void Application::postLambdaEvent(std::function<void()> f) { if (this->thread() == QThread::currentThread()) { f(); } else { QCoreApplication::postEvent(this, new LambdaEvent(f)); } } void Application::initPlugins(const QStringList& arguments) { QCommandLineOption display("display", "Preferred displays", "displays"); QCommandLineOption disableDisplays("disable-displays", "Displays to disable", "displays"); QCommandLineOption disableInputs("disable-inputs", "Inputs to disable", "inputs"); QCommandLineParser parser; parser.addOption(display); parser.addOption(disableDisplays); parser.addOption(disableInputs); parser.parse(arguments); if (parser.isSet(display)) { auto preferredDisplays = parser.value(display).split(',', QString::SkipEmptyParts); qInfo() << "Setting prefered display plugins:" << preferredDisplays; PluginManager::getInstance()->setPreferredDisplayPlugins(preferredDisplays); } if (parser.isSet(disableDisplays)) { auto disabledDisplays = parser.value(disableDisplays).split(',', QString::SkipEmptyParts); qInfo() << "Disabling following display plugins:" << disabledDisplays; PluginManager::getInstance()->disableDisplays(disabledDisplays); } if (parser.isSet(disableInputs)) { auto disabledInputs = parser.value(disableInputs).split(',', QString::SkipEmptyParts); qInfo() << "Disabling following input plugins:" << disabledInputs; PluginManager::getInstance()->disableInputs(disabledInputs); } } void Application::shutdownPlugins() { } glm::uvec2 Application::getCanvasSize() const { return glm::uvec2(_glWidget->width(), _glWidget->height()); } QRect Application::getRenderingGeometry() const { auto geometry = _glWidget->geometry(); auto topLeft = geometry.topLeft(); auto topLeftScreen = _glWidget->mapToGlobal(topLeft); geometry.moveTopLeft(topLeftScreen); return geometry; } glm::uvec2 Application::getUiSize() const { static const uint MIN_SIZE = 1; glm::uvec2 result(MIN_SIZE); if (_displayPlugin) { result = getActiveDisplayPlugin()->getRecommendedUiSize(); } return result; } QRect Application::getRecommendedOverlayRect() const { auto uiSize = getUiSize(); QRect result(0, 0, uiSize.x, uiSize.y); if (_displayPlugin) { result = getActiveDisplayPlugin()->getRecommendedOverlayRect(); } return result; } QSize Application::getDeviceSize() const { static const int MIN_SIZE = 1; QSize result(MIN_SIZE, MIN_SIZE); if (_displayPlugin) { result = fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize()); } return result; } bool Application::isThrottleRendering() const { if (_displayPlugin) { return getActiveDisplayPlugin()->isThrottled(); } return false; } bool Application::hasFocus() const { if (_displayPlugin) { return getActiveDisplayPlugin()->hasFocus(); } return (QApplication::activeWindow() != nullptr); } glm::vec2 Application::getViewportDimensions() const { return toGlm(getDeviceSize()); } void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) { if (maxOctreePPS != _maxOctreePPS) { _maxOctreePPS = maxOctreePPS; maxOctreePacketsPerSecond.set(_maxOctreePPS); } } int Application::getMaxOctreePacketsPerSecond() const { return _maxOctreePPS; } qreal Application::getDevicePixelRatio() { return (_window && _window->windowHandle()) ? _window->windowHandle()->devicePixelRatio() : 1.0; } DisplayPluginPointer Application::getActiveDisplayPlugin() const { if (QThread::currentThread() != thread()) { std::unique_lock<std::mutex> lock(_displayPluginLock); return _displayPlugin; } if (!_displayPlugin) { const_cast<Application*>(this)->updateDisplayMode(); Q_ASSERT(_displayPlugin); } return _displayPlugin; } static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { auto menu = Menu::getInstance(); QString name = displayPlugin->getName(); auto grouping = displayPlugin->getGrouping(); QString groupingMenu { "" }; Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); // assign the meny grouping based on plugin grouping switch (grouping) { case Plugin::ADVANCED: groupingMenu = "Advanced"; break; case Plugin::DEVELOPER: groupingMenu = "Developer"; break; default: groupingMenu = "Standard"; break; } static QActionGroup* displayPluginGroup = nullptr; if (!displayPluginGroup) { displayPluginGroup = new QActionGroup(menu); displayPluginGroup->setExclusive(true); } auto parent = menu->getMenu(MenuOption::OutputMenu); auto action = menu->addActionToQMenuAndActionHash(parent, name, 0, qApp, SLOT(updateDisplayMode()), QAction::NoRole, Menu::UNSPECIFIED_POSITION, groupingMenu); action->setCheckable(true); action->setChecked(active); displayPluginGroup->addAction(action); Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); } void Application::updateDisplayMode() { // Unsafe to call this method from anything but the main thread if (QThread::currentThread() != thread()) { qFatal("Attempted to switch display plugins from a non-main thread"); } // Some plugins *cough* Oculus *cough* process message events from inside their // display function, and we don't want to change the display plugin underneath // the paintGL call, so we need to guard against that // The current oculus runtime doesn't do this anymore if (_inPaint) { qFatal("Attempted to switch display plugins while in painting"); } auto menu = Menu::getInstance(); auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); static std::once_flag once; std::call_once(once, [&] { bool first = true; // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; DisplayPluginList developer; foreach(auto displayPlugin, displayPlugins) { auto grouping = displayPlugin->getGrouping(); switch (grouping) { case Plugin::ADVANCED: advanced.push_back(displayPlugin); break; case Plugin::DEVELOPER: developer.push_back(displayPlugin); break; default: standard.push_back(displayPlugin); break; } } // concatenate the groupings into a single list in the order: standard, advanced, developer standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); foreach(auto displayPlugin, standard) { addDisplayPluginToMenu(displayPlugin, first); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); first = false; } // after all plugins have been added to the menu, add a separator to the menu auto menu = Menu::getInstance(); auto parent = menu->getMenu(MenuOption::OutputMenu); parent->addSeparator(); }); // Default to the first item on the list, in case none of the menu items match DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0); foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { QString name = displayPlugin->getName(); QAction* action = menu->getActionForOption(name); // Menu might have been removed if the display plugin lost if (!action) { continue; } if (action->isChecked()) { newDisplayPlugin = displayPlugin; break; } } if (newDisplayPlugin == _displayPlugin) { return; } UserActivityLogger::getInstance().logAction("changed_display_mode", { { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" } }); auto offscreenUi = DependencyManager::get<OffscreenUi>(); // Make the switch atomic from the perspective of other threads { std::unique_lock<std::mutex> lock(_displayPluginLock); auto oldDisplayPlugin = _displayPlugin; if (_displayPlugin) { _displayPlugin->deactivate(); } // FIXME probably excessive and useless context switching _offscreenContext->makeCurrent(); bool active = newDisplayPlugin->activate(); if (!active) { // If the new plugin fails to activate, fallback to last display qWarning() << "Failed to activate display: " << newDisplayPlugin->getName(); newDisplayPlugin = oldDisplayPlugin; if (newDisplayPlugin) { qWarning() << "Falling back to last display: " << newDisplayPlugin->getName(); active = newDisplayPlugin->activate(); } // If there is no last display, or // If the last display fails to activate, fallback to desktop if (!active) { newDisplayPlugin = displayPlugins.at(0); qWarning() << "Falling back to display: " << newDisplayPlugin->getName(); active = newDisplayPlugin->activate(); } if (!active) { qFatal("Failed to activate fallback plugin"); } } _offscreenContext->makeCurrent(); offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); _offscreenContext->makeCurrent(); getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; } emit activeDisplayPluginChanged(); // reset the avatar, to set head and hand palms back to a reasonable default pose. getMyAvatar()->reset(false); Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } mat4 Application::getEyeProjection(int eye) const { QMutexLocker viewLocker(&_viewMutex); if (isHMDMode()) { return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection()); } return _viewFrustum.getProjection(); } mat4 Application::getEyeOffset(int eye) const { // FIXME invert? return getActiveDisplayPlugin()->getEyeToHeadTransform((Eye)eye); } mat4 Application::getHMDSensorPose() const { if (isHMDMode()) { return getActiveDisplayPlugin()->getHeadPose(); } return mat4(); } void Application::deadlockApplication() { qCDebug(interfaceapp) << "Intentionally deadlocked Interface"; // Using a loop that will *technically* eventually exit (in ~600 billion years) // to avoid compiler warnings about a loop that will never exit for (uint64_t i = 1; i != 0; ++i) { QThread::sleep(1); } } void Application::setActiveDisplayPlugin(const QString& pluginName) { auto menu = Menu::getInstance(); foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { QString name = displayPlugin->getName(); QAction* action = menu->getActionForOption(name); if (pluginName == name) { action->setChecked(true); } } updateDisplayMode(); } void Application::handleLocalServerConnection() const { auto server = qobject_cast<QLocalServer*>(sender()); qDebug() << "Got connection on local server from additional instance - waiting for parameters"; auto socket = server->nextPendingConnection(); connect(socket, &QLocalSocket::readyRead, this, &Application::readArgumentsFromLocalSocket); qApp->getWindow()->raise(); qApp->getWindow()->activateWindow(); } void Application::readArgumentsFromLocalSocket() const { auto socket = qobject_cast<QLocalSocket*>(sender()); auto message = socket->readAll(); socket->deleteLater(); qDebug() << "Read from connection: " << message; // If we received a message, try to open it as a URL if (message.length() > 0) { qApp->openUrl(QString::fromUtf8(message)); } } void Application::showDesktop() { Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, true); } CompositorHelper& Application::getApplicationCompositor() const { return *DependencyManager::get<CompositorHelper>(); } // virtual functions required for PluginContainer ui::Menu* Application::getPrimaryMenu() { auto appMenu = _window->menuBar(); auto uiMenu = dynamic_cast<ui::Menu*>(appMenu); return uiMenu; } void Application::showDisplayPluginsTools(bool show) { DependencyManager::get<DialogsManager>()->hmdTools(show); } GLWidget* Application::getPrimaryWidget() { return _glWidget; } MainWindow* Application::getPrimaryWindow() { return getWindow(); } QOpenGLContext* Application::getPrimaryContext() { return _glWidget->context()->contextHandle(); } bool Application::makeRenderingContextCurrent() { return _offscreenContext->makeCurrent(); } void Application::releaseSceneTexture(const gpu::TexturePointer& texture) { Q_ASSERT(QThread::currentThread() == thread()); auto& framebufferMap = _lockedFramebufferMap; Q_ASSERT(framebufferMap.contains(texture)); auto framebufferPointer = framebufferMap[texture]; framebufferMap.remove(texture); auto framebufferCache = DependencyManager::get<FramebufferCache>(); framebufferCache->releaseFramebuffer(framebufferPointer); } void Application::releaseOverlayTexture(const gpu::TexturePointer& texture) { _applicationOverlay.releaseOverlay(texture); } bool Application::isForeground() const { return _isForeground && !_window->isMinimized(); }