Merge pull request #15088 from SamGondelman/create

Case 21541: Fix mouse on create in HMD
This commit is contained in:
Sam Gondelman 2019-03-05 13:07:49 -08:00 committed by GitHub
commit 94cc5b83ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 129 additions and 213 deletions

View file

@ -1061,6 +1061,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged, connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged,
controllerScriptingInterface, &controller::ScriptingInterface::updateRunningInputDevices); controllerScriptingInterface, &controller::ScriptingInterface::updateRunningInputDevices);
EntityTree::setEntityClicksCapturedOperator([this] {
return _controllerScriptingInterface->areEntityClicksCaptured();
});
_entityClipboard->createRootElement(); _entityClipboard->createRootElement();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -4392,7 +4396,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||
getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) { getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) {
getEntities()->mouseMoveEvent(&mappedEvent); getEntities()->mouseMoveEvent(&mappedEvent);
getOverlays().mouseMoveEvent(&mappedEvent);
} }
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts
@ -4426,14 +4429,8 @@ void Application::mousePressEvent(QMouseEvent* event) {
#endif #endif
QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers()); QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers());
std::pair<float, QUuid> entityResult; QUuid result = getEntities()->mousePressEvent(&mappedEvent);
if (!_controllerScriptingInterface->areEntityClicksCaptured()) { setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(result) ? result : UNKNOWN_ENTITY_ID);
entityResult = getEntities()->mousePressEvent(&mappedEvent);
}
std::pair<float, QUuid> overlayResult = getOverlays().mousePressEvent(&mappedEvent);
QUuid focusedEntity = entityResult.first < overlayResult.first ? entityResult.second : overlayResult.second;
setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(focusedEntity) ? focusedEntity : UNKNOWN_ENTITY_ID);
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
@ -4472,11 +4469,7 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) {
transformedPos, transformedPos,
event->screenPos(), event->button(), event->screenPos(), event->button(),
event->buttons(), event->modifiers()); event->buttons(), event->modifiers());
getEntities()->mouseDoublePressEvent(&mappedEvent);
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
getEntities()->mouseDoublePressEvent(&mappedEvent);
}
getOverlays().mouseDoublePressEvent(&mappedEvent);
// if one of our scripts have asked to capture this event, then stop processing it // if one of our scripts have asked to capture this event, then stop processing it
if (_controllerScriptingInterface->isMouseCaptured()) { if (_controllerScriptingInterface->isMouseCaptured()) {
@ -4501,7 +4494,6 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
event->buttons(), event->modifiers()); event->buttons(), event->modifiers());
getEntities()->mouseReleaseEvent(&mappedEvent); getEntities()->mouseReleaseEvent(&mappedEvent);
getOverlays().mouseReleaseEvent(&mappedEvent);
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts

View file

