From 9bbb2eb69279a4b1c7d870fe4c026c0ca553b585 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 19 Oct 2017 14:50:00 -0700 Subject: [PATCH] austin's comments, send events directly to selected web entity --- interface/src/Application.h | 2 +- interface/src/ui/overlays/Overlays.cpp | 20 ++++-- .../src/EntityTreeRenderer.cpp | 37 ++++++++-- .../src/RenderableWebEntityItem.cpp | 71 ++++++++----------- .../src/RenderableWebEntityItem.h | 8 ++- 5 files changed, 83 insertions(+), 55 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index a3176ff1e3..0aeecadde0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -376,7 +376,7 @@ public slots: void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions); QUuid getKeyboardFocusEntity() const; // thread-safe - Q_INVOKABLE void setKeyboardFocusEntity(const EntityItemID& entityItemID); + void setKeyboardFocusEntity(const EntityItemID& entityItemID); OverlayID getKeyboardFocusOverlay(); void setKeyboardFocusOverlay(const OverlayID& overlayID); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 97fc908568..fd5aae4027 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -891,7 +891,10 @@ bool Overlays::mousePressEvent(QMouseEvent* event) { void Overlays::mousePressEvent(const OverlayID& overlayID, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - auto thisOverlay = std::dynamic_pointer_cast(getOverlay(overlayID)); + std::shared_ptr thisOverlay; + if (getOverlayType(overlayID) == "web3d") { + thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); + } if (thisOverlay) { // Focus keyboard on web overlays DependencyManager::get()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); @@ -925,7 +928,10 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { void Overlays::hoverLeaveEvent(const OverlayID& overlayID, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - auto thisOverlay = std::dynamic_pointer_cast(getOverlay(overlayID)); + std::shared_ptr thisOverlay; + if (getOverlayType(overlayID) == "web3d") { + thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); + } if (thisOverlay) { // Send to web overlay QMetaObject::invokeMethod(thisOverlay.get(), "hoverLeaveOverlay", Q_ARG(PointerEvent, event)); @@ -951,7 +957,10 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) { void Overlays::mouseReleaseEvent(const OverlayID& overlayID, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - auto thisOverlay = std::dynamic_pointer_cast(getOverlay(overlayID)); + std::shared_ptr thisOverlay; + if (getOverlayType(overlayID) == "web3d") { + thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); + } if (thisOverlay) { // Send to web overlay QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); @@ -999,7 +1008,10 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { void Overlays::mouseMoveEvent(const OverlayID& overlayID, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - auto thisOverlay = std::dynamic_pointer_cast(getOverlay(overlayID)); + std::shared_ptr thisOverlay; + if (getOverlayType(overlayID) == "web3d") { + thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); + } if (thisOverlay) { // Send to web overlay QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 89491a3910..57057297d6 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -35,6 +35,8 @@ #include "EntitiesRendererLogging.h" #include "RenderableEntityItem.h" +#include "RenderableWebEntityItem.h" + size_t std::hash::operator()(const EntityItemID& id) const { return qHash(id); } std::function EntityTreeRenderer::_entitiesShouldFadeFunction; @@ -55,6 +57,32 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf EntityRenderer::initEntityRenderers(); _currentHoverOverEntityID = UNKNOWN_ENTITY_ID; _currentClickingOnEntityID = UNKNOWN_ENTITY_ID; + + // Forward mouse events to web entities + auto handlePointerEvent = [&](const EntityItemID& entityID, const PointerEvent& event) { + std::shared_ptr thisEntity; + auto entity = getEntity(entityID); + if (entity && entity->getType() == EntityTypes::Web) { + thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); + } + if (thisEntity) { + QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); + } + }; + auto entityScriptingInterface = DependencyManager::get(); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const EntityItemID& entityID, const PointerEvent& event) { + std::shared_ptr thisEntity; + auto entity = getEntity(entityID); + if (entity && entity->getType() == EntityTypes::Web) { + thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); + } + if (thisEntity) { + QMetaObject::invokeMethod(thisEntity.get(), "hoverLeaveEntity", Q_ARG(PointerEvent, event)); + } + }); } EntityTreeRenderer::~EntityTreeRenderer() { @@ -78,7 +106,6 @@ render::ItemID EntityTreeRenderer::renderableIdForEntityId(const EntityItemID& i int EntityTreeRenderer::_entitiesScriptEngineCount = 0; void EntityTreeRenderer::resetEntitiesScriptEngine() { - auto oldEngine = _entitiesScriptEngine; _entitiesScriptEngine = scriptEngineFactory(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT, QString("about:Entities %1").arg(++_entitiesScriptEngineCount)); _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine); @@ -543,7 +570,7 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { auto entityScriptingInterface = DependencyManager::get(); PickRay ray = _viewState->computePickRay(event->x(), event->y()); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); - if (rayPickResult.intersects) { + if (rayPickResult.intersects && rayPickResult.entity) { auto properties = rayPickResult.entity->getProperties(); QString urlString = properties.getHref(); QUrl url = QUrl(urlString, QUrl::StrictMode); @@ -582,7 +609,7 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) { auto entityScriptingInterface = DependencyManager::get(); PickRay ray = _viewState->computePickRay(event->x(), event->y()); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); - if (rayPickResult.intersects) { + if (rayPickResult.intersects && rayPickResult.entity) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, @@ -612,7 +639,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { auto entityScriptingInterface = DependencyManager::get(); PickRay ray = _viewState->computePickRay(event->x(), event->y()); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); - if (rayPickResult.intersects) { + if (rayPickResult.intersects && rayPickResult.entity) { //qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); @@ -656,7 +683,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { auto entityScriptingInterface = DependencyManager::get(); PickRay ray = _viewState->computePickRay(event->x(), event->y()); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); - if (rayPickResult.intersects) { + if (rayPickResult.intersects && rayPickResult.entity) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 1e83783828..6d9f948ae1 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -85,6 +85,10 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe return true; } + if (_lastLocked != entity->getLocked()) { + return true; + } + return false; } @@ -135,6 +139,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene } _lastDPI = entity->getDPI(); + _lastLocked = entity->getLocked(); glm::vec2 windowSize = getWindowSize(entity); _webSurface->resize(QSize(windowSize.x, windowSize.y)); @@ -233,38 +238,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { emit entities->webEventReceived(entityItemID, message); }); - auto forwardPointerEvent = [=](const EntityItemID& entityItemID, const PointerEvent& event) { - if (entityItemID == entity->getID()) { - handlePointerEvent(entity, event); - } - }; - - auto entityScriptingInterface = DependencyManager::get(); - QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, forwardPointerEvent); - QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, forwardPointerEvent); - QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, forwardPointerEvent); - QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, - [=](const EntityItemID& entityItemID, const PointerEvent& event) { - if (this->_pressed && entity->getID() == entityItemID) { - // If the user mouses off the entity while the button is down, simulate a touch end. - QTouchEvent::TouchPoint point; - point.setId(event.getID()); - point.setState(Qt::TouchPointReleased); - glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI); - QPointF windowPoint(windowPos.x, windowPos.y); - point.setScenePos(windowPoint); - point.setPos(windowPoint); - QList touchPoints; - touchPoints.push_back(point); - QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, - Qt::NoModifier, Qt::TouchPointReleased, touchPoints); - touchEvent->setWindow(_webSurface->getWindow()); - touchEvent->setDevice(&_touchDevice); - touchEvent->setTarget(_webSurface->getRootItem()); - QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); - } - }); - return true; } @@ -294,13 +267,6 @@ void WebEntityRenderer::destroyWebSurface() { } webSurface->pause(); - auto entityScriptingInterface = DependencyManager::get(); - if (entityScriptingInterface) { - QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, nullptr); - QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, nullptr); - QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, nullptr); - QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, nullptr); - } webSurface.reset(); } } @@ -346,13 +312,34 @@ void WebEntityRenderer::loadSourceURL() { } } -void WebEntityRenderer::handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event) { +void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) { + if (!_lastLocked && _webSurface && _pressed) { + // If the user mouses off the entity while the button is down, simulate a touch end. + QTouchEvent::TouchPoint point; + point.setId(event.getID()); + point.setState(Qt::TouchPointReleased); + glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI); + QPointF windowPoint(windowPos.x, windowPos.y); + point.setScenePos(windowPoint); + point.setPos(windowPoint); + QList touchPoints; + touchPoints.push_back(point); + QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, + Qt::NoModifier, Qt::TouchPointReleased, touchPoints); + touchEvent->setWindow(_webSurface->getWindow()); + touchEvent->setDevice(&_touchDevice); + touchEvent->setTarget(_webSurface->getRootItem()); + QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); + } +} + +void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) { // Ignore mouse interaction if we're locked - if (entity->getLocked() || !_webSurface) { + if (_lastLocked || !_webSurface) { return; } - glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * entity->getDPI()); + glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI); QPointF windowPoint(windowPos.x, windowPos.y); if (event.getType() == PointerEvent::Move) { // Forward a mouse move event to webSurface diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 4b7e7e25a1..896d0c7c54 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -18,12 +18,16 @@ class PointerEvent; namespace render { namespace entities { class WebEntityRenderer : public TypedEntityRenderer { + Q_OBJECT using Parent = TypedEntityRenderer; friend class EntityRenderer; public: WebEntityRenderer(const EntityItemPointer& entity); + Q_INVOKABLE void hoverLeaveEntity(const PointerEvent& event); + Q_INVOKABLE void handlePointerEvent(const PointerEvent& event); + protected: virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override; virtual bool needsRenderUpdate() const override; @@ -44,9 +48,6 @@ private: bool hasWebSurface(); void loadSourceURL(); glm::vec2 getWindowSize(const TypedEntityPointer& entity) const; - void handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event); - -private: int _geometryId{ 0 }; enum contentType { @@ -60,6 +61,7 @@ private: bool _pressed{ false }; QString _lastSourceUrl; uint16_t _lastDPI; + bool _lastLocked; QTimer _timer; uint64_t _lastRenderTime { 0 }; };