Merge pull request #11584 from SamGondelman/pointerEvents

First step of cleaning up PointerEvents
This commit is contained in:
Bradley Austin Davis 2017-10-26 12:01:03 -07:00 committed by GitHub
commit becd99a964
13 changed files with 284 additions and 358 deletions

View file

@ -692,7 +692,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<CloseEventSender>(); DependencyManager::set<CloseEventSender>();
DependencyManager::set<ResourceManager>(); DependencyManager::set<ResourceManager>();
DependencyManager::set<SelectionScriptingInterface>(); DependencyManager::set<SelectionScriptingInterface>();
DependencyManager::set<ContextOverlayInterface>();
DependencyManager::set<Ledger>(); DependencyManager::set<Ledger>();
DependencyManager::set<Wallet>(); DependencyManager::set<Wallet>();
DependencyManager::set<WalletScriptingInterface>(); DependencyManager::set<WalletScriptingInterface>();
@ -1188,7 +1187,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// allow you to move an entity around in your hand // allow you to move an entity around in your hand
_entityEditSender.setPacketsPerSecond(3000); // super high!! _entityEditSender.setPacketsPerSecond(3000); // super high!!
// Overlays need to exist before we set the ContextOverlayInterface dependency
_overlays.init(); // do this before scripts load _overlays.init(); // do this before scripts load
DependencyManager::set<ContextOverlayInterface>();
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
updateHeartbeat(); updateHeartbeat();
@ -1478,53 +1480,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
} }
}); });
// If the user clicks somewhere where there is NO entity at all, we will release focus
connect(getEntities().data(), &EntityTreeRenderer::mousePressOffEntity, [=]() {
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
});
// Keyboard focus handling for Web overlays. // Keyboard focus handling for Web overlays.
auto overlays = &(qApp->getOverlays()); auto overlays = &(qApp->getOverlays());
connect(overlays, &Overlays::mousePressOnOverlay, [=](const OverlayID& overlayID, const PointerEvent& event) {
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays->getOverlay(overlayID));
// Only Web overlays can have keyboard focus.
if (thisOverlay) {
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
setKeyboardFocusOverlay(overlayID);
}
});
connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) { connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
if (overlayID == _keyboardFocusedOverlay.get()) { if (overlayID == _keyboardFocusedOverlay.get()) {
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
} }
}); });
connect(overlays, &Overlays::mousePressOffOverlay, [=]() {
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
});
connect(this, &Application::aboutToQuit, [=]() { connect(this, &Application::aboutToQuit, [=]() {
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
}); });
connect(overlays,
SIGNAL(mousePressOnOverlay(const OverlayID&, const PointerEvent&)),
DependencyManager::get<ContextOverlayInterface>().data(),
SLOT(contextOverlays_mousePressOnOverlay(const OverlayID&, const PointerEvent&)));
connect(overlays,
SIGNAL(hoverEnterOverlay(const OverlayID&, const PointerEvent&)),
DependencyManager::get<ContextOverlayInterface>().data(),
SLOT(contextOverlays_hoverEnterOverlay(const OverlayID&, const PointerEvent&)));
connect(overlays,
SIGNAL(hoverLeaveOverlay(const OverlayID&, const PointerEvent&)),
DependencyManager::get<ContextOverlayInterface>().data(),
SLOT(contextOverlays_hoverLeaveOverlay(const OverlayID&, const PointerEvent&)));
// 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;
@ -4561,14 +4529,9 @@ QUuid Application::getKeyboardFocusEntity() const {
return _keyboardFocusedEntity.get(); return _keyboardFocusedEntity.get();
} }
void Application::setKeyboardFocusEntity(QUuid id) {
EntityItemID entityItemID(id);
setKeyboardFocusEntity(entityItemID);
}
static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
void Application::setKeyboardFocusEntity(EntityItemID entityItemID) { void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {
if (_keyboardFocusedEntity.get() != entityItemID) { if (_keyboardFocusedEntity.get() != entityItemID) {
_keyboardFocusedEntity.set(entityItemID); _keyboardFocusedEntity.set(entityItemID);
@ -4605,7 +4568,7 @@ OverlayID Application::getKeyboardFocusOverlay() {
return _keyboardFocusedOverlay.get(); return _keyboardFocusedOverlay.get();
} }
void Application::setKeyboardFocusOverlay(OverlayID overlayID) { void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
if (overlayID != _keyboardFocusedOverlay.get()) { if (overlayID != _keyboardFocusedOverlay.get()) {
_keyboardFocusedOverlay.set(overlayID); _keyboardFocusedOverlay.set(overlayID);
@ -7443,51 +7406,6 @@ bool Application::isForeground() const {
return _isForeground && !_window->isMinimized(); return _isForeground && !_window->isMinimized();
} }
void Application::sendMousePressOnEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->mousePressOnEntity(entityItemID, event);
}
void Application::sendMouseMoveOnEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->mouseMoveOnEntity(entityItemID, event);
}
void Application::sendMouseReleaseOnEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->mouseReleaseOnEntity(entityItemID, event);
}
void Application::sendClickDownOnEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->clickDownOnEntity(entityItemID, event);
}
void Application::sendHoldingClickOnEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->holdingClickOnEntity(entityItemID, event);
}
void Application::sendClickReleaseOnEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->clickReleaseOnEntity(entityItemID, event);
}
void Application::sendHoverEnterEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->hoverEnterEntity(entityItemID, event);
}
void Application::sendHoverOverEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->hoverOverEntity(entityItemID, event);
}
void Application::sendHoverLeaveEntity(QUuid id, PointerEvent event) {
EntityItemID entityItemID(id);
emit getEntities()->hoverLeaveEntity(entityItemID, event);
}
// FIXME? perhaps two, one for the main thread and one for the offscreen UI rendering thread? // FIXME? perhaps two, one for the main thread and one for the offscreen UI rendering thread?
static const int UI_RESERVED_THREADS = 1; static const int UI_RESERVED_THREADS = 1;
// Windows won't let you have all the cores // Windows won't let you have all the cores

