mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 14:52:46 +02:00
fix hover events, working on HUD events
This commit is contained in:
parent
657a0fb036
commit
dd4275430b
12 changed files with 129 additions and 105 deletions
|
@ -1504,6 +1504,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverBeginHUD, this, &Application::handleHUDPointerEvent);
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverContinueHUD, this, &Application::handleHUDPointerEvent);
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverEndHUD, this, &Application::handleHUDPointerEvent);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerBeginHUD, this, &Application::handleHUDPointerEvent);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerContinueHUD, this, &Application::handleHUDPointerEvent);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerEndHUD, this, &Application::handleHUDPointerEvent);
|
||||||
|
|
||||||
// Add periodic checks to send user activity data
|
// Add periodic checks to send user activity data
|
||||||
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
||||||
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
||||||
|
@ -7479,4 +7487,32 @@ void Application::setAvatarOverrideUrl(const QUrl& url, bool save) {
|
||||||
_avatarOverrideUrl = url;
|
_avatarOverrideUrl = url;
|
||||||
_saveAvatarOverrideUrl = save;
|
_saveAvatarOverrideUrl = save;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::handleHUDPointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||||
|
QEvent::Type type = QEvent::Type::MouseMove;
|
||||||
|
switch (event.getType()) {
|
||||||
|
case PointerEvent::Press:
|
||||||
|
type = QEvent::Type::MouseButtonPress;
|
||||||
|
break;
|
||||||
|
case PointerEvent::DoublePress:
|
||||||
|
type = QEvent::Type::MouseButtonDblClick;
|
||||||
|
break;
|
||||||
|
case PointerEvent::Release:
|
||||||
|
type = QEvent::Type::MouseButtonRelease;
|
||||||
|
break;
|
||||||
|
case PointerEvent::Move:
|
||||||
|
type = QEvent::Type::MouseMove;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF screenPos(event.getPos2D().x, event.getPos2D().y);
|
||||||
|
//QMouseEvent mouseEvent(type, screenPos, Qt::MouseButton(event.getButton()), Qt::MouseButtons(event.getButtons()), event.getKeyboardModifiers());
|
||||||
|
QMouseEvent moveEvent(QEvent::Type::MouseMove, screenPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||||
|
sendEvent(_glWidget, &moveEvent);
|
||||||
|
QMouseEvent mouseEvent(type, screenPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||||
|
sendEvent(_glWidget, &mouseEvent);
|
||||||
|
}
|
||||||
|
|
||||||
#include "Application.moc"
|
#include "Application.moc"
|
||||||
|
|
|
@ -434,6 +434,8 @@ private slots:
|
||||||
|
|
||||||
void handleSandboxStatus(QNetworkReply* reply);
|
void handleSandboxStatus(QNetworkReply* reply);
|
||||||
void switchDisplayMode();
|
void switchDisplayMode();
|
||||||
|
|
||||||
|
void handleHUDPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
private:
|
private:
|
||||||
static void initDisplay();
|
static void initDisplay();
|
||||||
void init();
|
void init();
|
||||||
|
|
|
@ -35,7 +35,7 @@ public slots:
|
||||||
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const;
|
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const;
|
||||||
Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const;
|
Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const;
|
||||||
|
|
||||||
Q_INVOKABLE void setLockEndUid(unsigned int uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay); }
|
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
|
|
@ -160,14 +160,6 @@ void Web3DOverlay::buildWebSurface() {
|
||||||
QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Web3DOverlay::hoverLeaveOverlay(const PointerEvent& event) {
|
|
||||||
if ((_pressed || (!_activeTouchPoints.empty() && _touchBeginAccepted))) {
|
|
||||||
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
|
||||||
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
|
||||||
handlePointerEvent(endEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Web3DOverlay::update(float deltatime) {
|
void Web3DOverlay::update(float deltatime) {
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
// update globalPosition
|
// update globalPosition
|
||||||
|
@ -348,6 +340,17 @@ void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) {
|
||||||
_webSurface->setProxyWindow(proxyWindow);
|
_webSurface->setProxyWindow(proxyWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Web3DOverlay::hoverLeaveOverlay(const PointerEvent& event) {
|
||||||
|
if ((_pressed || (!_activeTouchPoints.empty() && _touchBeginAccepted)) && event.sendReleaseOnHoverLeave()) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
||||||
if (event.getType() == PointerEvent::Press) {
|
if (event.getType() == PointerEvent::Press) {
|
||||||
_pressed = true;
|
_pressed = true;
|
||||||
|
@ -386,7 +389,7 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||||
} if (state == Qt::TouchPointReleased && _activeTouchPoints.size() == 1 && _activeTouchPoints.count(event.getID())) {
|
} if (state == Qt::TouchPointReleased && _activeTouchPoints.size() == 1 && _activeTouchPoints.count(event.getID())) {
|
||||||
// If the last active touch point is being released, send an end
|
// If the last active touch point is being released, send an end
|
||||||
touchType = QEvent::TouchEnd;
|
touchType = QEvent::TouchEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
QTouchEvent::TouchPoint point;
|
QTouchEvent::TouchPoint point;
|
||||||
|
@ -428,7 +431,7 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers());
|
||||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -446,7 +449,7 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers());
|
||||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -485,7 +488,7 @@ void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMouseEvent mouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers());
|
||||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,11 +315,13 @@ void WebEntityRenderer::loadSourceURL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) {
|
void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) {
|
||||||
if (!_lastLocked && _webSurface && _pressed) {
|
if (!_lastLocked && _webSurface && _pressed && event.sendReleaseOnHoverLeave()) {
|
||||||
// If the user mouses off the entity while the button is down, simulate a touch end.
|
|
||||||
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
||||||
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
||||||
handlePointerEvent(endEvent);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +398,7 @@ void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) {
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers());
|
||||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -414,7 +416,7 @@ void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) {
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers());
|
||||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -71,18 +71,15 @@ void PickCacheOptimizer<T>::update(QHash<unsigned int, std::shared_ptr<PickQuery
|
||||||
PickCache results;
|
PickCache results;
|
||||||
for (const auto& uid : picks.keys()) {
|
for (const auto& uid : picks.keys()) {
|
||||||
std::shared_ptr<Pick<T>> pick = std::static_pointer_cast<Pick<T>>(picks[uid]);
|
std::shared_ptr<Pick<T>> pick = std::static_pointer_cast<Pick<T>>(picks[uid]);
|
||||||
if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
T mathematicalPick = pick->getMathematicalPick();
|
T mathematicalPick = pick->getMathematicalPick();
|
||||||
|
PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap());
|
||||||
|
|
||||||
if (!mathematicalPick) {
|
if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f || !mathematicalPick) {
|
||||||
|
pick->setPickResult(res);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap());
|
|
||||||
|
|
||||||
if (pick->getFilter().doesPickEntities()) {
|
if (pick->getFilter().doesPickEntities()) {
|
||||||
PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||||
if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) {
|
if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) {
|
||||||
|
|
|
@ -59,14 +59,45 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
// TODO: avatars?
|
// TODO: avatars?
|
||||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||||
|
|
||||||
|
// NOTE: After this loop: _prevButtons = buttons that were removed
|
||||||
|
// If switching to disabled or should stop triggering, release all buttons
|
||||||
|
Buttons buttons;
|
||||||
|
Buttons newButtons;
|
||||||
|
Buttons sameButtons;
|
||||||
|
const std::string PRIMARY_BUTTON = "Primary";
|
||||||
|
bool primaryPressed = false;
|
||||||
|
if (_enabled && shouldTrigger()) {
|
||||||
|
buttons = getPressedButtons();
|
||||||
|
primaryPressed = buttons.find(PRIMARY_BUTTON) != buttons.end();
|
||||||
|
for (const std::string& button : buttons) {
|
||||||
|
if (_prevButtons.find(button) == _prevButtons.end()) {
|
||||||
|
newButtons.insert(button);
|
||||||
|
} else {
|
||||||
|
sameButtons.insert(button);
|
||||||
|
_prevButtons.erase(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hover events
|
// Hover events
|
||||||
|
bool doHover = shouldHover();
|
||||||
Pointer::PickedObject hoveredObject = getHoveredObject(pickResult);
|
Pointer::PickedObject hoveredObject = getHoveredObject(pickResult);
|
||||||
PointerEvent hoveredEvent = buildPointerEvent(hoveredObject, pickResult);
|
PointerEvent hoveredEvent = buildPointerEvent(hoveredObject, pickResult);
|
||||||
hoveredEvent.setType(PointerEvent::Move);
|
hoveredEvent.setType(PointerEvent::Move);
|
||||||
hoveredEvent.setID(pointerID);
|
hoveredEvent.setID(pointerID);
|
||||||
// TODO: set buttons on hover events
|
bool releaseOnHoverLeave = !primaryPressed || (!_enabled && _prevEnabled) || (!doHover && _prevDoHover);
|
||||||
hoveredEvent.setButton(PointerEvent::NoButtons);
|
hoveredEvent.setReleaseOnHoverLeave(releaseOnHoverLeave);
|
||||||
if (_enabled && _hover && shouldHover()) {
|
|
||||||
|
// if shouldHover && !_prevDoHover, only send hoverBegin
|
||||||
|
if (_enabled && _hover && doHover && !_prevDoHover) {
|
||||||
|
if (hoveredObject.type == ENTITY) {
|
||||||
|
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||||
|
} else if (hoveredObject.type == OVERLAY) {
|
||||||
|
emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
||||||
|
} else if (hoveredObject.type == HUD) {
|
||||||
|
emit pointerManager->hoverBeginHUD(hoveredObject.objectID, hoveredEvent);
|
||||||
|
}
|
||||||
|
} else if (_enabled && _hover && doHover) {
|
||||||
if (hoveredObject.type == OVERLAY) {
|
if (hoveredObject.type == OVERLAY) {
|
||||||
if (_prevHoveredObject.type == OVERLAY) {
|
if (_prevHoveredObject.type == OVERLAY) {
|
||||||
if (hoveredObject.objectID == _prevHoveredObject.objectID) {
|
if (hoveredObject.objectID == _prevHoveredObject.objectID) {
|
||||||
|
@ -74,6 +105,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
} else {
|
} else {
|
||||||
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
|
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
|
||||||
prevHoveredEvent.setID(pointerID);
|
prevHoveredEvent.setID(pointerID);
|
||||||
|
prevHoveredEvent.setReleaseOnHoverLeave(releaseOnHoverLeave);
|
||||||
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, prevHoveredEvent);
|
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, prevHoveredEvent);
|
||||||
emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +127,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
} else {
|
} else {
|
||||||
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
|
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
|
||||||
prevHoveredEvent.setID(pointerID);
|
prevHoveredEvent.setID(pointerID);
|
||||||
|
prevHoveredEvent.setReleaseOnHoverLeave(releaseOnHoverLeave);
|
||||||
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, prevHoveredEvent);
|
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, prevHoveredEvent);
|
||||||
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
|
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||||
}
|
}
|
||||||
|
@ -123,20 +156,15 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger events
|
if (_hover) {
|
||||||
Buttons buttons;
|
// send hoverEnd events if we disable the pointer, disable hovering, or actually stop hovering over an object
|
||||||
Buttons newButtons;
|
if ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover) || (hoveredObject.type == NONE && _prevHoveredObject.type != NONE)) {
|
||||||
Buttons sameButtons;
|
if (_prevHoveredObject.type == ENTITY) {
|
||||||
// NOTE: After this loop: _prevButtons = buttons that were removed
|
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
|
||||||
// If switching to disabled or should stop triggering, release all buttons
|
} else if (_prevHoveredObject.type == OVERLAY) {
|
||||||
if (_enabled && shouldTrigger()) {
|
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
|
||||||
buttons = getPressedButtons();
|
} else if (_prevHoveredObject.type == HUD) {
|
||||||
for (const std::string& button : buttons) {
|
emit pointerManager->hoverEndHUD(_prevHoveredObject.objectID, hoveredEvent);
|
||||||
if (_prevButtons.find(button) == _prevButtons.end()) {
|
|
||||||
newButtons.insert(button);
|
|
||||||
} else {
|
|
||||||
sameButtons.insert(button);
|
|
||||||
_prevButtons.erase(button);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,15 +184,13 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
}
|
}
|
||||||
_triggeredObjects[button] = hoveredObject;
|
_triggeredObjects[button] = hoveredObject;
|
||||||
}
|
}
|
||||||
// We still want other trigger events for Focus buttons, but they only set focus on triggerBegin
|
|
||||||
hoveredEvent.setShouldFocus(false);
|
|
||||||
|
|
||||||
// Trigger continue
|
// Trigger continue
|
||||||
for (const std::string& button : sameButtons) {
|
for (const std::string& button : sameButtons) {
|
||||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult);
|
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult);
|
||||||
triggeredEvent.setID(pointerID);
|
triggeredEvent.setID(pointerID);
|
||||||
triggeredEvent.setType(PointerEvent::Move);
|
triggeredEvent.setType(PointerEvent::Move);
|
||||||
hoveredEvent.setButton(chooseButton(button));
|
triggeredEvent.setButton(chooseButton(button));
|
||||||
if (_triggeredObjects[button].type == ENTITY) {
|
if (_triggeredObjects[button].type == ENTITY) {
|
||||||
emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
||||||
} else if (_triggeredObjects[button].type == OVERLAY) {
|
} else if (_triggeredObjects[button].type == OVERLAY) {
|
||||||
|
@ -179,7 +205,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult);
|
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult);
|
||||||
triggeredEvent.setID(pointerID);
|
triggeredEvent.setID(pointerID);
|
||||||
triggeredEvent.setType(PointerEvent::Release);
|
triggeredEvent.setType(PointerEvent::Release);
|
||||||
hoveredEvent.setButton(chooseButton(button));
|
triggeredEvent.setButton(chooseButton(button));
|
||||||
if (_triggeredObjects[button].type == ENTITY) {
|
if (_triggeredObjects[button].type == ENTITY) {
|
||||||
emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
||||||
} else if (_triggeredObjects[button].type == OVERLAY) {
|
} else if (_triggeredObjects[button].type == OVERLAY) {
|
||||||
|
@ -192,6 +218,8 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const QVariantMap& p
|
||||||
|
|
||||||
_prevHoveredObject = hoveredObject;
|
_prevHoveredObject = hoveredObject;
|
||||||
_prevButtons = buttons;
|
_prevButtons = buttons;
|
||||||
|
_prevEnabled = _enabled;
|
||||||
|
_prevDoHover = doHover;
|
||||||
}
|
}
|
||||||
|
|
||||||
PointerEvent::Button Pointer::chooseButton(const std::string& button) {
|
PointerEvent::Button Pointer::chooseButton(const std::string& button) {
|
||||||
|
|
|
@ -89,6 +89,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
PickedObject _prevHoveredObject;
|
PickedObject _prevHoveredObject;
|
||||||
Buttons _prevButtons;
|
Buttons _prevButtons;
|
||||||
|
bool _prevEnabled { false };
|
||||||
|
bool _prevDoHover { false };
|
||||||
std::unordered_map<std::string, PickedObject> _triggeredObjects;
|
std::unordered_map<std::string, PickedObject> _triggeredObjects;
|
||||||
|
|
||||||
PointerEvent::Button chooseButton(const std::string& button);
|
PointerEvent::Button chooseButton(const std::string& button);
|
||||||
|
|
|
@ -37,9 +37,9 @@ public:
|
||||||
|
|
||||||
PointerEvent();
|
PointerEvent();
|
||||||
PointerEvent(EventType type, uint32_t id,
|
PointerEvent(EventType type, uint32_t id,
|
||||||
const glm::vec2& pos2D, const glm::vec3& pos3D,
|
const glm::vec2& pos2D = glm::vec2(NAN), const glm::vec3& pos3D = glm::vec3(NAN),
|
||||||
const glm::vec3& normal, const glm::vec3& direction,
|
const glm::vec3& normal = glm::vec3(NAN), const glm::vec3& direction = glm::vec3(NAN),
|
||||||
Button button, uint32_t buttons = NoButtons, Qt::KeyboardModifiers keyboardModifiers = Qt::KeyboardModifier::NoModifier);
|
Button button = NoButtons, uint32_t buttons = NoButtons, Qt::KeyboardModifiers keyboardModifiers = Qt::KeyboardModifier::NoModifier);
|
||||||
|
|
||||||
static QScriptValue toScriptValue(QScriptEngine* engine, const PointerEvent& event);
|
static QScriptValue toScriptValue(QScriptEngine* engine, const PointerEvent& event);
|
||||||
static void fromScriptValue(const QScriptValue& object, PointerEvent& event);
|
static void fromScriptValue(const QScriptValue& object, PointerEvent& event);
|
||||||
|
@ -56,11 +56,13 @@ public:
|
||||||
uint32_t getButtons() const { return _buttons; }
|
uint32_t getButtons() const { return _buttons; }
|
||||||
Qt::KeyboardModifiers getKeyboardModifiers() const { return _keyboardModifiers; }
|
Qt::KeyboardModifiers getKeyboardModifiers() const { return _keyboardModifiers; }
|
||||||
bool shouldFocus() const { return _shouldFocus; }
|
bool shouldFocus() const { return _shouldFocus; }
|
||||||
|
bool sendReleaseOnHoverLeave() const { return _releaseOnHoverLeave; }
|
||||||
|
|
||||||
void setID(uint32_t id) { _id = id; }
|
void setID(uint32_t id) { _id = id; }
|
||||||
void setType(EventType type) { _type = type; }
|
void setType(EventType type) { _type = type; }
|
||||||
void setButton(Button button);
|
void setButton(Button button);
|
||||||
void setShouldFocus(bool focus) { _shouldFocus = focus; }
|
void setShouldFocus(bool focus) { _shouldFocus = focus; }
|
||||||
|
void setReleaseOnHoverLeave(bool releaseOnHoverLeave) { _releaseOnHoverLeave = releaseOnHoverLeave; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventType _type;
|
EventType _type;
|
||||||
|
@ -75,6 +77,7 @@ private:
|
||||||
Qt::KeyboardModifiers _keyboardModifiers; // set of keys held when event was generated
|
Qt::KeyboardModifiers _keyboardModifiers; // set of keys held when event was generated
|
||||||
|
|
||||||
bool _shouldFocus { true };
|
bool _shouldFocus { true };
|
||||||
|
bool _releaseOnHoverLeave { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug& operator<<(QDebug& dbg, const PointerEvent& p);
|
QDebug& operator<<(QDebug& dbg, const PointerEvent& p);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
set(TARGET_NAME ui)
|
set(TARGET_NAME ui)
|
||||||
setup_hifi_library(OpenGL Network Qml Quick Script WebChannel WebEngine WebSockets XmlPatterns)
|
setup_hifi_library(OpenGL Network Qml Quick Script WebChannel WebEngine WebSockets XmlPatterns)
|
||||||
link_hifi_libraries(shared networking gl audio pointers)
|
link_hifi_libraries(shared networking gl audio)
|
||||||
include_hifi_library_headers(controllers)
|
|
||||||
|
|
||||||
# Required for some low level GL interaction in the OffscreenQMLSurface
|
# Required for some low level GL interaction in the OffscreenQMLSurface
|
||||||
target_opengl()
|
target_opengl()
|
||||||
|
|
|
@ -49,8 +49,6 @@
|
||||||
|
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
#include <pointers/PointerManager.h>
|
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml")
|
Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml")
|
||||||
Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl")
|
Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl")
|
||||||
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
|
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
|
||||||
|
@ -531,13 +529,6 @@ bool OffscreenQmlSurface::allowNewFrame(uint8_t fps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OffscreenQmlSurface::OffscreenQmlSurface() {
|
OffscreenQmlSurface::OffscreenQmlSurface() {
|
||||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
|
||||||
connect(pointerManager.data(), &PointerManager::hoverBeginHUD, this, &OffscreenQmlSurface::handlePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::hoverContinueHUD, this, &OffscreenQmlSurface::handlePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::hoverEndHUD, this, &OffscreenQmlSurface::handlePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::triggerBeginHUD, this, &OffscreenQmlSurface::handlePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::triggerContinueHUD, this, &OffscreenQmlSurface::handlePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::triggerEndHUD, this, &OffscreenQmlSurface::handlePointerEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OffscreenQmlSurface::~OffscreenQmlSurface() {
|
OffscreenQmlSurface::~OffscreenQmlSurface() {
|
||||||
|
@ -941,8 +932,14 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even
|
||||||
transformedPos,
|
transformedPos,
|
||||||
mouseEvent->screenPos(), mouseEvent->button(),
|
mouseEvent->screenPos(), mouseEvent->button(),
|
||||||
mouseEvent->buttons(), mouseEvent->modifiers());
|
mouseEvent->buttons(), mouseEvent->modifiers());
|
||||||
if (sendMouseEvent(mappedEvent)) {
|
if (event->type() == QEvent::MouseMove) {
|
||||||
return true;
|
// TODO - this line necessary for the QML Tooltop to work (which is not currently being used), but it causes interface to crash on launch on a fresh install
|
||||||
|
// need to investigate into why this crash is happening.
|
||||||
|
//_qmlContext->setContextProperty("lastMousePosition", mouseEvent.localPos());
|
||||||
|
}
|
||||||
|
mappedEvent.ignore();
|
||||||
|
if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) {
|
||||||
|
return mappedEvent.isAccepted();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -954,46 +951,6 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::handlePointerEvent(const QUuid& id, const PointerEvent& event) {
|
|
||||||
if (_paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QEvent::Type type = QEvent::Type::MouseMove;
|
|
||||||
switch (event.getType()) {
|
|
||||||
case PointerEvent::Press:
|
|
||||||
type = QEvent::Type::MouseButtonPress;
|
|
||||||
break;
|
|
||||||
case PointerEvent::DoublePress:
|
|
||||||
type = QEvent::Type::MouseButtonDblClick;
|
|
||||||
break;
|
|
||||||
case PointerEvent::Release:
|
|
||||||
type = QEvent::Type::MouseButtonRelease;
|
|
||||||
break;
|
|
||||||
case PointerEvent::Move:
|
|
||||||
type = QEvent::Type::MouseMove;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
QPointF screenPos(event.getPos2D().x, event.getPos2D().y);
|
|
||||||
QMouseEvent mouseEvent(type, screenPos, Qt::MouseButton(event.getButton()), Qt::MouseButtons(event.getButtons()), event.getKeyboardModifiers());
|
|
||||||
sendMouseEvent(mouseEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OffscreenQmlSurface::sendMouseEvent(QMouseEvent& mouseEvent) {
|
|
||||||
if (mouseEvent.type() == QEvent::MouseMove) {
|
|
||||||
// TODO - this line necessary for the QML Tooltop to work (which is not currently being used), but it causes interface to crash on launch on a fresh install
|
|
||||||
// need to investigate into why this crash is happening.
|
|
||||||
//_qmlContext->setContextProperty("lastMousePosition", mouseEvent.localPos());
|
|
||||||
}
|
|
||||||
mouseEvent.ignore();
|
|
||||||
if (QCoreApplication::sendEvent(_quickWindow, &mouseEvent)) {
|
|
||||||
return mouseEvent.isAccepted();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OffscreenQmlSurface::pause() {
|
void OffscreenQmlSurface::pause() {
|
||||||
_paused = true;
|
_paused = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,6 @@ class QQmlContext;
|
||||||
class QQmlComponent;
|
class QQmlComponent;
|
||||||
class QQuickWindow;
|
class QQuickWindow;
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
class QMouseEvent;
|
|
||||||
class PointerEvent;
|
|
||||||
|
|
||||||
// GPU resources are typically buffered for one copy being used by the renderer,
|
// GPU resources are typically buffered for one copy being used by the renderer,
|
||||||
// one copy in flight, and one copy being used by the receiver
|
// one copy in flight, and one copy being used by the receiver
|
||||||
|
@ -137,7 +135,6 @@ private:
|
||||||
private slots:
|
private slots:
|
||||||
void updateQuick();
|
void updateQuick();
|
||||||
void onFocusObjectChanged(QObject* newFocus);
|
void onFocusObjectChanged(QObject* newFocus);
|
||||||
void handlePointerEvent(const QUuid& id, const PointerEvent& event);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QQuickWindow* _quickWindow { nullptr };
|
QQuickWindow* _quickWindow { nullptr };
|
||||||
|
@ -164,8 +161,6 @@ private:
|
||||||
QWindow* _proxyWindow { nullptr };
|
QWindow* _proxyWindow { nullptr };
|
||||||
|
|
||||||
QQuickItem* _currentFocusItem { nullptr };
|
QQuickItem* _currentFocusItem { nullptr };
|
||||||
|
|
||||||
bool sendMouseEvent(QMouseEvent& mouseEvent);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue