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 | 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 | 1068 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| 1069 | 1069 | connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, |
| 1070 | − [this, entityScriptingInterface](const EntityItemID& entityItemID, const MouseEvent& event) { | |
| 1071 | − if (_keyboardFocusedItem != 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 | − } | |
| 1070 | + [this](const EntityItemID& entityItemID, const PointerEvent& event) { | |
| 1071 | + setKeyboardFocusEntity(entityItemID); | |
| 1108 | 1072 | }); |
| 1109 | 1073 | |
| 1110 | − connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, | |
| 1111 | − [=](const EntityItemID& entityItemID) { | |
| 1112 | − if (entityItemID == _keyboardFocusedItem) { | |
| 1113 | − _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | |
| 1114 | − if (_keyboardFocusHighlight) { | |
| 1115 | − _keyboardFocusHighlight->setVisible(false); | |
| 1116 | − } | |
| 1074 | + connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [=](const EntityItemID& entityItemID) { | |
| 1075 | + if (entityItemID == _keyboardFocusedItem.get()) { | |
| 1076 | + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); | |
| 1117 | 1077 | } |
| 1118 | 1078 | }); |
| 1119 | 1079 | |
| 1120 | 1080 | // If the user clicks somewhere where there is NO entity at all, we will release focus |
| 1121 | − connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, | |
| 1122 | − [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event) { | |
| 1123 | − _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | |
| 1124 | − if (_keyboardFocusHighlight) { | |
| 1125 | − _keyboardFocusHighlight->setVisible(false); | |
| 1126 | − } | |
| 1081 | + connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, [=]() { | |
| 1082 | + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); | |
| 1127 | 1083 | }); |
| 1128 | 1084 | |
| 1129 | 1085 | connect(this, &Application::aboutToQuit, [=]() { |
| 1130 | − _keyboardFocusedItem = UNKNOWN_ENTITY_ID; | |
| 1131 | − if (_keyboardFocusHighlight) { | |
| 1132 | − _keyboardFocusHighlight->setVisible(false); | |
| 1133 | − } | |
| 1086 | + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); | |
| 1134 | 1087 | }); |
| 1135 | 1088 | |
| 1136 | 1089 | // Add periodic checks to send user activity data |
| @@ -1403,11 +1356,13 @@ void Application::cleanupBeforeQuit() { · 266 unmodified lines | ||
| 1403 | 1356 | // FIXME: once we move to shared pointer for the INputDevice we shoud remove this naked delete: |
| 1404 | 1357 | _applicationStateDevice.reset(); |
| 1405 | 1358 | |
| 1406 | − if (_keyboardFocusHighlightID > 0) { | |
| 1407 | − getOverlays().deleteOverlay(_keyboardFocusHighlightID); | |
| 1408 | − _keyboardFocusHighlightID = -1; | |
| 1359 | + { | |
| 1360 | + if (_keyboardFocusHighlightID > 0) { | |
| 1361 | + getOverlays().deleteOverlay(_keyboardFocusHighlightID); | |
| 1362 | + _keyboardFocusHighlightID = -1; | |
| 1363 | + } | |
| 1364 | + _keyboardFocusHighlight = nullptr; | |
| 1409 | 1365 | } |
| 1410 | − _keyboardFocusHighlight = nullptr; | |
| 1411 | 1366 | |
| 1412 | 1367 | auto nodeList = DependencyManager::get<NodeList>(); |
| 1413 | 1368 | |
| @@ -2122,16 +2077,16 @@ bool Application::event(QEvent* event) { · 708 unmodified lines | ||
| 2122 | 2077 | return true; |
| 2123 | 2078 | } |
| 2124 | 2079 | |
| 2125 | − if (!_keyboardFocusedItem.isInvalidID()) { | |
| 2126 | − switch (event->type()) { | |
| 2080 | + { | |
| 2081 | + if (!_keyboardFocusedItem.get().isInvalidID()) { | |
| 2082 | + switch (event->type()) { | |
| 2127 | 2083 | case QEvent::KeyPress: |
| 2128 | 2084 | case QEvent::KeyRelease: { |
| 2129 | 2085 | auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); |
| 2130 | − auto entity = entityScriptingInterface->getEntityTree()->findEntityByID(_keyboardFocusedItem); | |
| 2131 | − RenderableWebEntityItem* webEntity = dynamic_cast<RenderableWebEntityItem*>(entity.get()); | |
| 2132 | − if (webEntity && webEntity->getEventHandler()) { | |
| 2086 | + auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedItem.get()); | |
| 2087 | + if (entity && entity->getEventHandler()) { | |
| 2133 | 2088 | event->setAccepted(false); |
| 2134 | − QCoreApplication::sendEvent(webEntity->getEventHandler(), event); | |
| 2089 | + QCoreApplication::sendEvent(entity->getEventHandler(), event); | |
| 2135 | 2090 | if (event->isAccepted()) { |
| 2136 | 2091 | _lastAcceptedKeyPress = usecTimestampNow(); |
| 2137 | 2092 | return true; |
| @@ -2142,6 +2097,7 @@ bool Application::event(QEvent* event) { · 4 unmodified lines | ||
| 2142 | 2097 | |
| 2143 | 2098 | default: |
| 2144 | 2099 | break; |
| 2100 | + } | |
| 2145 | 2101 | } |
| 2146 | 2102 | } |
| 2147 | 2103 | |
| @@ -2691,7 +2647,10 @@ void Application::mouseMoveEvent(QMouseEvent* event) { · 543 unmodified lines | ||
| 2691 | 2647 | event->screenPos(), button, |
| 2692 | 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 | 2654 | _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts |
| 2696 | 2655 | |
| 2697 | 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 | 2940 | _simCounter.increment(); |
| 2982 | 2941 | |
| 2983 | 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 | 2944 | // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing |
| 2994 | 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 | 2953 | static const float BIGGEST_DELTA_TIME_SECS = 0.25f; |
| 3003 | 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 | 2978 | PerformanceTimer perfTimer("pluginIdle"); |
| 3007 | 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 | 3609 | void Application::updateDialogs(float deltaTime) const { |
| 3590 | 3610 | PerformanceTimer perfTimer("updateDialogs"); |
| 3591 | 3611 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| @@ -5642,3 +5662,48 @@ bool Application::makeRenderingContextCurrent() { · 2050 unmodified lines | ||
| 5642 | 5662 | bool Application::isForeground() const { |
| 5643 | 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 | +} | |