@ -43,14 +43,6 @@ std::unordered_map<QString, QString> Overlays::_entityToOverlayTypes;
std::unordered_map<QString, QString> Overlays::_overlayToEntityTypes; std::unordered_map<QString, QString> Overlays::_overlayToEntityTypes;
Overlays::Overlays() { Overlays::Overlays() {
auto pointerManager = DependencyManager::get<PointerManager>();
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterPointerEvent);
connect(pointerManager.data(), &PointerManager::hoverContinueOverlay, this, &Overlays::hoverOverPointerEvent);
connect(pointerManager.data(), &PointerManager::hoverEndOverlay, this, &Overlays::hoverLeavePointerEvent);
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, this, &Overlays::mousePressPointerEvent);
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMovePointerEvent);
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, this, &Overlays::mouseReleasePointerEvent);
ADD_TYPE_MAP(Box, cube); ADD_TYPE_MAP(Box, cube);
ADD_TYPE_MAP(Sphere, sphere); ADD_TYPE_MAP(Sphere, sphere);
_overlayToEntityTypes["rectangle3d"] = "Shape"; _overlayToEntityTypes["rectangle3d"] = "Shape";
@ -81,13 +73,23 @@ void Overlays::cleanupAllOverlays() {
void Overlays::init() { void Overlays::init() {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
auto pointerManager = DependencyManager::get<PointerManager>(); auto pointerManager = DependencyManager::get<PointerManager>().data();
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, entityScriptingInterface , &EntityScriptingInterface::hoverEnterEntity); connect(pointerManager, &PointerManager::hoverBeginOverlay, entityScriptingInterface , &EntityScriptingInterface::hoverEnterEntity);
connect(pointerManager.data(), &PointerManager::hoverContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity); connect(pointerManager, &PointerManager::hoverContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
connect(pointerManager.data(), &PointerManager::hoverEndOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity); connect(pointerManager, &PointerManager::hoverEndOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity); connect(pointerManager, &PointerManager::triggerBeginOverlay, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity); connect(pointerManager, &PointerManager::triggerContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity); connect(pointerManager, &PointerManager::triggerEndOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &Overlays::mousePressOnPointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOffEntity, this, &Overlays::mousePressOffPointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::mouseDoublePressOnEntity, this, &Overlays::mouseDoublePressOnPointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::mouseDoublePressOffEntity, this, &Overlays::mouseDoublePressOffPointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, &Overlays::mouseReleasePointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity, this, &Overlays::mouseMovePointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity , this, &Overlays::hoverEnterPointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity, this, &Overlays::hoverOverPointerEvent);
connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, &Overlays::hoverLeavePointerEvent);
} }
void Overlays::update(float deltatime) { void Overlays::update(float deltatime) {
@ -1159,7 +1161,7 @@ bool Overlays::isAddedOverlay(const QUuid& id) {
} }
void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) { void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
mousePressPointerEvent(id, event); mousePressOnPointerEvent(id, event);
} }
void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) { void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) {
@ -1206,57 +1208,66 @@ float Overlays::height() {
return offscreenUi->getWindow()->size().height(); return offscreenUi->getWindow()->size().height();
} }
static uint32_t toPointerButtons(const QMouseEvent& event) { void Overlays::mousePressOnPointerEvent(const QUuid& id, const PointerEvent& event) {
uint32_t buttons = 0; auto keyboard = DependencyManager::get<Keyboard>();
buttons |= event.buttons().testFlag(Qt::LeftButton) ? PointerEvent::PrimaryButton : 0; // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
buttons |= event.buttons().testFlag(Qt::RightButton) ? PointerEvent::SecondaryButton : 0; if (!keyboard->getKeyIDs().contains(id)) {
buttons |= event.buttons().testFlag(Qt::MiddleButton) ? PointerEvent::TertiaryButton : 0; auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
return buttons; if (entity && entity->isLocalEntity()) {
} emit mousePressOnOverlay(id, event);
static PointerEvent::Button toPointerButton(const QMouseEvent& event) {
switch (event.button()) {
case Qt::LeftButton:
return PointerEvent::PrimaryButton;
case Qt::RightButton:
return PointerEvent::SecondaryButton;
case Qt::MiddleButton:
return PointerEvent::TertiaryButton;
default:
return PointerEvent::NoButtons;
}
}
RayToOverlayIntersectionResult getPrevPickResult() {
RayToOverlayIntersectionResult overlayResult;
overlayResult.intersects = false;
auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(DependencyManager::get<EntityTreeRenderer>()->getMouseRayPickID());
if (pickResult) {
overlayResult.intersects = pickResult->type == IntersectionType::LOCAL_ENTITY;
if (overlayResult.intersects) {
overlayResult.intersection = pickResult->intersection;
overlayResult.distance = pickResult->distance;
overlayResult.surfaceNormal = pickResult->surfaceNormal;
overlayResult.overlayID = pickResult->objectID;
overlayResult.extraInfo = pickResult->extraInfo;
} }
} }
return overlayResult;
} }
PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, void Overlays::mousePressOffPointerEvent() {
const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, emit mousePressOffOverlay();
PointerEvent::EventType eventType) { }
glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection);
return PointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, void Overlays::mouseDoublePressOnPointerEvent(const QUuid& id, const PointerEvent& event) {
ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers()); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) {
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
if (entity && entity->isLocalEntity()) {
emit mouseDoublePressOnOverlay(id, event);
}
}
}
void Overlays::mouseDoublePressOffPointerEvent() {
emit mouseDoublePressOffOverlay();
}
void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) {
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) {
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
if (entity && entity->isLocalEntity()) {
emit mouseReleaseOnOverlay(id, event);
}
}
}
void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) {
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) {
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
if (entity && entity->isLocalEntity()) {
emit mouseMoveOnOverlay(id, event);
}
}
} }
void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) { void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) {
auto keyboard = DependencyManager::get<Keyboard>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) { if (!keyboard->getKeyIDs().contains(id)) {
emit hoverEnterOverlay(id, event); auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
if (entity && entity->isLocalEntity()) {
emit hoverEnterOverlay(id, event);
}
} }
} }
@ -1264,7 +1275,10 @@ void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event)
auto keyboard = DependencyManager::get<Keyboard>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) { if (!keyboard->getKeyIDs().contains(id)) {
emit hoverOverOverlay(id, event); auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
if (entity && entity->isLocalEntity()) {
emit hoverOverOverlay(id, event);
}
} }
} }
@ -1272,113 +1286,10 @@ void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event
auto keyboard = DependencyManager::get<Keyboard>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) { if (!keyboard->getKeyIDs().contains(id)) {
emit hoverLeaveOverlay(id, event); auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
} if (entity && entity->isLocalEntity()) {
} emit hoverLeaveOverlay(id, event);
std::pair<float, QUuid> Overlays::mousePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mousePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID;
PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
mousePressPointerEvent(_currentClickingOnOverlayID, pointerEvent);
return { rayPickResult.distance, rayPickResult.overlayID };
}
emit mousePressOffOverlay();
return { FLT_MAX, UNKNOWN_ENTITY_ID };
}
void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) {
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) {
emit mousePressOnOverlay(id, event);
}
}
bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID;
auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
return true;
}
emit mouseDoublePressOffOverlay();
return false;
}
bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
}
_currentClickingOnOverlayID = UNKNOWN_ENTITY_ID;
return false;
}
void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) {
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) {
emit mouseReleaseOnOverlay(id, event);
}
}
bool Overlays::mouseMoveEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
// If previously hovering over a different overlay then leave hover on that overlay.
if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) {
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
} }
// If hovering over a new overlay then enter hover on that overlay.
if (rayPickResult.overlayID != _currentHoverOverOverlayID) {
hoverEnterPointerEvent(rayPickResult.overlayID, pointerEvent);
}
// Hover over current overlay.
hoverOverPointerEvent(rayPickResult.overlayID, pointerEvent);
_currentHoverOverOverlayID = rayPickResult.overlayID;
} else {
// If previously hovering an overlay then leave hover.
if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID) {
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
_currentHoverOverOverlayID = UNKNOWN_ENTITY_ID;
}
}
return false;
}
void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) {
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeyIDs().contains(id)) {
emit mouseMoveOnOverlay(id, event);
} }
} }

