handControllerGrab and web entity input integration
Showing the changes to interface/src/Application.cpp (1 of 21 files). Show all
Unified · Split
| @@ -1067,70 +1067,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 1066 unmodified lines | |||
| 1067 | // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it | 1067 | // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it |
| 1068 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | 1068 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| 1069 | connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, | 1069 | connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, |
| 1070 | [this, entityScriptingInterface](const EntityItemID& entityItemID, const MouseEvent& event) { | 1070 | [this](const EntityItemID& entityItemID, const PointerEvent& event) { |
| 1071 | if (_keyboardFocusedItem != entityItemID) { | 1071 | setKeyboardFocusEntity(entityItemID); |
| 1072 | _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | ||
| 1073 | auto properties = entityScriptingInterface->getEntityProperties(entityItemID); | ||
| 1074 | if (EntityTypes::Web == properties.getType() && !properties.getLocked() && properties.getVisible()) { | ||
| 1075 | auto entity = entityScriptingInterface->getEntityTree()->findEntityByID(entityItemID); | ||
| 1076 | RenderableWebEntityItem* webEntity = dynamic_cast<RenderableWebEntityItem*>(entity.get()); | ||
| 1077 | if (webEntity) { | ||
| 1078 | webEntity->setProxyWindow(_window->windowHandle()); | ||
| 1079 | if (_keyboardMouseDevice->isActive()) { | ||
| 1080 | _keyboardMouseDevice->pluginFocusOutEvent(); | ||
| 1081 | } | ||
| 1082 | _keyboardFocusedItem = entityItemID; | ||
| 1083 | _lastAcceptedKeyPress = usecTimestampNow(); | ||
| 1084 | if (_keyboardFocusHighlightID < 0 || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { | ||
| 1085 | _keyboardFocusHighlight = new Cube3DOverlay(); | ||
| 1086 | _keyboardFocusHighlight->setAlpha(1.0f); | ||
| 1087 | _keyboardFocusHighlight->setBorderSize(1.0f); | ||
| 1088 | _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 }); | ||
| 1089 | _keyboardFocusHighlight->setIsSolid(false); | ||
| 1090 | _keyboardFocusHighlight->setPulseMin(0.5); | ||
| 1091 | _keyboardFocusHighlight->setPulseMax(1.0); | ||
| 1092 | _keyboardFocusHighlight->setColorPulse(1.0); | ||
| 1093 | _keyboardFocusHighlight->setIgnoreRayIntersection(true); | ||
| 1094 | _keyboardFocusHighlight->setDrawInFront(true); | ||
| 1095 | } | ||
| 1096 | _keyboardFocusHighlight->setRotation(webEntity->getRotation()); | ||
| 1097 | _keyboardFocusHighlight->setPosition(webEntity->getPosition()); | ||
| 1098 | _keyboardFocusHighlight->setDimensions(webEntity->getDimensions() * 1.05f); | ||
| 1099 | _keyboardFocusHighlight->setVisible(true); | ||
| 1100 | _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | if (_keyboardFocusedItem == UNKNOWN_ENTITY_ID && _keyboardFocusHighlight) { | ||
| 1104 | _keyboardFocusHighlight->setVisible(false); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | } | ||
| 1108 | }); | 1072 | }); |
| 1109 | 1073 | ||
| 1110 | connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, | 1074 | connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [=](const EntityItemID& entityItemID) { |
| 1111 | [=](const EntityItemID& entityItemID) { | 1075 | if (entityItemID == _keyboardFocusedItem.get()) { |
| 1112 | if (entityItemID == _keyboardFocusedItem) { | 1076 | setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); |
| 1113 | _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | ||
| 1114 | if (_keyboardFocusHighlight) { | ||
| 1115 | _keyboardFocusHighlight->setVisible(false); | ||
| 1116 | } | ||
| 1117 | } | 1077 | } |
| 1118 | }); | 1078 | }); |
| 1119 | 1079 | ||
| 1120 | // If the user clicks somewhere where there is NO entity at all, we will release focus | 1080 | // If the user clicks somewhere where there is NO entity at all, we will release focus |
| 1121 | connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, | 1081 | connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, [=]() { |
| 1122 | [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event) { | 1082 | setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); |
| 1123 | _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | ||
| 1124 | if (_keyboardFocusHighlight) { | ||
| 1125 | _keyboardFocusHighlight->setVisible(false); | ||
| 1126 | } | ||
| 1127 | }); | 1083 | }); |
| 1128 | 1084 | ||
| 1129 | connect(this, &Application::aboutToQuit, [=]() { | 1085 | connect(this, &Application::aboutToQuit, [=]() { |
| 1130 | _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | 1086 | setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); |
| 1131 | if (_keyboardFocusHighlight) { | ||
| 1132 | _keyboardFocusHighlight->setVisible(false); | ||
| 1133 | } | ||
| 1134 | }); | 1087 | }); |
| 1135 | 1088 | ||
| 1136 | // Add periodic checks to send user activity data | 1089 | // Add periodic checks to send user activity data |
| @@ -1403,11 +1356,13 @@ void Application::cleanupBeforeQuit() { · 266 unmodified lines | |||
| 1403 | // FIXME: once we move to shared pointer for the INputDevice we shoud remove this naked delete: | 1356 | // FIXME: once we move to shared pointer for the INputDevice we shoud remove this naked delete: |
| 1404 | _applicationStateDevice.reset(); | 1357 | _applicationStateDevice.reset(); |
| 1405 | 1358 | ||
| 1406 | if (_keyboardFocusHighlightID > 0) { | 1359 | { |
| 1407 | getOverlays().deleteOverlay(_keyboardFocusHighlightID); | 1360 | if (_keyboardFocusHighlightID > 0) { |
| 1408 | _keyboardFocusHighlightID = -1; | 1361 | getOverlays().deleteOverlay(_keyboardFocusHighlightID); |
| 1362 | _keyboardFocusHighlightID = -1; | ||
| 1363 | } | ||
| 1364 | _keyboardFocusHighlight = nullptr; | ||
| 1409 | } | 1365 | } |
| 1410 | _keyboardFocusHighlight = nullptr; | ||
| 1411 | 1366 | ||
| 1412 | auto nodeList = DependencyManager::get<NodeList>(); | 1367 | auto nodeList = DependencyManager::get<NodeList>(); |
| 1413 | 1368 | ||
| @@ -2122,16 +2077,16 @@ bool Application::event(QEvent* event) { · 708 unmodified lines | |||
| 2122 | return true; | 2077 | return true; |
| 2123 | } | 2078 | } |
| 2124 | 2079 | ||
| 2125 | if (!_keyboardFocusedItem.isInvalidID()) { | 2080 | { |
| 2126 | switch (event->type()) { | 2081 | if (!_keyboardFocusedItem.get().isInvalidID()) { |
| 2082 | switch (event->type()) { | ||
| 2127 | case QEvent::KeyPress: | 2083 | case QEvent::KeyPress: |
| 2128 | case QEvent::KeyRelease: { | 2084 | case QEvent::KeyRelease: { |
| 2129 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | 2085 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| 2130 | auto entity = entityScriptingInterface->getEntityTree()->findEntityByID(_keyboardFocusedItem); | 2086 | auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedItem.get()); |
| 2131 | RenderableWebEntityItem* webEntity = dynamic_cast<RenderableWebEntityItem*>(entity.get()); | 2087 | if (entity && entity->getEventHandler()) { |
| 2132 | if (webEntity && webEntity->getEventHandler()) { | ||
| 2133 | event->setAccepted(false); | 2088 | event->setAccepted(false); |
| 2134 | QCoreApplication::sendEvent(webEntity->getEventHandler(), event); | 2089 | QCoreApplication::sendEvent(entity->getEventHandler(), event); |
| 2135 | if (event->isAccepted()) { | 2090 | if (event->isAccepted()) { |
| 2136 | _lastAcceptedKeyPress = usecTimestampNow(); | 2091 | _lastAcceptedKeyPress = usecTimestampNow(); |
| 2137 | return true; | 2092 | return true; |
| @@ -2142,6 +2097,7 @@ bool Application::event(QEvent* event) { · 4 unmodified lines | |||
| 2142 | 2097 | ||
| 2143 | default: | 2098 | default: |
| 2144 | break; | 2099 | break; |
| 2100 | } | ||
| 2145 | } | 2101 | } |
| 2146 | } | 2102 | } |
| 2147 | 2103 | ||
| @@ -2691,7 +2647,10 @@ void Application::mouseMoveEvent(QMouseEvent* event) { · 543 unmodified lines | |||
| 2691 | event->screenPos(), button, | 2647 | event->screenPos(), button, |
| 2692 | buttons, event->modifiers()); | 2648 | buttons, event->modifiers()); |
| 2693 | 2649 | ||
| 2694 | getEntities()->mouseMoveEvent(&mappedEvent); | 2650 | if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || |
| 2651 | getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y()))) { | ||
| 2652 | getEntities()->mouseMoveEvent(&mappedEvent); | ||
| 2653 | } | ||
| 2695 | _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts | 2654 | _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts |
| 2696 | 2655 | ||
| 2697 | // if one of our scripts have asked to capture this event, then stop processing it | 2656 | // if one of our scripts have asked to capture this event, then stop processing it |
| @@ -2981,14 +2940,6 @@ void Application::idle(float nsecsElapsed) { · 283 unmodified lines | |||
| 2981 | _simCounter.increment(); | 2940 | _simCounter.increment(); |
| 2982 | 2941 | ||
| 2983 | PerformanceTimer perfTimer("idle"); | 2942 | PerformanceTimer perfTimer("idle"); |
| 2984 | // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds | ||
| 2985 | if (!_keyboardFocusedItem.isInvalidID()) { | ||
| 2986 | const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus | ||
| 2987 | quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; | ||
| 2988 | if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { | ||
| 2989 | _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | ||
| 2990 | } | ||
| 2991 | } | ||
| 2992 | 2943 | ||
| 2993 | // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing | 2944 | // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing |
| 2994 | // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing | 2945 | // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing |
| @@ -3002,6 +2953,27 @@ void Application::idle(float nsecsElapsed) { · 7 unmodified lines | |||
| 3002 | static const float BIGGEST_DELTA_TIME_SECS = 0.25f; | 2953 | static const float BIGGEST_DELTA_TIME_SECS = 0.25f; |
| 3003 | update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); | 2954 | update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); |
| 3004 | } | 2955 | } |
| 2956 | |||
| 2957 | |||
| 2958 | // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds | ||
| 2959 | { | ||
| 2960 | if (!_keyboardFocusedItem.get().isInvalidID()) { | ||
| 2961 | const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus | ||
| 2962 | quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; | ||
| 2963 | if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { | ||
| 2964 | setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); | ||
| 2965 | } else { | ||
| 2966 | // update position of highlight overlay | ||
| 2967 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | ||
| 2968 | auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedItem.get()); | ||
| 2969 | if (entity && _keyboardFocusHighlight) { | ||
| 2970 | _keyboardFocusHighlight->setRotation(entity->getRotation()); | ||
| 2971 | _keyboardFocusHighlight->setPosition(entity->getPosition()); | ||
| 2972 | } | ||
| 2973 | } | ||
| 2974 | } | ||
| 2975 | } | ||
| 2976 | |||
| 3005 | { | 2977 | { |
| 3006 | PerformanceTimer perfTimer("pluginIdle"); | 2978 | PerformanceTimer perfTimer("pluginIdle"); |
| 3007 | PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); | 2979 | PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); |
| @@ -3586,6 +3558,54 @@ void Application::rotationModeChanged() const { · 578 unmodified lines | |||
| 3586 | } | 3558 | } |
| 3587 | } | 3559 | } |
| 3588 | 3560 | ||
| 3561 | QUuid Application::getKeyboardFocusEntity() const { | ||
| 3562 | return _keyboardFocusedItem.get(); | ||
| 3563 | } | ||
| 3564 | |||
| 3565 | void Application::setKeyboardFocusEntity(QUuid id) { | ||
| 3566 | EntityItemID entityItemID(id); | ||
| 3567 | setKeyboardFocusEntity(entityItemID); | ||
| 3568 | } | ||
| 3569 | |||
| 3570 | void Application::setKeyboardFocusEntity(EntityItemID entityItemID) { | ||
| 3571 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); | ||
| 3572 | if (_keyboardFocusedItem.get() != entityItemID) { | ||
| 3573 | _keyboardFocusedItem.set(UNKNOWN_ENTITY_ID); | ||
| 3574 | auto properties = entityScriptingInterface->getEntityProperties(entityItemID); | ||
| 3575 | if (!properties.getLocked() && properties.getVisible()) { | ||
| 3576 | auto entity = getEntities()->getTree()->findEntityByID(entityItemID); | ||
| 3577 | if (entity && entity->wantsKeyboardFocus()) { | ||
| 3578 | entity->setProxyWindow(_window->windowHandle()); | ||
| 3579 | if (_keyboardMouseDevice->isActive()) { | ||
| 3580 | _keyboardMouseDevice->pluginFocusOutEvent(); | ||
| 3581 | } | ||
| 3582 | _keyboardFocusedItem.set(entityItemID); | ||
| 3583 | _lastAcceptedKeyPress = usecTimestampNow(); | ||
| 3584 | if (_keyboardFocusHighlightID < 0 || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { | ||
| 3585 | _keyboardFocusHighlight = new Cube3DOverlay(); | ||
| 3586 | _keyboardFocusHighlight->setAlpha(1.0f); | ||
| 3587 | _keyboardFocusHighlight->setBorderSize(1.0f); | ||
| 3588 | _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 }); | ||
| 3589 | _keyboardFocusHighlight->setIsSolid(false); | ||
| 3590 | _keyboardFocusHighlight->setPulseMin(0.5); | ||
| 3591 | _keyboardFocusHighlight->setPulseMax(1.0); | ||
| 3592 | _keyboardFocusHighlight->setColorPulse(1.0); | ||
| 3593 | _keyboardFocusHighlight->setIgnoreRayIntersection(true); | ||
| 3594 | _keyboardFocusHighlight->setDrawInFront(false); | ||
| 3595 | } | ||
| 3596 | _keyboardFocusHighlight->setRotation(entity->getRotation()); | ||
| 3597 | _keyboardFocusHighlight->setPosition(entity->getPosition()); | ||
| 3598 | _keyboardFocusHighlight->setDimensions(entity->getDimensions() * 1.05f); | ||
| 3599 | _keyboardFocusHighlight->setVisible(true); | ||
| 3600 | _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight); | ||
| 3601 | } | ||
| 3602 | } | ||
| 3603 | if (_keyboardFocusedItem.get() == UNKNOWN_ENTITY_ID && _keyboardFocusHighlight) { | ||
| 3604 | _keyboardFocusHighlight->setVisible(false); | ||
| 3605 | } | ||
| 3606 | } | ||
| 3607 | } | ||
| 3608 | |||
| 3589 | void Application::updateDialogs(float deltaTime) const { | 3609 | void Application::updateDialogs(float deltaTime) const { |
| 3590 | PerformanceTimer perfTimer("updateDialogs"); | 3610 | PerformanceTimer perfTimer("updateDialogs"); |
| 3591 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); | 3611 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| @@ -5642,3 +5662,48 @@ bool Application::makeRenderingContextCurrent() { · 2050 unmodified lines | |||
| 5642 | bool Application::isForeground() const { | 5662 | bool Application::isForeground() const { |
| 5643 | return _isForeground && !_window->isMinimized(); | 5663 | return _isForeground && !_window->isMinimized(); |
| 5644 | } | 5664 | } |
| 5665 | |||
| 5666 | void Application::sendMousePressOnEntity(QUuid id, PointerEvent event) { | ||
| 5667 | EntityItemID entityItemID(id); | ||
| 5668 | emit getEntities()->mousePressOnEntity(entityItemID, event); | ||
| 5669 | } | ||
| 5670 | |||
| 5671 | void Application::sendMouseMoveOnEntity(QUuid id, PointerEvent event) { | ||
| 5672 | EntityItemID entityItemID(id); | ||
| 5673 | emit getEntities()->mouseMoveOnEntity(entityItemID, event); | ||
| 5674 | } | ||
| 5675 | |||
| 5676 | void Application::sendMouseReleaseOnEntity(QUuid id, PointerEvent event) { | ||
| 5677 | EntityItemID entityItemID(id); | ||
| 5678 | emit getEntities()->mouseReleaseOnEntity(entityItemID, event); | ||
| 5679 | } | ||
| 5680 | |||
| 5681 | void Application::sendClickDownOnEntity(QUuid id, PointerEvent event) { | ||
| 5682 | EntityItemID entityItemID(id); | ||
| 5683 | emit getEntities()->clickDownOnEntity(entityItemID, event); | ||
| 5684 | } | ||
| 5685 | |||
| 5686 | void Application::sendHoldingClickOnEntity(QUuid id, PointerEvent event) { | ||
| 5687 | EntityItemID entityItemID(id); | ||
| 5688 | emit getEntities()->holdingClickOnEntity(entityItemID, event); | ||
| 5689 | } | ||
| 5690 | |||
| 5691 | void Application::sendClickReleaseOnEntity(QUuid id, PointerEvent event) { | ||
| 5692 | EntityItemID entityItemID(id); | ||
| 5693 | emit getEntities()->clickReleaseOnEntity(entityItemID, event); | ||
| 5694 | } | ||
| 5695 | |||
| 5696 | void Application::sendHoverEnterEntity(QUuid id, PointerEvent event) { | ||
| 5697 | EntityItemID entityItemID(id); | ||
| 5698 | emit getEntities()->hoverEnterEntity(entityItemID, event); | ||
| 5699 | } | ||
| 5700 | |||
| 5701 | void Application::sendHoverOverEntity(QUuid id, PointerEvent event) { | ||
| 5702 | EntityItemID entityItemID(id); | ||
| 5703 | emit getEntities()->hoverOverEntity(entityItemID, event); | ||
| 5704 | } | ||
| 5705 | |||
| 5706 | void Application::sendHoverLeaveEntity(QUuid id, PointerEvent event) { | ||
| 5707 | EntityItemID entityItemID(id); | ||
| 5708 | emit getEntities()->hoverLeaveEntity(entityItemID, event); | ||
| 5709 | } | ||