}} 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 Load more
} } 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_IVIEWHMD void 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;