View file

@ -112,11 +112,6 @@ public:
const QVector<EntityItemID>& discard, const QVector<EntityItemID>& discard,
bool visibleOnly = false, bool collidableOnly = false); bool visibleOnly = false, bool collidableOnly = false);
std::pair<float, QUuid> mousePressEvent(QMouseEvent* event);
bool mouseDoublePressEvent(QMouseEvent* event);
bool mouseReleaseEvent(QMouseEvent* event);
bool mouseMoveEvent(QMouseEvent* event);
void cleanupAllOverlays(); void cleanupAllOverlays();
mutable QScriptEngine _scriptEngine; mutable QScriptEngine _scriptEngine;
@ -719,9 +714,6 @@ private:
PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult,
QMouseEvent* event, PointerEvent::EventType eventType); QMouseEvent* event, PointerEvent::EventType eventType);
QUuid _currentClickingOnOverlayID;
QUuid _currentHoverOverOverlayID;
static QString entityToOverlayType(const QString& type); static QString entityToOverlayType(const QString& type);
static QString overlayToEntityType(const QString& type); static QString overlayToEntityType(const QString& type);
static std::unordered_map<QString, QString> _entityToOverlayTypes; static std::unordered_map<QString, QString> _entityToOverlayTypes;
@ -732,12 +724,17 @@ private:
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid()); EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid());
private slots: private slots:
void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); void mousePressOnPointerEvent(const QUuid& id, const PointerEvent& event);
void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event); void mousePressOffPointerEvent();
void mouseDoublePressOnPointerEvent(const QUuid& id, const PointerEvent& event);
void mouseDoublePressOffPointerEvent();
void mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event); void mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event);
void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event);
void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event); void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event);
void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event); void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event);
void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event); void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event);
}; };
#define ADD_TYPE_MAP(entity, overlay) \ #define ADD_TYPE_MAP(entity, overlay) \

