eventBridge for web entities.

This commit is contained in:
Anthony J. Thibault 2016-09-01 16:32:06 -07:00
parent 823420ae0a
commit 21bf931559
6 changed files with 73 additions and 6 deletions

View file

@ -1,8 +1,16 @@
import QtQuick 2.5 import QtQuick 2.5
import QtWebEngine 1.1 import QtWebEngine 1.1
import QtWebChannel 1.0
Item { Item {
property alias url: root.url property alias url: root.url
property alias eventBridge: eventBridgeWrapper.eventBridge
QtObject {
id: eventBridgeWrapper
WebChannel.id: "eventBridgeWrapper"
property var eventBridge;
}
WebEngineView { WebEngineView {
id: root id: root
@ -16,6 +24,8 @@ Item {
profile.httpUserAgent: "Mozilla/5.0 Chrome (HighFidelityInterface)" profile.httpUserAgent: "Mozilla/5.0 Chrome (HighFidelityInterface)"
webChannel.registeredObjects: [eventBridgeWrapper]
Component.onCompleted: { Component.onCompleted: {
console.log("Connecting JS messaging to Hifi Logging") console.log("Connecting JS messaging to Hifi Logging")
// Ensure the JS from the web-engine makes it to our logging // Ensure the JS from the web-engine makes it to our logging
@ -76,6 +86,7 @@ Item {
//profile: desktop.browserProfile //profile: desktop.browserProfile
} }
// virtual keyboard
Keyboard { Keyboard {
id: keyboard1 id: keyboard1
x: 197 x: 197

View file

@ -37,12 +37,28 @@ static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND;
static int MAX_WINDOW_SIZE = 4096; static int MAX_WINDOW_SIZE = 4096;
static float OPAQUE_ALPHA_THRESHOLD = 0.99f; static float OPAQUE_ALPHA_THRESHOLD = 0.99f;
void WebEntityQMLAPIHelper::synthesizeKeyPress(QString key) { void WebEntityAPIHelper::synthesizeKeyPress(QString key) {
if (_ptr) { if (_ptr) {
_ptr->synthesizeKeyPress(key); _ptr->synthesizeKeyPress(key);
} }
} }
void WebEntityAPIHelper::emitScriptEvent(const QVariant& message) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message));
} else {
emit scriptEventReceived(message);
}
}
void WebEntityAPIHelper::emitWebEvent(const QVariant& message) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, message));
} else {
emit webEventReceived(message);
}
}
EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer entity{ new RenderableWebEntityItem(entityID) }; EntityItemPointer entity{ new RenderableWebEntityItem(entityID) };
entity->setProperties(properties); entity->setProperties(properties);
@ -58,11 +74,18 @@ RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemI
_touchDevice.setName("RenderableWebEntityItemTouchDevice"); _touchDevice.setName("RenderableWebEntityItemTouchDevice");
_touchDevice.setMaximumTouchPoints(4); _touchDevice.setMaximumTouchPoints(4);
_webEntityQMLAPIHelper.setPtr(this); _webEntityAPIHelper.setPtr(this);
_webEntityAPIHelper.moveToThread(qApp->thread());
// forward web events to EntityScriptingInterface
auto entities = DependencyManager::get<EntityScriptingInterface>();
QObject::connect(&_webEntityAPIHelper, &WebEntityAPIHelper::webEventReceived, [=](const QVariant& message) {
emit entities->webEventReceived(entityItemID, message);
});
} }
RenderableWebEntityItem::~RenderableWebEntityItem() { RenderableWebEntityItem::~RenderableWebEntityItem() {
_webEntityQMLAPIHelper.setPtr(nullptr); _webEntityAPIHelper.setPtr(nullptr);
destroyWebSurface(); destroyWebSurface();
qDebug() << "Destroyed web entity " << getID(); qDebug() << "Destroyed web entity " << getID();
} }
@ -83,9 +106,10 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) {
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/")); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/"));
_webSurface->load("WebView.qml"); _webSurface->load("WebView.qml");
_webSurface->resume(); _webSurface->resume();
_webSurface->getRootItem()->setProperty("eventBridge", QVariant::fromValue(&_webEntityAPIHelper));
_webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootItem()->setProperty("url", _sourceUrl);
_webSurface->getRootContext()->setContextProperty("desktop", QVariant()); _webSurface->getRootContext()->setContextProperty("desktop", QVariant());
_webSurface->getRootContext()->setContextProperty("webEntity", &_webEntityQMLAPIHelper); _webSurface->getRootContext()->setContextProperty("webEntity", &_webEntityAPIHelper);
_connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) {
_texture = textureId; _texture = textureId;
}); });
@ -329,3 +353,7 @@ void RenderableWebEntityItem::synthesizeKeyPress(QString key) {
QCoreApplication::postEvent(getEventHandler(), pressEvent); QCoreApplication::postEvent(getEventHandler(), pressEvent);
QCoreApplication::postEvent(getEventHandler(), releaseEvent); QCoreApplication::postEvent(getEventHandler(), releaseEvent);
} }
void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) {
_webEntityAPIHelper.emitScriptEvent(message);
}