View file

@ -277,18 +277,6 @@ public:
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; } gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; } gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; }
Q_INVOKABLE void sendMousePressOnEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendMouseMoveOnEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendMouseReleaseOnEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendClickDownOnEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendHoldingClickOnEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendClickReleaseOnEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendHoverEnterEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendHoverOverEntity(QUuid id, PointerEvent event);
Q_INVOKABLE void sendHoverLeaveEntity(QUuid id, PointerEvent event);
OverlayID getTabletScreenID() const; OverlayID getTabletScreenID() const;
OverlayID getTabletHomeButtonID() const; OverlayID getTabletHomeButtonID() const;
QUuid getTabletFrameID() const; // may be an entity or an overlay QUuid getTabletFrameID() const; // may be an entity or an overlay
@ -389,11 +377,10 @@ public slots:
void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions); void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions);
QUuid getKeyboardFocusEntity() const; // thread-safe QUuid getKeyboardFocusEntity() const; // thread-safe
void setKeyboardFocusEntity(QUuid id); void setKeyboardFocusEntity(const EntityItemID& entityItemID);
void setKeyboardFocusEntity(EntityItemID entityItemID);
OverlayID getKeyboardFocusOverlay(); OverlayID getKeyboardFocusOverlay();
void setKeyboardFocusOverlay(OverlayID overlayID); void setKeyboardFocusOverlay(const OverlayID& overlayID);
void addAssetToWorldMessageClose(); void addAssetToWorldMessageClose();

View file

@ -43,10 +43,10 @@ ContextOverlayInterface::ContextOverlayInterface() {
_entityPropertyFlags += PROP_REGISTRATION_POINT; _entityPropertyFlags += PROP_REGISTRATION_POINT;
_entityPropertyFlags += PROP_CERTIFICATE_ID; _entityPropertyFlags += PROP_CERTIFICATE_ID;
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>().data(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
connect(entityTreeRenderer, SIGNAL(mousePressOnEntity(const EntityItemID&, const PointerEvent&)), this, SLOT(createOrDestroyContextOverlay(const EntityItemID&, const PointerEvent&))); connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &ContextOverlayInterface::createOrDestroyContextOverlay);
connect(entityTreeRenderer, SIGNAL(hoverEnterEntity(const EntityItemID&, const PointerEvent&)), this, SLOT(contextOverlays_hoverEnterEntity(const EntityItemID&, const PointerEvent&))); connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, &ContextOverlayInterface::contextOverlays_hoverEnterEntity);
connect(entityTreeRenderer, SIGNAL(hoverLeaveEntity(const EntityItemID&, const PointerEvent&)), this, SLOT(contextOverlays_hoverLeaveEntity(const EntityItemID&, const PointerEvent&))); connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, &ContextOverlayInterface::contextOverlays_hoverLeaveEntity);
connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() { connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() {
if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) { if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) {
QUuid tabletFrameID = _hmdScriptingInterface->getCurrentTabletFrameID(); QUuid tabletFrameID = _hmdScriptingInterface->getCurrentTabletFrameID();
@ -59,9 +59,12 @@ ContextOverlayInterface::ContextOverlayInterface() {
_contextOverlayJustClicked = false; _contextOverlayJustClicked = false;
} }
}); });
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity); connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity);
connect(&qApp->getOverlays(), &Overlays::mousePressOnOverlay, this, &ContextOverlayInterface::contextOverlays_mousePressOnOverlay);
connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay);
connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged); connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged);
} }

View file

