5476 lines · 222.9 KB · C++
RawDownload
    }} void Application::focusOutEvent(QFocusEvent* event) {    auto inputPlugins = PluginManager::getInstance()->getInputPlugins();    foreach(auto inputPlugin, inputPlugins) {        if (inputPlugin->isActive()) {            inputPlugin->pluginFocusOutEvent();        }    } // FIXME spacemouse code still needs cleanup#if 0    //SpacemouseDevice::getInstance().focusOutEvent();    //SpacemouseManager::getInstance().getDevice()->focusOutEvent();    SpacemouseManager::getInstance().ManagerFocusOutEvent();#endif     // synthesize events for keys currently pressed, since we may not get their release events    foreach (int key, _keysPressed) {        QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);        keyReleaseEvent(&keyEvent);    }    _keysPressed.clear();} void Application::maybeToggleMenuVisible(QMouseEvent* event) const {#ifndef Q_OS_MAC    // If in full screen, and our main windows menu bar is hidden, and we're close to the top of the QMainWindow    // then show the menubar.    if (_window->isFullScreen()) {        QMenuBar* menuBar = _window->menuBar();        if (menuBar) {            static const int MENU_TOGGLE_AREA = 10;            if (!menuBar->isVisible()) {                if (event->pos().y() <= MENU_TOGGLE_AREA) {                    menuBar->setVisible(true);                }            }  else {                if (event->pos().y() > MENU_TOGGLE_AREA) {                    menuBar->setVisible(false);                }            }        }    }#endif} void Application::mouseMoveEvent(QMouseEvent* event) {    PROFILE_RANGE(__FUNCTION__);     if (_aboutToQuit) {        return;    }     maybeToggleMenuVisible(event);     auto& compositor = getApplicationCompositor();    // if this is a real mouse event, and we're in HMD mode, then we should use it to move the     // compositor reticle    // handleRealMouseMoveEvent() will return true, if we shouldn't process the event further    if (!compositor.fakeEventActive() && compositor.handleRealMouseMoveEvent()) {        return; // bail    }     auto offscreenUi = DependencyManager::get<OffscreenUi>();    auto eventPosition = compositor.getMouseEventPosition(event);    QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);    auto button = event->button();    auto buttons = event->buttons();    // Determine if the ReticleClick Action is 1 and if so, fake include the LeftMouseButton    if (_reticleClickPressed) {        if (button == Qt::NoButton) {            button = Qt::LeftButton;        }        buttons |= Qt::LeftButton;    }     QMouseEvent mappedEvent(event->type(),        transformedPos,        event->screenPos(), button,        buttons, event->modifiers());     getEntities()->mouseMoveEvent(&mappedEvent);    _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isMouseCaptured()) {        return;    }     if (_keyboardMouseDevice->isActive()) {        _keyboardMouseDevice->mouseMoveEvent(event);    } } void Application::mousePressEvent(QMouseEvent* event) {    // Inhibit the menu if the user is using alt-mouse dragging    _altPressed = false;     auto offscreenUi = DependencyManager::get<OffscreenUi>();    // If we get a mouse press event it means it wasn't consumed by the offscreen UI,    // hence, we should defocus all of the offscreen UI windows, in order to allow    // keyboard shortcuts not to be swallowed by them.  In particular, WebEngineViews    // will consume all keyboard events.    offscreenUi->unfocusWindows();     auto eventPosition = getApplicationCompositor().getMouseEventPosition(event);    QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);    QMouseEvent mappedEvent(event->type(),        transformedPos,        event->screenPos(), event->button(),        event->buttons(), event->modifiers());     if (!_aboutToQuit) {        getEntities()->mousePressEvent(&mappedEvent);    }     _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isMouseCaptured()) {        return;    }      if (hasFocus()) {        if (_keyboardMouseDevice->isActive()) {            _keyboardMouseDevice->mousePressEvent(event);        }         if (event->button() == Qt::LeftButton) {            // nobody handled this - make it an action event on the _window object            HFActionEvent actionEvent(HFActionEvent::startType(),                computePickRay(mappedEvent.x(), mappedEvent.y()));            sendEvent(this, &actionEvent);         }    }} void Application::mouseDoublePressEvent(QMouseEvent* event) const {    // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isMouseCaptured()) {        return;    }     _controllerScriptingInterface->emitMouseDoublePressEvent(event);} void Application::mouseReleaseEvent(QMouseEvent* event) {     auto offscreenUi = DependencyManager::get<OffscreenUi>();    auto eventPosition = getApplicationCompositor().getMouseEventPosition(event);    QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);    QMouseEvent mappedEvent(event->type(),        transformedPos,        event->screenPos(), event->button(),        event->buttons(), event->modifiers());     if (!_aboutToQuit) {        getEntities()->mouseReleaseEvent(&mappedEvent);    }     _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isMouseCaptured()) {        return;    }     if (hasFocus()) {        if (_keyboardMouseDevice->isActive()) {            _keyboardMouseDevice->mouseReleaseEvent(event);        }         if (event->button() == Qt::LeftButton) {            // fire an action end event            HFActionEvent actionEvent(HFActionEvent::endType(),                computePickRay(mappedEvent.x(), mappedEvent.y()));            sendEvent(this, &actionEvent);        }    }} void Application::touchUpdateEvent(QTouchEvent* event) {    _altPressed = false;     if (event->type() == QEvent::TouchUpdate) {        TouchEvent thisEvent(*event, _lastTouchEvent);        _controllerScriptingInterface->emitTouchUpdateEvent(thisEvent); // send events to any registered scripts        _lastTouchEvent = thisEvent;    }     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isTouchCaptured()) {        return;    }     if (_keyboardMouseDevice->isActive()) {        _keyboardMouseDevice->touchUpdateEvent(event);    }} void Application::touchBeginEvent(QTouchEvent* event) {    _altPressed = false;    TouchEvent thisEvent(*event); // on touch begin, we don't compare to last event    _controllerScriptingInterface->emitTouchBeginEvent(thisEvent); // send events to any registered scripts     _lastTouchEvent = thisEvent; // and we reset our last event to this event before we call our update    touchUpdateEvent(event);     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isTouchCaptured()) {        return;    }     if (_keyboardMouseDevice->isActive()) {        _keyboardMouseDevice->touchBeginEvent(event);    } } void Application::touchEndEvent(QTouchEvent* event) {    _altPressed = false;    TouchEvent thisEvent(*event, _lastTouchEvent);    _controllerScriptingInterface->emitTouchEndEvent(thisEvent); // send events to any registered scripts    _lastTouchEvent = thisEvent;     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isTouchCaptured()) {        return;    }     if (_keyboardMouseDevice->isActive()) {        _keyboardMouseDevice->touchEndEvent(event);    }     // put any application specific touch behavior below here..} void Application::wheelEvent(QWheelEvent* event) const {    _altPressed = false;    _controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts     // if one of our scripts have asked to capture this event, then stop processing it    if (_controllerScriptingInterface->isWheelCaptured()) {        return;    }     if (_keyboardMouseDevice->isActive()) {        _keyboardMouseDevice->wheelEvent(event);    }} void Application::dropEvent(QDropEvent *event) {    const QMimeData* mimeData = event->mimeData();    for (auto& url : mimeData->urls()) {        QString urlString = url.toString();        if (acceptURL(urlString, true)) {            event->acceptProposedAction();        }    }} void Application::dragEnterEvent(QDragEnterEvent* event) {    event->acceptProposedAction();} bool Application::acceptSnapshot(const QString& urlString) {    QUrl url(urlString);    QString snapshotPath = url.toLocalFile();     SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);    if (snapshotData) {        if (!snapshotData->getURL().toString().isEmpty()) {            DependencyManager::get<AddressManager>()->handleLookupString(snapshotData->getURL().toString());        }    } else {        OffscreenUi::warning("", "No location details were found in the file\n" +                             snapshotPath + "\nTry dragging in an authentic Hifi snapshot.");    }    return true;} static uint32_t _renderedFrameIndex { INVALID_FRAME }; bool Application::shouldPaint(float nsecsElapsed) {    if (_aboutToQuit) {        return false;    }     auto displayPlugin = getActiveDisplayPlugin(); #ifdef DEBUG_PAINT_DELAY    static uint64_t paintDelaySamples{ 0 };    static uint64_t paintDelayUsecs{ 0 };     paintDelayUsecs += displayPlugin->getPaintDelayUsecs();     static const int PAINT_DELAY_THROTTLE = 1000;    if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) {        qCDebug(interfaceapp).nospace() <<            "Paint delay (" << paintDelaySamples << " samples): " <<            (float)paintDelaySamples / paintDelayUsecs << "us";    }#endif     float msecondsSinceLastUpdate = nsecsElapsed / NSECS_PER_USEC / USECS_PER_MSEC;     // Throttle if requested    if (displayPlugin->isThrottled() && (msecondsSinceLastUpdate < THROTTLED_SIM_FRAME_PERIOD_MS)) {        return false;    }     // Sync up the _renderedFrameIndex    _renderedFrameIndex = displayPlugin->presentCount();     return true;} void Application::idle(float nsecsElapsed) {     // Update the deadlock watchdog    updateHeartbeat();     auto offscreenUi = DependencyManager::get<OffscreenUi>();     // These tasks need to be done on our first idle, because we don't want the showing of    // overlay subwindows to do a showDesktop() until after the first time through    static bool firstIdle = true;    if (firstIdle) {        firstIdle = false;        connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop);    }     PROFILE_RANGE(__FUNCTION__);     float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND;     // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.    if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {        _keyboardMouseDevice->pluginFocusOutEvent();        _keyboardDeviceHasFocus = false;    } else if (offscreenUi && offscreenUi->getWindow()->activeFocusItem() == offscreenUi->getRootItem()) {        _keyboardDeviceHasFocus = true;    }     checkChangeCursor();     Stats::getInstance()->updateStats();     _simCounter.increment();     PerformanceTimer perfTimer("idle");    // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds    if (!_keyboardFocusedItem.isInvalidID()) {        const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus        quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress;        if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) {            _keyboardFocusedItem = UNKNOWN_ENTITY_ID;        }    }     // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing    // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing    // details normally.    bool showWarnings = getLogger()->extraDebugging();    PerformanceWarning warn(showWarnings, "idle()");     {        PerformanceTimer perfTimer("update");        PerformanceWarning warn(showWarnings, "Application::idle()... update()");        static const float BIGGEST_DELTA_TIME_SECS = 0.25f;        update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS));    }    {        PerformanceTimer perfTimer("pluginIdle");        PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()");        getActiveDisplayPlugin()->idle();        auto inputPlugins = PluginManager::getInstance()->getInputPlugins();        foreach(auto inputPlugin, inputPlugins) {            if (inputPlugin->isActive()) {                inputPlugin->idle();            }        }    }    {        PerformanceTimer perfTimer("rest");        PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");        _idleLoopStdev.addValue(secondsSinceLastUpdate);         //  Record standard deviation and reset counter if needed        const int STDEV_SAMPLES = 500;        if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) {            _idleLoopMeasuredJitter = _idleLoopStdev.getStDev();            _idleLoopStdev.reset();        }    }     _overlayConductor.update(secondsSinceLastUpdate);} void Application::setLowVelocityFilter(bool lowVelocityFilter) {    controller::InputDevice::setLowVelocityFilter(lowVelocityFilter);} ivec2 Application::getMouse() const {    return getApplicationCompositor().getReticlePosition();} FaceTracker* Application::getActiveFaceTracker() {    auto faceshift = DependencyManager::get<Faceshift>();    auto dde = DependencyManager::get<DdeFaceTracker>();     return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) :            (faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) : nullptr));} FaceTracker* Application::getSelectedFaceTracker() {    FaceTracker* faceTracker = nullptr;#ifdef HAVE_FACESHIFT    if (Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)) {        faceTracker = DependencyManager::get<Faceshift>().data();    }#endif#ifdef HAVE_DDE    if (Menu::getInstance()->isOptionChecked(MenuOption::UseCamera)) {        faceTracker = DependencyManager::get<DdeFaceTracker>().data();    }#endif    return faceTracker;} void Application::setActiveFaceTracker() const {#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)    bool isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking);#endif#ifdef HAVE_FACESHIFT    auto faceshiftTracker = DependencyManager::get<Faceshift>();    faceshiftTracker->setIsMuted(isMuted);    faceshiftTracker->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && !isMuted);#endif#ifdef HAVE_DDE    bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera);    Menu::getInstance()->getActionForOption(MenuOption::BinaryEyelidControl)->setVisible(isUsingDDE);    Menu::getInstance()->getActionForOption(MenuOption::CoupleEyelids)->setVisible(isUsingDDE);    Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE);    Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE);    Menu::getInstance()->getActionForOption(MenuOption::CalibrateCamera)->setVisible(isUsingDDE);    auto ddeTracker = DependencyManager::get<DdeFaceTracker>();    ddeTracker->setIsMuted(isMuted);    ddeTracker->setEnabled(isUsingDDE && !isMuted);#endif} #ifdef HAVE_IVIEWHMDvoid Application::setActiveEyeTracker() {    auto eyeTracker = DependencyManager::get<EyeTracker>();    if (!eyeTracker->isInitialized()) {        return;    }     bool isEyeTracking = Menu::getInstance()->isOptionChecked(MenuOption::SMIEyeTracking);    bool isSimulating = Menu::getInstance()->isOptionChecked(MenuOption::SimulateEyeTracking);    eyeTracker->setEnabled(isEyeTracking, isSimulating);     Menu::getInstance()->getActionForOption(MenuOption::OnePointCalibration)->setEnabled(isEyeTracking && !isSimulating);    Menu::getInstance()->getActionForOption(MenuOption::ThreePointCalibration)->setEnabled(isEyeTracking && !isSimulating);    Menu::getInstance()->getActionForOption(MenuOption::FivePointCalibration)->setEnabled(isEyeTracking && !isSimulating);} void Application::calibrateEyeTracker1Point() {    DependencyManager::get<EyeTracker>()->calibrate(1);} void Application::calibrateEyeTracker3Points() {    DependencyManager::get<EyeTracker>()->calibrate(3);} void Application::calibrateEyeTracker5Points() {    DependencyManager::get<EyeTracker>()->calibrate(5);}#endif bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset) {    QHash<EntityItemID, EntityItemPointer> entities;     auto entityTree = getEntities()->getTree();    auto exportTree = std::make_shared<EntityTree>();    exportTree->createRootElement();    glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);    bool success = true;    entityTree->withReadLock([&] {        for (auto entityID : entityIDs) { // Gather entities and properties.            auto entityItem = entityTree->findEntityByEntityItemID(entityID);            if (!entityItem) {                qCWarning(interfaceapp) << "Skipping export of" << entityID << "that is not in scene.";                continue;

Lines 2501–3000 of 5476. Previous lines