From 8ff457a1b62e8a63e651516d5f30cda105cb0087 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 3 Apr 2017 16:03:55 -0700 Subject: [PATCH] Fix broken eventBridge on tablet after Reload All Scripts. The main issue here was the "webEventReceived" connection between the OffscreenQMLSurface and the TabletProxy object. For whatever reason, if this is not a direct Signal to Slot connection, the webEventReceived event does not propagate. --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 2 + libraries/script-engine/src/ScriptEngine.cpp | 2 + .../src/TabletScriptingInterface.cpp | 12 +- .../src/TabletScriptingInterface.h | 5 +- .../developer/tests/tabletEventBridgeTest.js | 114 +++++++++++------- scripts/system/tablet-ui/tabletUI.js | 7 ++ 6 files changed, 92 insertions(+), 50 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index de0caf56a9..33d62a6a40 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -576,7 +576,9 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionsetObjectOwnership(this, QQmlEngine::CppOwnership); newObject->setProperty("eventBridge", QVariant::fromValue(this)); + newContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); f(newContext, newObject); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a5c94c1bb4..caa42bea5e 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -974,6 +974,8 @@ void ScriptEngine::run() { return; // bail early - avoid setting state in init(), as evaluate() will bail too } + scriptInfoMessage("Script Engine starting:" + getFilename()); + if (!_isInitialized) { init(); } diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index c287fbcfe7..02c2253fc6 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -201,7 +201,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { QObject::connect(quickItem, SIGNAL(windowClosed()), this, SLOT(desktopWindowClosed())); - QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SIGNAL(webEventReceived(QVariant))); + QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection); // forward qml surface events to interface js connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); @@ -271,12 +271,17 @@ bool TabletProxy::isMessageDialogOpen() { return false; } +void TabletProxy::emitWebEvent(QVariant msg) { + emit webEventReceived(msg); +} + void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { std::lock_guard guard(_mutex); _qmlOffscreenSurface = qmlOffscreenSurface; _qmlTabletRoot = qmlTabletRoot; if (_qmlTabletRoot && _qmlOffscreenSurface) { - QObject::connect(_qmlOffscreenSurface, SIGNAL(webEventReceived(QVariant)), this, SIGNAL(webEventReceived(QVariant))); + + QObject::connect(_qmlOffscreenSurface, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection); // forward qml surface events to interface js connect(dynamic_cast(_qmlOffscreenSurface), &OffscreenQmlSurface::fromQml, [this](QVariant message) { @@ -398,7 +403,7 @@ void TabletProxy::popFromStack() { auto stack = _desktopWindow->asQuickItem()->findChild("stack"); if (stack) { QMetaObject::invokeMethod(stack, "popSource"); - } else { + } else { qCDebug(scriptengine) << "tablet cannot pop QML because _desktopWindow doesn't have child stack"; } } else { @@ -705,4 +710,3 @@ void TabletButtonProxy::editProperties(QVariantMap properties) { } #include "TabletScriptingInterface.moc" - diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index 2e7b91fa4c..fa6b8fb56f 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -63,7 +63,7 @@ signals: * @returns {Signal} */ void tabletNotification(); - + private: void processMenuEvents(QObject* object, const QKeyEvent* event); void processTabletEvents(QObject* object, const QKeyEvent* event); @@ -209,6 +209,7 @@ signals: protected slots: void addButtonsToHomeScreen(); void desktopWindowClosed(); + void emitWebEvent(QVariant msg); protected: void removeButtonsFromHomeScreen(); void loadHomeScreen(bool forceOntoHomeScreen); @@ -216,7 +217,7 @@ protected: void removeButtonsFromToolbar(); bool _initialScreen { false }; - QVariant _initialPath { "" }; + QVariant _initialPath { "" }; QString _name; std::mutex _mutex; std::vector> _tabletButtonProxies; diff --git a/scripts/developer/tests/tabletEventBridgeTest.js b/scripts/developer/tests/tabletEventBridgeTest.js index 1fa935bef2..83031741fc 100644 --- a/scripts/developer/tests/tabletEventBridgeTest.js +++ b/scripts/developer/tests/tabletEventBridgeTest.js @@ -16,66 +16,92 @@ var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var tabletButton = tablet.addButton({ - text: "SOUNDS" + text: "SOUNDS", + icon: "http://s3.amazonaws.com/hifi-public/tony/icons/trombone-i.png", + activeIcon: "http://s3.amazonaws.com/hifi-public/tony/icons/trombone-a.png" }); var WEB_BRIDGE_TEST_HTML = "https://s3.amazonaws.com/hifi-public/tony/webBridgeTest.html?2"; - var TROMBONE_URL = "https://s3.amazonaws.com/hifi-public/tony/audio/sad-trombone.wav"; -var tromboneSound = SoundCache.getSound(TROMBONE_URL); -var tromboneInjector; - var SCREAM_URL = "https://s3.amazonaws.com/hifi-public/tony/audio/wilhelm-scream.wav"; -var screamSound = SoundCache.getSound(SCREAM_URL); -var screamInjector; tabletButton.clicked.connect(function () { - tablet.gotoWebScreen(WEB_BRIDGE_TEST_HTML); + if (shown) { + tablet.gotoHomeScreen(); + } else { + tablet.gotoWebScreen(WEB_BRIDGE_TEST_HTML); + } }); -// hook up to the event bridge -tablet.webEventReceived.connect(function (msg) { +var shown = false; + +function onScreenChanged(type, url) { + if (type === "Web" && url === WEB_BRIDGE_TEST_HTML) { + tabletButton.editProperties({isActive: true}); + + if (!shown) { + // hook up to the event bridge + tablet.webEventReceived.connect(onWebEventReceived); + } + shown = true; + } else { + tabletButton.editProperties({isActive: false}); + + if (shown) { + // disconnect from the event bridge + tablet.webEventReceived.disconnect(onWebEventReceived); + } + shown = false; + } +} + +tablet.screenChanged.connect(onScreenChanged); + +// ctor +function SoundBuddy(url) { + this.sound = SoundCache.getSound(url); + this.injector = null; +} + +SoundBuddy.prototype.play = function (options, doneCallback) { + if (this.sound.downloaded) { + if (this.injector) { + this.injector.setOptions(options); + this.injector.restart(); + } else { + this.injector = Audio.playSound(this.sound, options); + this.injector.finished.connect(function () { + if (doneCallback) { + doneCallback(); + } + }); + } + } +}; + +var tromboneSound = new SoundBuddy(TROMBONE_URL); +var screamSound = new SoundBuddy(SCREAM_URL); +var soundOptions = { position: MyAvatar.position, volume: 1.0, loop: false, localOnly: true }; + +function onWebEventReceived(msg) { Script.print("HIFI: recv web event = " + JSON.stringify(msg)); if (msg === "button-1-play") { - - // play sad trombone - if (tromboneSound.downloaded) { - if (tromboneInjector) { - tromboneInjector.restart(); - } else { - tromboneInjector = Audio.playSound(tromboneSound, { position: MyAvatar.position, - volume: 1.0, - loop: false }); - } - } - - // wait until sound is finished then send a done event - Script.setTimeout(function () { + soundOptions.position = MyAvatar.position; + tromboneSound.play(soundOptions, function () { tablet.emitScriptEvent("button-1-done"); - }, 3500); - } - - if (msg === "button-2-play") { - - // play scream - if (screamSound.downloaded) { - if (screamInjector) { - screamInjector.restart(); - } else { - screamInjector = Audio.playSound(screamSound, { position: MyAvatar.position, - volume: 1.0, - loop: false }); - } - } - - // wait until sound is finished then send a done event - Script.setTimeout(function () { + }); + } else if (msg === "button-2-play") { + soundOptions.position = MyAvatar.position; + screamSound.play(soundOptions, function () { tablet.emitScriptEvent("button-2-done"); - }, 1000); + }); } -}); +} Script.scriptEnding.connect(function () { tablet.removeButton(tabletButton); + if (shown) { + tablet.webEventReceived.disconnect(onWebEventReceived); + } }); diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index a010cb0a9c..a3ccd34976 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -271,6 +271,13 @@ } Script.scriptEnding.connect(function () { + + // if we reload scripts in tablet mode make sure we close the currently open window, by calling gotoHomeScreen + var tabletProxy = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + if (tabletProxy && tabletProxy.toolbarMode) { + tabletProxy.gotoHomeScreen(); + } + var tabletID = HMD.tabletID; Entities.deleteEntity(tabletID); Overlays.deleteOverlay(tabletID)