@ -717,39 +717,34 @@ bool Overlays::isAddedOverlay(OverlayID id) {
} }
void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
QMetaObject::invokeMethod(this, "mousePressOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event)); mousePressEvent(overlayID, event);
} }
void Overlays::sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { void Overlays::sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
QMetaObject::invokeMethod(this, "mouseReleaseOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event)); mouseReleaseEvent(overlayID, event);
} }
void Overlays::sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { void Overlays::sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
QMetaObject::invokeMethod(this, "mouseMoveOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event)); mouseMoveEvent(overlayID, event);
} }
void Overlays::sendHoverEnterOverlay(const OverlayID& id, const PointerEvent& event) { void Overlays::sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event) {
QMetaObject::invokeMethod(this, "hoverEnterOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event)); emit hoverEnterOverlay(overlayID, event);
} }
void Overlays::sendHoverOverOverlay(const OverlayID& id, const PointerEvent& event) { void Overlays::sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event) {
QMetaObject::invokeMethod(this, "hoverOverOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event)); emit hoverOverOverlay(overlayID, event);
} }
void Overlays::sendHoverLeaveOverlay(const OverlayID& id, const PointerEvent& event) { void Overlays::sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event) {
QMetaObject::invokeMethod(this, "hoverLeaveOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event)); hoverLeaveEvent(overlayID, event);
} }
OverlayID Overlays::getKeyboardFocusOverlay() { OverlayID Overlays::getKeyboardFocusOverlay() {
return qApp->getKeyboardFocusOverlay(); return qApp->getKeyboardFocusOverlay();
} }
void Overlays::setKeyboardFocusOverlay(OverlayID id) { void Overlays::setKeyboardFocusOverlay(const OverlayID& id) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setKeyboardFocusOverlay", Q_ARG(OverlayID, id));
return;
}
qApp->setKeyboardFocusOverlay(id); qApp->setKeyboardFocusOverlay(id);
} }
@ -884,13 +879,35 @@ bool Overlays::mousePressEvent(QMouseEvent* event) {
_currentClickingOnOverlayID = rayPickResult.overlayID; _currentClickingOnOverlayID = rayPickResult.overlayID;
PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press); PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
emit mousePressOnOverlay(_currentClickingOnOverlayID, pointerEvent); mousePressEvent(_currentClickingOnOverlayID, pointerEvent);
return true; return true;
} }
// if we didn't press on an overlay, disable overlay keyboard focus
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
// emit to scripts
emit mousePressOffOverlay(); emit mousePressOffOverlay();
return false; return false;
} }
void Overlays::mousePressEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
}
if (thisOverlay) {
// Focus keyboard on web overlays
DependencyManager::get<EntityScriptingInterface>()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
setKeyboardFocusOverlay(overlayID);
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
// emit to scripts
emit mousePressOnOverlay(overlayID, event);
}
bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
@ -900,13 +917,30 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
_currentClickingOnOverlayID = rayPickResult.overlayID; _currentClickingOnOverlayID = rayPickResult.overlayID;
auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press); auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
// emit to scripts
emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent); emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
return true; return true;
} }
// emit to scripts
emit mouseDoublePressOffOverlay(); emit mouseDoublePressOffOverlay();
return false; return false;
} }
void Overlays::hoverLeaveEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "hoverLeaveOverlay", Q_ARG(PointerEvent, event));
}
// emit to scripts
emit hoverLeaveOverlay(overlayID, event);
}
bool Overlays::mouseReleaseEvent(QMouseEvent* event) { bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent"); PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
@ -914,13 +948,28 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray); RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release); auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
emit mouseReleaseOnOverlay(rayPickResult.overlayID, pointerEvent); mouseReleaseEvent(rayPickResult.overlayID, pointerEvent);
} }
_currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID; _currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID;
return false; return false;
} }
void Overlays::mouseReleaseEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
// emit to scripts
emit mouseReleaseOnOverlay(overlayID, event);
}
bool Overlays::mouseMoveEvent(QMouseEvent* event) { bool Overlays::mouseMoveEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseMoveEvent"); PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
@ -928,12 +977,12 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray); RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move); auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
emit mouseMoveOnOverlay(rayPickResult.overlayID, pointerEvent); mouseMoveEvent(rayPickResult.overlayID, pointerEvent);
// If previously hovering over a different overlay then leave hover on that overlay. // If previously hovering over a different overlay then leave hover on that overlay.
if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) { if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) {
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move); auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
emit hoverLeaveOverlay(_currentHoverOverOverlayID, pointerEvent); hoverLeaveEvent(_currentHoverOverOverlayID, pointerEvent);
} }
// If hovering over a new overlay then enter hover on that overlay. // If hovering over a new overlay then enter hover on that overlay.
@ -949,7 +998,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
// If previously hovering an overlay then leave hover. // If previously hovering an overlay then leave hover.
if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID) { if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID) {
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move); auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
emit hoverLeaveOverlay(_currentHoverOverOverlayID, pointerEvent); hoverLeaveEvent(_currentHoverOverOverlayID, pointerEvent);
_currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID; _currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID;
} }
@ -957,6 +1006,21 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
return false; return false;
} }
void Overlays::mouseMoveEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
// emit to scripts
emit mouseMoveOnOverlay(overlayID, event);
}
QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) {
QVector<QUuid> result; QVector<QUuid> result;
//if (QThread::currentThread() != thread()) { //if (QThread::currentThread() != thread()) {

View file

@ -107,6 +107,11 @@ public:
bool mouseReleaseEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event);
bool mouseMoveEvent(QMouseEvent* event); bool mouseMoveEvent(QMouseEvent* event);
void mousePressEvent(const OverlayID& overlayID, const PointerEvent& event);
void mouseMoveEvent(const OverlayID& overlayID, const PointerEvent& event);
void mouseReleaseEvent(const OverlayID& overlayID, const PointerEvent& event);
void hoverLeaveEvent(const OverlayID& overlayID, const PointerEvent& event);
void cleanupAllOverlays(); void cleanupAllOverlays();
public slots: public slots:
@ -298,12 +303,12 @@ public slots:
void sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event); void sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
void sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event); void sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
void sendHoverEnterOverlay(const OverlayID& id, const PointerEvent& event); void sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event);
void sendHoverOverOverlay(const OverlayID& id, const PointerEvent& event); void sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event);
void sendHoverLeaveOverlay(const OverlayID& id, const PointerEvent& event); void sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event);
OverlayID getKeyboardFocusOverlay(); OverlayID getKeyboardFocusOverlay();
void setKeyboardFocusOverlay(OverlayID id); void setKeyboardFocusOverlay(const OverlayID& id);
signals: signals:
/**jsdoc /**jsdoc

View file

@ -125,11 +125,7 @@ void Web3DOverlay::destroyWebSurface() {
} }
_webSurface->pause(); _webSurface->pause();
auto overlays = &(qApp->getOverlays());
QObject::disconnect(overlays, &Overlays::mousePressOnOverlay, this, nullptr);
QObject::disconnect(overlays, &Overlays::mouseReleaseOnOverlay, this, nullptr);
QObject::disconnect(overlays, &Overlays::mouseMoveOnOverlay, this, nullptr);
QObject::disconnect(overlays, &Overlays::hoverLeaveOverlay, this, nullptr);
QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent); QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived); QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, _webSurface); DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, _webSurface);
@ -160,35 +156,17 @@ void Web3DOverlay::buildWebSurface() {
_webSurface->resume(); _webSurface->resume();
}); });
auto selfOverlayID = getOverlayID();
std::weak_ptr<Web3DOverlay> weakSelf = std::dynamic_pointer_cast<Web3DOverlay>(qApp->getOverlays().getOverlay(selfOverlayID));
auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) {
auto self = weakSelf.lock();
if (self && overlayID == selfOverlayID) {
self->handlePointerEvent(event);
}
};
auto overlays = &(qApp->getOverlays());
QObject::connect(overlays, &Overlays::mousePressOnOverlay, this, forwardPointerEvent);
QObject::connect(overlays, &Overlays::mouseReleaseOnOverlay, this, forwardPointerEvent);
QObject::connect(overlays, &Overlays::mouseMoveOnOverlay, this, forwardPointerEvent);
QObject::connect(overlays, &Overlays::hoverLeaveOverlay, this, [=](OverlayID overlayID, const PointerEvent& event) {
auto self = weakSelf.lock();
if (!self) {
return;
}
if (overlayID == selfOverlayID && (self->_pressed || (!self->_activeTouchPoints.empty() && self->_touchBeginAccepted))) {
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
forwardPointerEvent(overlayID, endEvent);
}
});
QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent); QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
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) {

View file

@ -39,7 +39,8 @@ public:
QObject* getEventHandler(); QObject* getEventHandler();
void setProxyWindow(QWindow* proxyWindow); void setProxyWindow(QWindow* proxyWindow);
void handlePointerEvent(const PointerEvent& event); Q_INVOKABLE void hoverLeaveOverlay(const PointerEvent& event);
Q_INVOKABLE void handlePointerEvent(const PointerEvent& event);
void handlePointerEventAsTouch(const PointerEvent& event); void handlePointerEventAsTouch(const PointerEvent& event);
void handlePointerEventAsMouse(const PointerEvent& event); void handlePointerEventAsMouse(const PointerEvent& event);

View file

@ -35,6 +35,8 @@
#include "EntitiesRendererLogging.h" #include "EntitiesRendererLogging.h"
#include "RenderableEntityItem.h" #include "RenderableEntityItem.h"
#include "RenderableWebEntityItem.h"
size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); } size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); }
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction; std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction;
@ -55,6 +57,32 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
EntityRenderer::initEntityRenderers(); EntityRenderer::initEntityRenderers();
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID; _currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID; _currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
// Forward mouse events to web entities
auto handlePointerEvent = [&](const EntityItemID& entityID, const PointerEvent& event) {
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID);
if (entity && entity->getType() == EntityTypes::Web) {
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
}
if (thisEntity) {
QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
};
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
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<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID);
if (entity && entity->getType() == EntityTypes::Web) {
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
}
if (thisEntity) {
QMetaObject::invokeMethod(thisEntity.get(), "hoverLeaveEntity", Q_ARG(PointerEvent, event));
}
});
} }
EntityTreeRenderer::~EntityTreeRenderer() { EntityTreeRenderer::~EntityTreeRenderer() {
@ -78,13 +106,49 @@ render::ItemID EntityTreeRenderer::renderableIdForEntityId(const EntityItemID& i
int EntityTreeRenderer::_entitiesScriptEngineCount = 0; int EntityTreeRenderer::_entitiesScriptEngineCount = 0;
void EntityTreeRenderer::resetEntitiesScriptEngine() { void EntityTreeRenderer::resetEntitiesScriptEngine() {
auto oldEngine = _entitiesScriptEngine;
_entitiesScriptEngine = scriptEngineFactory(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT, _entitiesScriptEngine = scriptEngineFactory(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT,
QString("about:Entities %1").arg(++_entitiesScriptEngineCount)); QString("about:Entities %1").arg(++_entitiesScriptEngineCount));
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine); _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
_entitiesScriptEngine->runInThread(); _entitiesScriptEngine->runInThread();
auto entitiesScriptEngineProvider = qSharedPointerCast<EntitiesScriptEngineProvider>(_entitiesScriptEngine); auto entitiesScriptEngineProvider = qSharedPointerCast<EntitiesScriptEngineProvider>(_entitiesScriptEngine);
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(entitiesScriptEngineProvider); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
entityScriptingInterface->setEntitiesScriptEngine(entitiesScriptEngineProvider);
// Connect mouse events to entity script callbacks
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mousePressOnEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseDoublePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseDoublePressOnEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveOnEntity", event);
// FIXME: this is a duplicate of mouseMoveOnEntity, but it seems like some scripts might use this naming
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveEvent", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseReleaseOnEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "clickDownOnEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::holdingClickOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "holdingClickOnEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "clickReleaseOnEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverEnterEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverOverEntity", event);
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
_entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverLeaveEntity", event);
});
} }
void EntityTreeRenderer::clear() { void EntityTreeRenderer::clear() {
@ -264,8 +328,7 @@ void EntityTreeRenderer::update(bool simulate) {
// not yet released the hold then this is still considered a holdingClickOnEntity event // not yet released the hold then this is still considered a holdingClickOnEntity event
// and we want to simulate this message here as well as in mouse move // and we want to simulate this message here as well as in mouse move
if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) { if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) {
emit holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent); emit DependencyManager::get<EntityScriptingInterface>()->holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent);
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", _lastPointerEvent);
} }
} }
@ -435,19 +498,6 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha
} }
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) { void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
connect(this, &EntityTreeRenderer::clickDownOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickDownOnEntity);
connect(this, &EntityTreeRenderer::holdingClickOnEntity, entityScriptingInterface, &EntityScriptingInterface::holdingClickOnEntity);
connect(this, &EntityTreeRenderer::clickReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickReleaseOnEntity);
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity); connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity);
connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity); connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity);
connect(this, &EntityTreeRenderer::collisionWithEntity, entityScriptingInterface, &EntityScriptingInterface::collisionWithEntity); connect(this, &EntityTreeRenderer::collisionWithEntity, entityScriptingInterface, &EntityScriptingInterface::collisionWithEntity);
@ -516,13 +566,11 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) { if (rayPickResult.intersects && rayPickResult.entity) {
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID; auto properties = rayPickResult.entity->getProperties();
auto entity = getTree()->findEntityByEntityItemID(rayPickResult.entityID);
auto properties = entity->getProperties();
QString urlString = properties.getHref(); QString urlString = properties.getHref();
QUrl url = QUrl(urlString, QUrl::StrictMode); QUrl url = QUrl(urlString, QUrl::StrictMode);
if (url.isValid() && !url.isEmpty()){ if (url.isValid() && !url.isEmpty()){
@ -536,23 +584,16 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
toPointerButton(*event), toPointerButtons(*event), toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys? Qt::NoModifier); // TODO -- check for modifier keys?
emit mousePressOnEntity(rayPickResult.entityID, pointerEvent); emit entityScriptingInterface->mousePressOnEntity(rayPickResult.entityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mousePressOnEntity", pointerEvent);
}
_currentClickingOnEntityID = rayPickResult.entityID; _currentClickingOnEntityID = rayPickResult.entityID;
emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent); emit entityScriptingInterface->clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "clickDownOnEntity", pointerEvent);
}
_lastPointerEvent = pointerEvent; _lastPointerEvent = pointerEvent;
_lastPointerEventValid = true; _lastPointerEventValid = true;
} else { } else {
emit mousePressOffEntity(); emit entityScriptingInterface->mousePressOffEntity();
} }
} }
@ -564,34 +605,25 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) { if (rayPickResult.intersects && rayPickResult.entity) {
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID, PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection, pos2D, rayPickResult.intersection,
rayPickResult.surfaceNormal, ray.direction, rayPickResult.surfaceNormal, ray.direction,
toPointerButton(*event), toPointerButtons(*event), Qt::NoModifier); toPointerButton(*event), toPointerButtons(*event), Qt::NoModifier);
emit mouseDoublePressOnEntity(rayPickResult.entityID, pointerEvent); emit entityScriptingInterface->mouseDoublePressOnEntity(rayPickResult.entityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseDoublePressOnEntity", pointerEvent);
}
_currentClickingOnEntityID = rayPickResult.entityID; _currentClickingOnEntityID = rayPickResult.entityID;
emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent); emit entityScriptingInterface->clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "doubleclickOnEntity", pointerEvent);
}
_lastPointerEvent = pointerEvent; _lastPointerEvent = pointerEvent;
_lastPointerEventValid = true; _lastPointerEventValid = true;
} else { } else {
emit mouseDoublePressOffEntity(); emit entityScriptingInterface->mouseDoublePressOffEntity();
} }
} }
@ -603,9 +635,10 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) { if (rayPickResult.intersects && rayPickResult.entity) {
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; //qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
@ -615,31 +648,23 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
toPointerButton(*event), toPointerButtons(*event), toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys? Qt::NoModifier); // TODO -- check for modifier keys?
emit mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent); emit entityScriptingInterface->mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseReleaseOnEntity", pointerEvent);
}
_lastPointerEvent = pointerEvent; _lastPointerEvent = pointerEvent;
_lastPointerEventValid = true; _lastPointerEventValid = true;
} }
// Even if we're no longer intersecting with an entity, if we started clicking on it, and now // Even if we're no longer intersecting with an entity, if we started clicking on it, and now
// we're releasing the button, then this is considered a clickOn event // we're releasing the button, then this is considered a clickReleaseOn event
if (!_currentClickingOnEntityID.isInvalidID()) { if (!_currentClickingOnEntityID.isInvalidID()) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
auto entity = getTree()->findEntityByID(_currentClickingOnEntityID);
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID, PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection, pos2D, rayPickResult.intersection,
rayPickResult.surfaceNormal, ray.direction, rayPickResult.surfaceNormal, ray.direction,
toPointerButton(*event), toPointerButtons(*event), toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys? Qt::NoModifier); // TODO -- check for modifier keys?
emit clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent); emit entityScriptingInterface->clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "clickReleaseOnEntity", pointerEvent);
}
} }
// makes it the unknown ID, we just released so we can't be clicking on anything // makes it the unknown ID, we just released so we can't be clicking on anything
@ -654,9 +679,10 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) { if (rayPickResult.intersects && rayPickResult.entity) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection, pos2D, rayPickResult.intersection,
@ -664,48 +690,32 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
toPointerButton(*event), toPointerButtons(*event), toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys? Qt::NoModifier); // TODO -- check for modifier keys?
emit mouseMoveOnEntity(rayPickResult.entityID, pointerEvent); emit entityScriptingInterface->mouseMoveOnEntity(rayPickResult.entityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveEvent", pointerEvent);
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveOnEntity", pointerEvent);
}
// handle the hover logic... // handle the hover logic...
// if we were previously hovering over an entity, and this new entity is not the same as our previous entity // if we were previously hovering over an entity, and this new entity is not the same as our previous entity
// then we need to send the hover leave. // then we need to send the hover leave.
if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
auto entity = getTree()->findEntityByID(_currentHoverOverEntityID);
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection, pos2D, rayPickResult.intersection,
rayPickResult.surfaceNormal, ray.direction, rayPickResult.surfaceNormal, ray.direction,
toPointerButton(*event), toPointerButtons(*event), toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys? Qt::NoModifier); // TODO -- check for modifier keys?
emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent); emit entityScriptingInterface->hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent);
}
} }
// If the new hover entity does not match the previous hover entity then we are entering the new one // If the new hover entity does not match the previous hover entity then we are entering the new one
// this is true if the _currentHoverOverEntityID is known or unknown // this is true if the _currentHoverOverEntityID is known or unknown
if (rayPickResult.entityID != _currentHoverOverEntityID) { if (rayPickResult.entityID != _currentHoverOverEntityID) {
emit hoverEnterEntity(rayPickResult.entityID, pointerEvent); emit entityScriptingInterface->hoverEnterEntity(rayPickResult.entityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverEnterEntity", pointerEvent);
}
} }
// and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and
// we should send our hover over event // we should send our hover over event
emit hoverOverEntity(rayPickResult.entityID, pointerEvent); emit entityScriptingInterface->hoverOverEntity(rayPickResult.entityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverOverEntity", pointerEvent);
}
// remember what we're hovering over // remember what we're hovering over
_currentHoverOverEntityID = rayPickResult.entityID; _currentHoverOverEntityID = rayPickResult.entityID;
@ -718,38 +728,18 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to // if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
// send the hover leave for our previous entity // send the hover leave for our previous entity
if (!_currentHoverOverEntityID.isInvalidID()) { if (!_currentHoverOverEntityID.isInvalidID()) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
auto entity = getTree()->findEntityByID(_currentHoverOverEntityID);
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection, pos2D, rayPickResult.intersection,
rayPickResult.surfaceNormal, ray.direction, rayPickResult.surfaceNormal, ray.direction,
toPointerButton(*event), toPointerButtons(*event), toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys? Qt::NoModifier); // TODO -- check for modifier keys?
emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent); emit entityScriptingInterface->hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent);
}
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID _currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID
}
}
// Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have _lastPointerEvent = pointerEvent;
// not yet released the hold then this is still considered a holdingClickOnEntity event _lastPointerEventValid = true;
if (!_currentClickingOnEntityID.isInvalidID()) {
auto entity = getTree()->findEntityByID(_currentClickingOnEntityID);
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection,
rayPickResult.surfaceNormal, ray.direction,
toPointerButton(*event), toPointerButtons(*event),
Qt::NoModifier); // TODO -- check for modifier keys?
emit holdingClickOnEntity(_currentClickingOnEntityID, pointerEvent);
if (_entitiesScriptEngine) {
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", pointerEvent);
} }
} }
} }

View file

@ -117,21 +117,6 @@ public:
void onEntityChanged(const EntityItemID& id); void onEntityChanged(const EntityItemID& id);
signals: signals:
void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mouseDoublePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mousePressOffEntity();
void mouseDoublePressOffEntity();
void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void clickReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void hoverEnterEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void hoverOverEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void hoverLeaveEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void enterEntity(const EntityItemID& entityItemID); void enterEntity(const EntityItemID& entityItemID);
void leaveEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID);
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);

View file

@ -24,7 +24,6 @@
#include <ui/TabletScriptingInterface.h> #include <ui/TabletScriptingInterface.h>
#include <EntityScriptingInterface.h> #include <EntityScriptingInterface.h>
#include "EntityTreeRenderer.h"
#include "EntitiesRendererLogging.h" #include "EntitiesRendererLogging.h"
@ -86,6 +85,10 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
return true; return true;
} }
if (_lastLocked != entity->getLocked()) {
return true;
}
return false; return false;
} }
@ -136,6 +139,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
} }
_lastDPI = entity->getDPI(); _lastDPI = entity->getDPI();
_lastLocked = entity->getLocked();
glm::vec2 windowSize = getWindowSize(entity); glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y)); _webSurface->resize(QSize(windowSize.x, windowSize.y));
@ -234,38 +238,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
emit entities->webEventReceived(entityItemID, message); emit entities->webEventReceived(entityItemID, message);
}); });
auto forwardPointerEvent = [=](const EntityItemID& entityItemID, const PointerEvent& event) {
if (entityItemID == entity->getID()) {
handlePointerEvent(entity, event);
}
};
auto renderer = DependencyManager::get<EntityTreeRenderer>();
QObject::connect(renderer.data(), &EntityTreeRenderer::mousePressOnEntity, this, forwardPointerEvent);
QObject::connect(renderer.data(), &EntityTreeRenderer::mouseReleaseOnEntity, this, forwardPointerEvent);
QObject::connect(renderer.data(), &EntityTreeRenderer::mouseMoveOnEntity, this, forwardPointerEvent);
QObject::connect(renderer.data(), &EntityTreeRenderer::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<QTouchEvent::TouchPoint> 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; return true;
} }
@ -295,13 +267,6 @@ void WebEntityRenderer::destroyWebSurface() {
} }
webSurface->pause(); webSurface->pause();
auto renderer = DependencyManager::get<EntityTreeRenderer>();
if (renderer) {
QObject::disconnect(renderer.data(), &EntityTreeRenderer::mousePressOnEntity, this, nullptr);
QObject::disconnect(renderer.data(), &EntityTreeRenderer::mouseReleaseOnEntity, this, nullptr);
QObject::disconnect(renderer.data(), &EntityTreeRenderer::mouseMoveOnEntity, this, nullptr);
QObject::disconnect(renderer.data(), &EntityTreeRenderer::hoverLeaveEntity, this, nullptr);
}
webSurface.reset(); webSurface.reset();
} }
} }
@ -347,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<QTouchEvent::TouchPoint> 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 // Ignore mouse interaction if we're locked
if (entity->getLocked() || !_webSurface) { if (_lastLocked || !_webSurface) {
return; 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); QPointF windowPoint(windowPos.x, windowPos.y);
if (event.getType() == PointerEvent::Move) { if (event.getType() == PointerEvent::Move) {
// Forward a mouse move event to webSurface // Forward a mouse move event to webSurface

View file

@ -18,12 +18,16 @@ class PointerEvent;
namespace render { namespace entities { namespace render { namespace entities {
class WebEntityRenderer : public TypedEntityRenderer<WebEntityItem> { class WebEntityRenderer : public TypedEntityRenderer<WebEntityItem> {
Q_OBJECT
using Parent = TypedEntityRenderer<WebEntityItem>; using Parent = TypedEntityRenderer<WebEntityItem>;
friend class EntityRenderer; friend class EntityRenderer;
public: public:
WebEntityRenderer(const EntityItemPointer& entity); WebEntityRenderer(const EntityItemPointer& entity);
Q_INVOKABLE void hoverLeaveEntity(const PointerEvent& event);
Q_INVOKABLE void handlePointerEvent(const PointerEvent& event);
protected: protected:
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override; virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
virtual bool needsRenderUpdate() const override; virtual bool needsRenderUpdate() const override;
@ -44,9 +48,6 @@ private:
bool hasWebSurface(); bool hasWebSurface();
void loadSourceURL(); void loadSourceURL();
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const; glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
void handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event);
private:
int _geometryId{ 0 }; int _geometryId{ 0 };
enum contentType { enum contentType {
@ -60,6 +61,7 @@ private:
bool _pressed{ false }; bool _pressed{ false };
QString _lastSourceUrl; QString _lastSourceUrl;
uint16_t _lastDPI; uint16_t _lastDPI;
bool _lastLocked;
QTimer _timer; QTimer _timer;
uint64_t _lastRenderTime { 0 }; uint64_t _lastRenderTime { 0 };
Transform _renderTransform; Transform _renderTransform;

View file

@ -51,6 +51,10 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership
connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged); connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged);
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged); connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
// If the user clicks somewhere where there is no entity at all, we will release focus
connect(this, &EntityScriptingInterface::mousePressOffEntity, [=]() {
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
});
auto& packetReceiver = nodeList->getPacketReceiver(); auto& packetReceiver = nodeList->getPacketReceiver();
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket"); packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
@ -1674,44 +1678,44 @@ QUuid EntityScriptingInterface::getKeyboardFocusEntity() const {
return result; return result;
} }
void EntityScriptingInterface::setKeyboardFocusEntity(QUuid id) { void EntityScriptingInterface::setKeyboardFocusEntity(const EntityItemID& id) {
QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::QueuedConnection, Q_ARG(QUuid, id)); QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::DirectConnection, Q_ARG(EntityItemID, id));
} }
void EntityScriptingInterface::sendMousePressOnEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendMousePressOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit mousePressOnEntity(id, event);
} }
void EntityScriptingInterface::sendMouseMoveOnEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendMouseMoveOnEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendMouseMoveOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit mouseMoveOnEntity(id, event);
} }
void EntityScriptingInterface::sendMouseReleaseOnEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendMouseReleaseOnEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendMouseReleaseOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit mouseReleaseOnEntity(id, event);
} }
void EntityScriptingInterface::sendClickDownOnEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendClickDownOnEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendClickDownOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit clickDownOnEntity(id, event);
} }
void EntityScriptingInterface::sendHoldingClickOnEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendHoldingClickOnEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendHoldingClickOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit holdingClickOnEntity(id, event);
} }
void EntityScriptingInterface::sendClickReleaseOnEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendClickReleaseOnEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendClickReleaseOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit clickReleaseOnEntity(id, event);
} }
void EntityScriptingInterface::sendHoverEnterEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendHoverEnterEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendHoverEnterEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit hoverEnterEntity(id, event);
} }
void EntityScriptingInterface::sendHoverOverEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendHoverOverEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendHoverOverEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit hoverOverEntity(id, event);
} }
void EntityScriptingInterface::sendHoverLeaveEntity(QUuid id, PointerEvent event) { void EntityScriptingInterface::sendHoverLeaveEntity(const EntityItemID& id, const PointerEvent& event) {
QMetaObject::invokeMethod(qApp, "sendHoverLeaveEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event)); emit hoverLeaveEntity(id, event);
} }
bool EntityScriptingInterface::wantsHandControllerPointerEvents(QUuid id) { bool EntityScriptingInterface::wantsHandControllerPointerEvents(QUuid id) {

View file

@ -380,19 +380,19 @@ public slots:
Q_INVOKABLE QString getNestableType(QUuid id); Q_INVOKABLE QString getNestableType(QUuid id);
Q_INVOKABLE QUuid getKeyboardFocusEntity() const; Q_INVOKABLE QUuid getKeyboardFocusEntity() const;
Q_INVOKABLE void setKeyboardFocusEntity(QUuid id); Q_INVOKABLE void setKeyboardFocusEntity(const EntityItemID& id);
Q_INVOKABLE void sendMousePressOnEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendMouseMoveOnEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendMouseMoveOnEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendMouseReleaseOnEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendMouseReleaseOnEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendClickDownOnEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendClickDownOnEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendHoldingClickOnEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendHoldingClickOnEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendClickReleaseOnEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendClickReleaseOnEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendHoverEnterEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendHoverEnterEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendHoverOverEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendHoverOverEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE void sendHoverLeaveEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendHoverLeaveEntity(const EntityItemID& id, const PointerEvent& event);
Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id); Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id);
@ -439,8 +439,11 @@ signals:
void canWriteAssetsChanged(bool canWriteAssets); void canWriteAssetsChanged(bool canWriteAssets);
void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mouseDoublePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void mousePressOffEntity();
void mouseDoublePressOffEntity();
void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);