5476 lines · 222.9 KB · C++
RawDownload
    } 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