From 7d420f5242bb421485a6c67d4f89fe536aae9440 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Nov 2017 12:29:21 -0800 Subject: [PATCH] isLeftHand, isRightHand, isMouse --- interface/resources/qml/controls-uit/Key.qml | 9 +- interface/src/raypick/JointRayPick.h | 3 + .../raypick/LaserPointerScriptingInterface.h | 6 +- interface/src/raypick/MouseRayPick.h | 2 + .../src/raypick/PickScriptingInterface.cpp | 12 ++ .../src/raypick/PickScriptingInterface.h | 6 +- .../src/raypick/PointerScriptingInterface.h | 5 +- .../src/raypick/RayPickScriptingInterface.cpp | 12 ++ .../src/raypick/RayPickScriptingInterface.h | 7 +- .../ui/overlays/ContextOverlayInterface.cpp | 14 ++- interface/src/ui/overlays/Overlays.cpp | 4 +- interface/src/ui/overlays/Web3DOverlay.cpp | 113 +++--------------- interface/src/ui/overlays/Web3DOverlay.h | 4 +- .../src/EntityTreeRenderer.cpp | 16 ++- libraries/pointers/src/pointers/Pick.h | 4 + .../pointers/src/pointers/PickManager.cpp | 24 ++++ libraries/pointers/src/pointers/PickManager.h | 4 + libraries/pointers/src/pointers/Pointer.cpp | 12 ++ libraries/pointers/src/pointers/Pointer.h | 4 + .../pointers/src/pointers/PointerManager.cpp | 24 ++++ .../pointers/src/pointers/PointerManager.h | 4 + libraries/ui/src/ui/OffscreenQmlSurface.cpp | 12 ++ libraries/ui/src/ui/OffscreenQmlSurface.h | 2 + 23 files changed, 176 insertions(+), 127 deletions(-) diff --git a/interface/resources/qml/controls-uit/Key.qml b/interface/resources/qml/controls-uit/Key.qml index e54250c872..3bba1e5f07 100644 --- a/interface/resources/qml/controls-uit/Key.qml +++ b/interface/resources/qml/controls-uit/Key.qml @@ -64,11 +64,12 @@ Item { keyItem.state = "mouseOver"; var globalPosition = keyItem.mapToGlobal(mouseArea1.mouseX, mouseArea1.mouseY); - var deviceId = Web3DOverlay.deviceIdByTouchPoint(globalPosition.x, globalPosition.y); - var hand = deviceId - 1; // based on touchEventUtils.js, deviceId is 'hand + 1', so 'hand' is 'deviceId' - 1 + var pointerID = Web3DOverlay.deviceIdByTouchPoint(globalPosition.x, globalPosition.y); - if (hand == leftHand || hand == rightHand) { - Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, hand); + if (Pointers.isLeftHand(pointerID)) { + Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, leftHand); + } else if (Pointers.isRightHand(pointerID)) { + Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, rightHand); } } diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index ab44bf67c8..67e6bf6945 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -20,6 +20,9 @@ public: const PickRay getMathematicalPick() const override; + bool isLeftHand() const override { return (_jointName == "_CONTROLLER_LEFTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); } + bool isRightHand() const override { return (_jointName == "_CONTROLLER_RIGHTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"); } + private: std::string _jointName; glm::vec3 _posOffset; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index da62f4eb12..baf8f0b2e6 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -20,7 +20,7 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY -public slots: +public: Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties) const; Q_INVOKABLE void enableLaserPointer(unsigned int uid) const { DependencyManager::get()->enablePointer(uid); } Q_INVOKABLE void disableLaserPointer(unsigned int uid) const { DependencyManager::get()->disablePointer(uid); } @@ -36,6 +36,10 @@ public slots: Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } + Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } + Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } + Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } + }; #endif // hifi_LaserPointerScriptingInterface_h diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h index e9eb3ccabf..6ce9e7d8d2 100644 --- a/interface/src/raypick/MouseRayPick.h +++ b/interface/src/raypick/MouseRayPick.h @@ -19,6 +19,8 @@ public: MouseRayPick(const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); const PickRay getMathematicalPick() const override; + + bool isMouse() const override { return true; } }; #endif // hifi_MouseRayPick_h diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 445a7e9b69..05e4a2acb0 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -109,6 +109,18 @@ void PickScriptingInterface::setIncludeItems(unsigned int uid, const QScriptValu DependencyManager::get()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); } +bool PickScriptingInterface::isLeftHand(unsigned int uid) { + return DependencyManager::get()->isLeftHand(uid); +} + +bool PickScriptingInterface::isRightHand(unsigned int uid) { + return DependencyManager::get()->isRightHand(uid); +} + +bool PickScriptingInterface::isMouse(unsigned int uid) { + return DependencyManager::get()->isMouse(uid); +} + QScriptValue pickTypesToScriptValue(QScriptEngine* engine, const PickQuery::PickType& pickType) { return pickType; } diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 900fa2ef40..cd296993fb 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -37,7 +37,6 @@ public: void registerMetaTypes(QScriptEngine* engine); -public slots: Q_INVOKABLE unsigned int createPick(const PickQuery::PickType type, const QVariant& properties); Q_INVOKABLE void enablePick(unsigned int uid); Q_INVOKABLE void disablePick(unsigned int uid); @@ -48,6 +47,11 @@ public slots: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities); Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities); + Q_INVOKABLE bool isLeftHand(unsigned int uid); + Q_INVOKABLE bool isRightHand(unsigned int uid); + Q_INVOKABLE bool isMouse(unsigned int uid); + +public slots: static constexpr unsigned int PICK_NOTHING() { return 0; } static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 8ea9594fda..e34a9ef74d 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -21,7 +21,6 @@ class PointerScriptingInterface : public QObject, public Dependency { public: unsigned int createLaserPointer(const QVariant& properties) const; -public slots: Q_INVOKABLE unsigned int createPointer(const PickQuery::PickType& type, const QVariant& properties) const; Q_INVOKABLE void enablePointer(unsigned int uid) const { DependencyManager::get()->enablePointer(uid); } Q_INVOKABLE void disablePointer(unsigned int uid) const { DependencyManager::get()->disablePointer(uid); } @@ -37,6 +36,10 @@ public slots: Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } + Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } + Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } + Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } + signals: void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent); void triggerContinue(const QUuid& id, const PointerEvent& pointerEvent); diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index f9774dda31..6b0b8dc167 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -51,3 +51,15 @@ void RayPickScriptingInterface::setIgnoreItems(uint32_t uid, const QScriptValue& void RayPickScriptingInterface::setIncludeItems(uint32_t uid, const QScriptValue& includeItems) { DependencyManager::get()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); } + +bool RayPickScriptingInterface::isLeftHand(unsigned int uid) { + return DependencyManager::get()->isLeftHand(uid); +} + +bool RayPickScriptingInterface::isRightHand(unsigned int uid) { + return DependencyManager::get()->isRightHand(uid); +} + +bool RayPickScriptingInterface::isMouse(unsigned int uid) { + return DependencyManager::get()->isMouse(uid); +} \ No newline at end of file diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 844add9012..65b0b2aced 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -36,7 +36,7 @@ class RayPickScriptingInterface : public QObject, public Dependency { Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) SINGLETON_DEPENDENCY -public slots: +public: Q_INVOKABLE unsigned int createRayPick(const QVariant& properties); Q_INVOKABLE void enableRayPick(unsigned int uid); Q_INVOKABLE void disableRayPick(unsigned int uid); @@ -47,6 +47,11 @@ public slots: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities); Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities); + Q_INVOKABLE bool isLeftHand(unsigned int uid); + Q_INVOKABLE bool isRightHand(unsigned int uid); + Q_INVOKABLE bool isMouse(unsigned int uid); + +public slots: static unsigned int PICK_NOTHING() { return PickScriptingInterface::PICK_NOTHING(); } static unsigned int PICK_ENTITIES() { return PickScriptingInterface::PICK_ENTITIES(); } static unsigned int PICK_OVERLAYS() { return PickScriptingInterface::PICK_OVERLAYS(); } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index b5af529f2b..fa02d4107c 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -19,6 +19,8 @@ #include #include +#include + #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif @@ -79,8 +81,6 @@ ContextOverlayInterface::ContextOverlayInterface() { _challengeOwnershipTimeoutTimer.setSingleShot(true); } -static const uint32_t MOUSE_HW_ID = 0; -static const uint32_t LEFT_HAND_HW_ID = 1; static const xColor CONTEXT_OVERLAY_COLOR = { 255, 255, 255 }; static const float CONTEXT_OVERLAY_INSIDE_DISTANCE = 1.0f; // in meters static const float CONTEXT_OVERLAY_SIZE = 0.09f; // in meters, same x and y dims @@ -100,7 +100,7 @@ void ContextOverlayInterface::setEnabled(bool enabled) { bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event) { if (_enabled && event.getButton() == PointerEvent::SecondaryButton) { if (contextOverlayFilterPassed(entityItemID)) { - if (event.getID() == MOUSE_HW_ID) { + if (event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get()->isMouse(event.getID())) { enableEntityHighlight(entityItemID); } @@ -151,7 +151,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID& glm::vec3 normal; boundingBox.findRayIntersection(cameraPosition, direction, distance, face, normal); float offsetAngle = -CONTEXT_OVERLAY_OFFSET_ANGLE; - if (event.getID() == LEFT_HAND_HW_ID) { + if (DependencyManager::get()->isLeftHand(event.getID())) { offsetAngle *= -1.0f; } contextOverlayPosition = cameraPosition + @@ -253,13 +253,15 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const OverlayID& } void ContextOverlayInterface::contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event) { - if (contextOverlayFilterPassed(entityID) && _enabled && event.getID() != MOUSE_HW_ID) { + bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get()->isMouse(event.getID()); + if (contextOverlayFilterPassed(entityID) && _enabled && !isMouse) { enableEntityHighlight(entityID); } } void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event) { - if (_currentEntityWithContextOverlay != entityID && _enabled && event.getID() != MOUSE_HW_ID) { + bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get()->isMouse(event.getID()); + if (_currentEntityWithContextOverlay != entityID && _enabled && !isMouse) { disableEntityHighlight(entityID); } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5a7b1bd76c..05ff3e289b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -784,8 +784,6 @@ float Overlays::height() { return offscreenUi->getWindow()->size().height(); } -static const uint32_t MOUSE_POINTER_ID = 0; - static glm::vec2 projectOntoOverlayXYPlane(glm::vec3 position, glm::quat rotation, glm::vec2 dimensions, const PickRay& pickRay, const RayToOverlayIntersectionResult& rayPickResult) { @@ -846,7 +844,7 @@ PointerEvent Overlays::calculateOverlayPointerEvent(OverlayID overlayID, PickRay glm::vec2 pos2D = projectOntoOverlayXYPlane(position, rotation, dimensions, ray, rayPickResult); - PointerEvent pointerEvent(eventType, MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, + PointerEvent pointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers()); return pointerEvent; diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index b8683b43e3..658b4edab8 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -56,6 +56,8 @@ #include "ui/Snapshot.h" #include "SoundCache.h" +#include "raypick/PointerScriptingInterface.h" + static const float DPI = 30.47f; static const float INCHES_TO_METERS = 1.0f / 39.3701f; static const float METERS_TO_INCHES = 39.3701f; @@ -216,6 +218,7 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); _webSurface->getSurfaceContext()->setContextProperty("Render", AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get()); _webSurface->getSurfaceContext()->setContextProperty("Controller", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Pointers", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("Web3DOverlay", this); _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../"); @@ -245,18 +248,12 @@ void Web3DOverlay::onResizeWebSurface() { _webSurface->resize(QSize(_resolution.x, _resolution.y)); } -const int INVALID_DEVICE_ID = -1; - -Q_INVOKABLE int Web3DOverlay::deviceIdByTouchPoint(qreal x, qreal y) { - auto mapped = _webSurface->getRootItem()->mapFromGlobal(QPoint(x, y)); - - for (auto pair : _activeTouchPoints) { - if (mapped.x() == (int)pair.second.pos().x() && mapped.y() == (int)pair.second.pos().y()) { - return pair.first; - } +unsigned int Web3DOverlay::deviceIdByTouchPoint(qreal x, qreal y) { + if (_webSurface) { + return _webSurface->deviceIdByTouchPoint(x, y); + } else { + return PointerEvent::INVALID_POINTER_ID; } - - return INVALID_DEVICE_ID; } void Web3DOverlay::render(RenderArgs* args) { @@ -341,13 +338,15 @@ void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) { } void Web3DOverlay::hoverLeaveOverlay(const PointerEvent& event) { - if ((_pressed || (!_activeTouchPoints.empty() && _touchBeginAccepted)) && event.sendReleaseOnHoverLeave()) { + if (_inputMode == Mouse) { PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(), event.getButton(), event.getButtons(), event.getKeyboardModifiers()); handlePointerEvent(endEvent); // QML onReleased is only triggered if a click has happened first. We need to send this "fake" mouse move event to properly trigger an onExited. PointerEvent endMoveEvent(PointerEvent::Move, event.getID()); handlePointerEvent(endMoveEvent); + } else if (_webSurface) { + _webSurface->hoverEndEvent(event, _touchDevice); } } @@ -366,93 +365,11 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { } void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { - if (!_webSurface) { - return; + if (_webSurface) { + PointerEvent webEvent = event; + webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); + _webSurface->handlePointerEvent(webEvent, _touchDevice); } - - glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); - QPointF windowPoint(windowPos.x, windowPos.y); - - Qt::TouchPointState state = Qt::TouchPointStationary; - if (event.getType() == PointerEvent::Press && event.getButton() == PointerEvent::PrimaryButton) { - state = Qt::TouchPointPressed; - } else if (event.getType() == PointerEvent::Release) { - state = Qt::TouchPointReleased; - } else if (_activeTouchPoints.count(event.getID()) && windowPoint != _activeTouchPoints[event.getID()].pos()) { - state = Qt::TouchPointMoved; - } - - QEvent::Type touchType = QEvent::TouchUpdate; - if (_activeTouchPoints.empty()) { - // If the first active touch point is being created, send a begin - touchType = QEvent::TouchBegin; - } if (state == Qt::TouchPointReleased && _activeTouchPoints.size() == 1 && _activeTouchPoints.count(event.getID())) { - // If the last active touch point is being released, send an end - touchType = QEvent::TouchEnd; - } - - { - QTouchEvent::TouchPoint point; - point.setId(event.getID()); - point.setState(state); - point.setPos(windowPoint); - point.setScreenPos(windowPoint); - _activeTouchPoints[event.getID()] = point; - } - - QTouchEvent touchEvent(touchType, &_touchDevice, event.getKeyboardModifiers()); - { - QList touchPoints; - Qt::TouchPointStates touchPointStates; - for (const auto& entry : _activeTouchPoints) { - touchPointStates |= entry.second.state(); - touchPoints.push_back(entry.second); - } - - touchEvent.setWindow(_webSurface->getWindow()); - touchEvent.setDevice(&_touchDevice); - touchEvent.setTarget(_webSurface->getRootItem()); - touchEvent.setTouchPoints(touchPoints); - touchEvent.setTouchPointStates(touchPointStates); - } - - // Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover. - // - // In Qt 5.9 mouse events must be sent before touch events to make sure some QtQuick components will - // receive mouse events - Qt::MouseButton button = Qt::NoButton; - Qt::MouseButtons buttons = Qt::NoButton; - if (event.getButton() == PointerEvent::PrimaryButton) { - button = Qt::LeftButton; - } - if (event.getButtons() & PointerEvent::PrimaryButton) { - buttons |= Qt::LeftButton; - } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) - if (event.getType() == PointerEvent::Move) { - QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers()); - QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); - } -#endif - - if (touchType == QEvent::TouchBegin) { - _touchBeginAccepted = QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent); - } else if (_touchBeginAccepted) { - QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent); - } - - // If this was a release event, remove the point from the active touch points - if (state == Qt::TouchPointReleased) { - _activeTouchPoints.erase(event.getID()); - } - -#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0) - if (event.getType() == PointerEvent::Move) { - QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers()); - QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); - } -#endif } void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) { diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 2fc63df76a..d2da1f7310 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -67,7 +67,7 @@ public: void destroyWebSurface(); void onResizeWebSurface(); - Q_INVOKABLE int deviceIdByTouchPoint(qreal x, qreal y); + Q_INVOKABLE unsigned int deviceIdByTouchPoint(qreal x, qreal y); public slots: void emitScriptEvent(const QVariant& scriptMessage); @@ -98,8 +98,6 @@ private: bool _showKeyboardFocusHighlight{ true }; bool _pressed{ false }; - bool _touchBeginAccepted { false }; - std::map _activeTouchPoints; QTouchDevice _touchDevice; uint8_t _desiredMaxFPS { 10 }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ad1c617287..8493d73db3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -571,8 +571,6 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) { } } -static const uint32_t MOUSE_POINTER_ID = 0; - void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { // If we don't have a tree, or we're in the process of shutting down, then don't // process these events. @@ -593,7 +591,7 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { } glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Press, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), @@ -625,7 +623,7 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) { RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); if (rayPickResult.intersects && rayPickResult.entity) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Press, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), Qt::NoModifier); @@ -657,7 +655,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { //qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Release, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), @@ -673,7 +671,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) { // we're releasing the button, then this is considered a clickReleaseOn event if (!_currentClickingOnEntityID.isInvalidID()) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Release, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), @@ -699,7 +697,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); if (rayPickResult.intersects && rayPickResult.entity) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Move, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), @@ -713,7 +711,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { // then we need to send the hover leave. if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Move, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), @@ -744,7 +742,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { // send the hover leave for our previous entity if (!_currentHoverOverEntityID.isInvalidID()) { glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); - PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, + PointerEvent pointerEvent(PointerEvent::Move, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), diff --git a/libraries/pointers/src/pointers/Pick.h b/libraries/pointers/src/pointers/Pick.h index e4ce5d3dce..b875285ad7 100644 --- a/libraries/pointers/src/pointers/Pick.h +++ b/libraries/pointers/src/pointers/Pick.h @@ -182,6 +182,10 @@ public: void setIgnoreItems(const QVector& items); void setIncludeItems(const QVector& items); + virtual bool isLeftHand() const { return false; } + virtual bool isRightHand() const { return false; } + virtual bool isMouse() const { return false; } + private: PickFilter _filter; const float _maxDistance; diff --git a/libraries/pointers/src/pointers/PickManager.cpp b/libraries/pointers/src/pointers/PickManager.cpp index cb9d715ba9..d601801d76 100644 --- a/libraries/pointers/src/pointers/PickManager.cpp +++ b/libraries/pointers/src/pointers/PickManager.cpp @@ -96,4 +96,28 @@ void PickManager::update() { bool shouldPickHUD = _shouldPickHUDOperator(); _rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], shouldPickHUD); +} + +bool PickManager::isLeftHand(unsigned int uid) { + auto pick = findPick(uid); + if (pick) { + return pick->isLeftHand(); + } + return false; +} + +bool PickManager::isRightHand(unsigned int uid) { + auto pick = findPick(uid); + if (pick) { + return pick->isRightHand(); + } + return false; +} + +bool PickManager::isMouse(unsigned int uid) { + auto pick = findPick(uid); + if (pick) { + return pick->isMouse(); + } + return false; } \ No newline at end of file diff --git a/libraries/pointers/src/pointers/PickManager.h b/libraries/pointers/src/pointers/PickManager.h index 0794ac0a41..bdc3e16054 100644 --- a/libraries/pointers/src/pointers/PickManager.h +++ b/libraries/pointers/src/pointers/PickManager.h @@ -33,6 +33,10 @@ public: void setIgnoreItems(unsigned int uid, const QVector& ignore) const; void setIncludeItems(unsigned int uid, const QVector& include) const; + bool isLeftHand(unsigned int uid); + bool isRightHand(unsigned int uid); + bool isMouse(unsigned int uid); + void setShouldPickHUDOperator(std::function shouldPickHUDOperator) { _shouldPickHUDOperator = shouldPickHUDOperator; } void setCalculatePos2DFromHUDOperator(std::function calculatePos2DFromHUDOperator) { _calculatePos2DFromHUDOperator = calculatePos2DFromHUDOperator; } glm::vec2 calculatePos2DFromHUD(const glm::vec3& intersection) { return _calculatePos2DFromHUDOperator(intersection); } diff --git a/libraries/pointers/src/pointers/Pointer.cpp b/libraries/pointers/src/pointers/Pointer.cpp index 0fc5c54ad2..6e95b48280 100644 --- a/libraries/pointers/src/pointers/Pointer.cpp +++ b/libraries/pointers/src/pointers/Pointer.cpp @@ -46,6 +46,18 @@ void Pointer::setIncludeItems(const QVector& includeItems) const { DependencyManager::get()->setIncludeItems(_pickUID, includeItems); } +bool Pointer::isLeftHand() const { + return DependencyManager::get()->isLeftHand(_pickUID); +} + +bool Pointer::isRightHand() const { + return DependencyManager::get()->isRightHand(_pickUID); +} + +bool Pointer::isMouse() const { + return DependencyManager::get()->isMouse(_pickUID); +} + void Pointer::update(unsigned int pointerID) { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts withReadLock([&] { diff --git a/libraries/pointers/src/pointers/Pointer.h b/libraries/pointers/src/pointers/Pointer.h index d8661436b9..6d9c1a172b 100644 --- a/libraries/pointers/src/pointers/Pointer.h +++ b/libraries/pointers/src/pointers/Pointer.h @@ -53,6 +53,10 @@ public: virtual void setIgnoreItems(const QVector& ignoreItems) const; virtual void setIncludeItems(const QVector& includeItems) const; + bool isLeftHand() const; + bool isRightHand() const; + bool isMouse() const; + // Pointers can choose to implement these virtual void setLength(float length) {} virtual void setLockEndUUID(const QUuid& objectID, bool isOverlay) {} diff --git a/libraries/pointers/src/pointers/PointerManager.cpp b/libraries/pointers/src/pointers/PointerManager.cpp index b117b24770..de85e74da1 100644 --- a/libraries/pointers/src/pointers/PointerManager.cpp +++ b/libraries/pointers/src/pointers/PointerManager.cpp @@ -120,3 +120,27 @@ void PointerManager::setLockEndUUID(unsigned int uid, const QUuid& objectID, boo pointer->setLockEndUUID(objectID, isOverlay); } } + +bool PointerManager::isLeftHand(unsigned int uid) { + auto pointer = find(uid); + if (pointer) { + return pointer->isLeftHand(); + } + return false; +} + +bool PointerManager::isRightHand(unsigned int uid) { + auto pointer = find(uid); + if (pointer) { + return pointer->isRightHand(); + } + return false; +} + +bool PointerManager::isMouse(unsigned int uid) { + auto pointer = find(uid); + if (pointer) { + return pointer->isMouse(); + } + return false; +} \ No newline at end of file diff --git a/libraries/pointers/src/pointers/PointerManager.h b/libraries/pointers/src/pointers/PointerManager.h index a415c9dbd9..461d27959c 100644 --- a/libraries/pointers/src/pointers/PointerManager.h +++ b/libraries/pointers/src/pointers/PointerManager.h @@ -40,6 +40,10 @@ public: void update(); + bool isLeftHand(unsigned int uid); + bool isRightHand(unsigned int uid); + bool isMouse(unsigned int uid); + static const unsigned int MOUSE_POINTER_ID { PointerEvent::INVALID_POINTER_ID + 1 }; private: diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index e2675008f9..41c3da2a4f 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -927,6 +927,18 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even return false; } +unsigned int OffscreenQmlSurface::deviceIdByTouchPoint(qreal x, qreal y) { + auto mapped = _rootItem->mapFromGlobal(QPoint(x, y)); + + for (auto pair : _activeTouchPoints) { + if (mapped.x() == (int)pair.second.pos().x() && mapped.y() == (int)pair.second.pos().y()) { + return pair.first; + } + } + + return PointerEvent::INVALID_POINTER_ID; +} + PointerEvent::EventType OffscreenQmlSurface::choosePointerEventType(QEvent::Type type) { switch (type) { case QEvent::MouseButtonDblClick: diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 1f1817faa2..8ddfbfe8cc 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -100,6 +100,8 @@ public: PointerEvent::EventType choosePointerEventType(QEvent::Type type); + unsigned int deviceIdByTouchPoint(qreal x, qreal y); + signals: void focusObjectChanged(QObject* newFocus); void focusTextChanged(bool focusText);