View file

@ -24,7 +24,7 @@ class QObject;
class EntityTreeRenderer; class EntityTreeRenderer;
class RenderableWebEntityItem; class RenderableWebEntityItem;
class WebEntityQMLAPIHelper : public QObject { class WebEntityAPIHelper : public QObject {
Q_OBJECT Q_OBJECT
public: public:
void setPtr(RenderableWebEntityItem* ptr) { void setPtr(RenderableWebEntityItem* ptr) {
@ -32,6 +32,14 @@ public:
} }
Q_INVOKABLE void synthesizeKeyPress(QString key); Q_INVOKABLE void synthesizeKeyPress(QString key);
// event bridge
public slots:
void emitScriptEvent(const QVariant& scriptMessage);
void emitWebEvent(const QVariant& webMessage);
signals:
void scriptEventReceived(const QVariant& message);
void webEventReceived(const QVariant& message);
protected: protected:
RenderableWebEntityItem* _ptr{ nullptr }; RenderableWebEntityItem* _ptr{ nullptr };
}; };
@ -55,6 +63,8 @@ public:
void update(const quint64& now) override; void update(const quint64& now) override;
bool needsToCallUpdate() const override { return _webSurface != nullptr; } bool needsToCallUpdate() const override { return _webSurface != nullptr; }
void emitScriptEvent(const QVariant& message);
SIMPLE_RENDERABLE(); SIMPLE_RENDERABLE();
virtual bool isTransparent() override; virtual bool isTransparent() override;
@ -75,7 +85,7 @@ private:
QTouchEvent _lastTouchEvent { QEvent::TouchUpdate }; QTouchEvent _lastTouchEvent { QEvent::TouchUpdate };
uint64_t _lastRenderTime{ 0 }; uint64_t _lastRenderTime{ 0 };
QTouchDevice _touchDevice; QTouchDevice _touchDevice;
WebEntityQMLAPIHelper _webEntityQMLAPIHelper; WebEntityAPIHelper _webEntityAPIHelper;
QMetaObject::Connection _mousePressConnection; QMetaObject::Connection _mousePressConnection;
QMetaObject::Connection _mouseReleaseConnection; QMetaObject::Connection _mouseReleaseConnection;

View file

@ -446,6 +446,8 @@ public:
virtual void setProxyWindow(QWindow* proxyWindow) {} virtual void setProxyWindow(QWindow* proxyWindow) {}
virtual QObject* getEventHandler() { return nullptr; } virtual QObject* getEventHandler() { return nullptr; }
virtual void emitScriptEvent(const QVariant& message) {}
protected: protected:
void setSimulated(bool simulated) { _simulated = simulated; } void setSimulated(bool simulated) { _simulated = simulated; }

View file

@ -1289,6 +1289,17 @@ bool EntityScriptingInterface::wantsHandControllerPointerEvents(QUuid id) {
return result; return result;
} }
void EntityScriptingInterface::emitScriptEvent(const EntityItemID& entityID, const QVariant& message) {
if (_entityTree) {
_entityTree->withReadLock([&] {
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID));
if (entity) {
entity->emitScriptEvent(message);
}
});
}
}
float EntityScriptingInterface::calculateCost(float mass, float oldVelocity, float newVelocity) { float EntityScriptingInterface::calculateCost(float mass, float oldVelocity, float newVelocity) {
return std::abs(mass * (newVelocity - oldVelocity)); return std::abs(mass * (newVelocity - oldVelocity));
} }
@ -1305,3 +1316,4 @@ float EntityScriptingInterface::getCostMultiplier() {
void EntityScriptingInterface::setCostMultiplier(float value) { void EntityScriptingInterface::setCostMultiplier(float value) {
costMultiplier = value; costMultiplier = value;
} }

View file

@ -205,6 +205,8 @@ public slots:
Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id); Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id);
Q_INVOKABLE void emitScriptEvent(const EntityItemID& entityID, const QVariant& message);
signals: signals:
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
@ -232,6 +234,8 @@ signals:
void clearingEntities(); void clearingEntities();
void debitEnergySource(float value); void debitEnergySource(float value);
void webEventReceived(const EntityItemID& entityItemID, const QVariant& message);
private: private:
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor); bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor);
bool setVoxels(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor); bool setVoxels(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor);