austin's comments, send events directly to selected web entity

This commit is contained in:
SamGondelman 2017-10-19 14:50:00 -07:00
parent c6b636901a
commit 9bbb2eb692
5 changed files with 83 additions and 55 deletions

View file

@ -376,7 +376,7 @@ public slots:
void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions);
QUuid getKeyboardFocusEntity() const; // thread-safe
Q_INVOKABLE void setKeyboardFocusEntity(const EntityItemID& entityItemID);
void setKeyboardFocusEntity(const EntityItemID& entityItemID);
OverlayID getKeyboardFocusOverlay();
void setKeyboardFocusOverlay(const OverlayID& overlayID);

View file

@ -891,7 +891,10 @@ bool Overlays::mousePressEvent(QMouseEvent* event) {
void Overlays::mousePressEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
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);
@ -925,7 +928,10 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
void Overlays::hoverLeaveEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
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));
@ -951,7 +957,10 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
void Overlays::mouseReleaseEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
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));
@ -999,7 +1008,10 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
void Overlays::mouseMoveEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
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));

View file

@ -35,6 +35,8 @@
#include "EntitiesRendererLogging.h"
#include "RenderableEntityItem.h"
#include "RenderableWebEntityItem.h"
size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); }
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction;
@ -55,6 +57,32 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
EntityRenderer::initEntityRenderers();
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
// Forward mouse events to web entities
auto handlePointerEvent = [&](const EntityItemID& entityID, const PointerEvent& event) {
std::shared_ptr<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() {
@ -78,7 +106,6 @@ render::ItemID EntityTreeRenderer::renderableIdForEntityId(const EntityItemID& i
int EntityTreeRenderer::_entitiesScriptEngineCount = 0;
void EntityTreeRenderer::resetEntitiesScriptEngine() {
auto oldEngine = _entitiesScriptEngine;
_entitiesScriptEngine = scriptEngineFactory(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT,
QString("about:Entities %1").arg(++_entitiesScriptEngineCount));
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
@ -543,7 +570,7 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) {
if (rayPickResult.intersects && rayPickResult.entity) {
auto properties = rayPickResult.entity->getProperties();
QString urlString = properties.getHref();
QUrl url = QUrl(urlString, QUrl::StrictMode);
@ -582,7 +609,7 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) {
if (rayPickResult.intersects && rayPickResult.entity) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection,
@ -612,7 +639,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) {
if (rayPickResult.intersects && rayPickResult.entity) {
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
@ -656,7 +683,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
if (rayPickResult.intersects) {
if (rayPickResult.intersects && rayPickResult.entity) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection,

View file

@ -85,6 +85,10 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
return true;
}
if (_lastLocked != entity->getLocked()) {
return true;
}
return false;
}
@ -135,6 +139,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
}
_lastDPI = entity->getDPI();
_lastLocked = entity->getLocked();
glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y));
@ -233,38 +238,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
emit entities->webEventReceived(entityItemID, message);
});
auto forwardPointerEvent = [=](const EntityItemID& entityItemID, const PointerEvent& event) {
if (entityItemID == entity->getID()) {
handlePointerEvent(entity, event);
}
};
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, forwardPointerEvent);
QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, forwardPointerEvent);
QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, forwardPointerEvent);
QObject::connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this,
[=](const EntityItemID& entityItemID, const PointerEvent& event) {
if (this->_pressed && entity->getID() == entityItemID) {
// If the user mouses off the entity while the button is down, simulate a touch end.
QTouchEvent::TouchPoint point;
point.setId(event.getID());
point.setState(Qt::TouchPointReleased);
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI);
QPointF windowPoint(windowPos.x, windowPos.y);
point.setScenePos(windowPoint);
point.setPos(windowPoint);
QList<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;
}
@ -294,13 +267,6 @@ void WebEntityRenderer::destroyWebSurface() {
}
webSurface->pause();
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
if (entityScriptingInterface) {
QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, nullptr);
QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, nullptr);
QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, nullptr);
QObject::disconnect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, nullptr);
}
webSurface.reset();
}
}
@ -346,13 +312,34 @@ void WebEntityRenderer::loadSourceURL() {
}
}
void WebEntityRenderer::handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event) {
void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) {
if (!_lastLocked && _webSurface && _pressed) {
// If the user mouses off the entity while the button is down, simulate a touch end.
QTouchEvent::TouchPoint point;
point.setId(event.getID());
point.setState(Qt::TouchPointReleased);
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI);
QPointF windowPoint(windowPos.x, windowPos.y);
point.setScenePos(windowPoint);
point.setPos(windowPoint);
QList<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
if (entity->getLocked() || !_webSurface) {
if (_lastLocked || !_webSurface) {
return;
}
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * entity->getDPI());
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI);
QPointF windowPoint(windowPos.x, windowPos.y);
if (event.getType() == PointerEvent::Move) {
// Forward a mouse move event to webSurface

View file

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