View file

@ -73,14 +73,14 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID; _currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID; _currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
auto pointerManager = DependencyManager::get<PointerManager>(); auto pointerManager = DependencyManager::get<PointerManager>();
connect(pointerManager.data(), &PointerManager::hoverBeginEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity); connect(pointerManager.data(), &PointerManager::hoverBeginEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
connect(pointerManager.data(), &PointerManager::hoverContinueEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity); connect(pointerManager.data(), &PointerManager::hoverContinueEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
connect(pointerManager.data(), &PointerManager::hoverEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity); connect(pointerManager.data(), &PointerManager::hoverEndEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity); connect(pointerManager.data(), &PointerManager::triggerBeginEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
connect(pointerManager.data(), &PointerManager::triggerContinueEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity); connect(pointerManager.data(), &PointerManager::triggerContinueEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity); connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
// Forward mouse events to web entities // Forward mouse events to web entities
auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) { auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) {
@ -93,10 +93,10 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(const PointerEvent&, event)); QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(const PointerEvent&, event));
} }
}; };
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent); connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent);
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent); connect(entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent);
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent); connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent);
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity; std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID); auto entity = getEntity(entityID);
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) { if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
@ -106,8 +106,8 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
QMetaObject::invokeMethod(thisEntity.get(), "hoverEnterEntity", Q_ARG(const PointerEvent&, event)); QMetaObject::invokeMethod(thisEntity.get(), "hoverEnterEntity", Q_ARG(const PointerEvent&, event));
} }
}); });
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent); connect(entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent);
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity; std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID); auto entity = getEntity(entityID);
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) { if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
@ -792,11 +792,11 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) {
} }
} }
std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { QUuid EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
// If we don't have a tree, or we're in the process of shutting down, then don't // If we don't have a tree, or we're in the process of shutting down, then don't
// process these events. // process these events.
if (!_tree || _shuttingDown) { if (!_tree || _shuttingDown) {
return { FLT_MAX, UNKNOWN_ENTITY_ID }; return UNKNOWN_ENTITY_ID;
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
@ -805,11 +805,13 @@ std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event)
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID); RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
EntityItemPointer entity; EntityItemPointer entity;
if (rayPickResult.intersects && (entity = getTree()->findEntityByID(rayPickResult.entityID))) { if (rayPickResult.intersects && (entity = getTree()->findEntityByID(rayPickResult.entityID))) {
auto properties = entity->getProperties(); if (!EntityTree::areEntityClicksCaptured()) {
QString urlString = properties.getHref(); auto properties = entity->getProperties();
QUrl url = QUrl(urlString, QUrl::StrictMode); QString urlString = properties.getHref();
if (url.isValid() && !url.isEmpty()){ QUrl url = QUrl(urlString, QUrl::StrictMode);
DependencyManager::get<AddressManager>()->handleLookupString(urlString); if (url.isValid() && !url.isEmpty()) {
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
}
} }
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult); glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
@ -827,10 +829,10 @@ std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event)
_lastPointerEvent = pointerEvent; _lastPointerEvent = pointerEvent;
_lastPointerEventValid = true; _lastPointerEventValid = true;
return { rayPickResult.distance, rayPickResult.entityID }; return rayPickResult.entityID;
} }
emit entityScriptingInterface->mousePressOffEntity(); emit entityScriptingInterface->mousePressOffEntity();
return { FLT_MAX, UNKNOWN_ENTITY_ID }; return UNKNOWN_ENTITY_ID;
} }
void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) { void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {

View file

@ -94,7 +94,7 @@ public:
void reloadEntityScripts(); void reloadEntityScripts();
// event handles which may generate entity related events // event handles which may generate entity related events
std::pair<float, QUuid> mousePressEvent(QMouseEvent* event); QUuid mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
void mouseDoublePressEvent(QMouseEvent* event); void mouseDoublePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event);

View file

@ -2972,6 +2972,7 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr; std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr;
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr; std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
std::function<bool()> EntityTree::_areEntityClicksCapturedOperator = nullptr;
QObject* EntityTree::getEntityObject(const QUuid& id) { QObject* EntityTree::getEntityObject(const QUuid& id) {
if (_getEntityObjectOperator) { if (_getEntityObjectOperator) {
@ -2987,6 +2988,13 @@ QSizeF EntityTree::textSize(const QUuid& id, const QString& text) {
return QSizeF(0.0f, 0.0f); return QSizeF(0.0f, 0.0f);
} }
bool EntityTree::areEntityClicksCaptured() {
if (_areEntityClicksCapturedOperator) {
return _areEntityClicksCapturedOperator();
}
return false;
}
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) { MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
// if the queryBox has changed, tell the entity-server // if the queryBox has changed, tell the entity-server

View file

@ -268,6 +268,9 @@ public:
static void setTextSizeOperator(std::function<QSizeF(const QUuid&, const QString&)> textSizeOperator) { _textSizeOperator = textSizeOperator; } static void setTextSizeOperator(std::function<QSizeF(const QUuid&, const QString&)> textSizeOperator) { _textSizeOperator = textSizeOperator; }
static QSizeF textSize(const QUuid& id, const QString& text); static QSizeF textSize(const QUuid& id, const QString& text);
static void setEntityClicksCapturedOperator(std::function<bool()> areEntityClicksCapturedOperator) { _areEntityClicksCapturedOperator = areEntityClicksCapturedOperator; }
static bool areEntityClicksCaptured();
std::map<QString, QString> getNamedPaths() const { return _namedPaths; } std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
@ -378,6 +381,7 @@ private:
static std::function<QObject*(const QUuid&)> _getEntityObjectOperator; static std::function<QObject*(const QUuid&)> _getEntityObjectOperator;
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator; static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;
static std::function<bool()> _areEntityClicksCapturedOperator;
std::vector<int32_t> _staleProxies; std::vector<int32_t> _staleProxies;

View file

@ -976,7 +976,9 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString&
using PointerHandler = std::function<void(const EntityItemID&, const PointerEvent&)>; using PointerHandler = std::function<void(const EntityItemID&, const PointerEvent&)>;
auto makePointerHandler = [this](QString eventName) -> PointerHandler { auto makePointerHandler = [this](QString eventName) -> PointerHandler {
return [this, eventName](const EntityItemID& entityItemID, const PointerEvent& event) { return [this, eventName](const EntityItemID& entityItemID, const PointerEvent& event) {
forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(this), event.toScriptValue(this) }); if (!EntityTree::areEntityClicksCaptured()) {
forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(this), event.toScriptValue(this) });
}
}; };
}; };