History

Merge pull request #7845 from jherico/script_debug

Enable script debugging

Brad Hefta-Gaub committed 10 years ago

Commit af6be7f2 parents 3507434 b117a4b6 files · +143 −17Browse files

Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 6 files). Show all

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+104−6
@@ -17,12 +17,18 @@ · 16 unmodified lines
1717 #include <QtCore/QFileInfo>
1818 #include <QtCore/QTimer>
1919 #include <QtCore/QThread>
20+#include <QtCore/QRegularExpression>
21+
22+#include <QtWidgets/QMainWindow>
23+#include <QtWidgets/QApplication>
24+
2025 #include <QtNetwork/QNetworkRequest>
2126 #include <QtNetwork/QNetworkReply>
22−#include <QtScript/QScriptEngine>
27+
2328 #include <QtScript/QScriptValue>
2429 #include <QtScript/QScriptValueIterator>
25−#include <QtCore/QStringList>
30+
31+#include <QtScriptTools/QScriptEngineDebugger>
2632
2733 #include <AudioConstants.h>
2834 #include <AudioEffectOptions.h>
@@ -34,6 +40,7 @@ · 5 unmodified lines
3440 #include <NodeList.h>
3541 #include <udt/PacketHeaders.h>
3642 #include <UUID.h>
43+#include <ui/Menu.h>
3744
3845 #include <controllers/ScriptingInterface.h>
3946 #include <AnimationObject.h>
@@ -169,6 +176,93 @@ void ScriptEngine::disconnectNonEssentialSignals() { · 129 unmodified lines
169176 }
170177 }
171178
179+void ScriptEngine::runDebuggable() {
180+ static QMenuBar* menuBar { nullptr };
181+ static QMenu* scriptDebugMenu { nullptr };
182+ static size_t scriptMenuCount { 0 };
183+ if (!scriptDebugMenu) {
184+ for (auto window : qApp->topLevelWidgets()) {
185+ auto mainWindow = qobject_cast<QMainWindow*>(window);
186+ if (mainWindow) {
187+ menuBar = mainWindow->menuBar();
188+ break;
189+ }
190+ }
191+ if (menuBar) {
192+ scriptDebugMenu = menuBar->addMenu("Script Debug");
193+ }
194+ }
195+
196+ init();
197+ _isRunning = true;
198+ _debuggable = true;
199+ _debugger = new QScriptEngineDebugger(this);
200+ _debugger->attachTo(this);
201+
202+ QMenu* parentMenu = scriptDebugMenu;
203+ QMenu* scriptMenu { nullptr };
204+ if (parentMenu) {
205+ ++scriptMenuCount;
206+ scriptMenu = parentMenu->addMenu(_fileNameString);
207+ scriptMenu->addMenu(_debugger->createStandardMenu(qApp->activeWindow()));
208+ } else {
209+ qWarning() << "Unable to add script debug menu";
210+ }
211+
212+ QScriptValue result = evaluate(_scriptContents, _fileNameString);
213+
214+ _lastUpdate = usecTimestampNow();
215+ QTimer* timer = new QTimer(this);
216+ connect(this, &ScriptEngine::finished, [this, timer, parentMenu, scriptMenu] {
217+ if (scriptMenu) {
218+ parentMenu->removeAction(scriptMenu->menuAction());
219+ --scriptMenuCount;
220+ if (0 == scriptMenuCount) {
221+ menuBar->removeAction(scriptDebugMenu->menuAction());
222+ scriptDebugMenu = nullptr;
223+ }
224+ }
225+ disconnect(timer);
226+ });
227+
228+ connect(timer, &QTimer::timeout, [this, timer] {
229+ if (_isFinished) {
230+ if (!_isRunning) {
231+ return;
232+ }
233+ stopAllTimers(); // make sure all our timers are stopped if the script is ending
234+ if (_wantSignals) {
235+ emit scriptEnding();
236+ emit finished(_fileNameString, this);
237+ }
238+ _isRunning = false;
239+ if (_wantSignals) {
240+ emit runningStateChanged();
241+ emit doneRunning();
242+ }
243+ timer->deleteLater();
244+ return;
245+ }
246+
247+ qint64 now = usecTimestampNow();
248+ // we check for 'now' in the past in case people set their clock back
249+ if (_lastUpdate < now) {
250+ float deltaTime = (float)(now - _lastUpdate) / (float)USECS_PER_SECOND;
251+ if (!_isFinished) {
252+ if (_wantSignals) {
253+ emit update(deltaTime);
254+ }
255+ }
256+ }
257+ _lastUpdate = now;
258+ // Debug and clear exceptions
259+ hadUncaughtExceptions(*this, _fileNameString);
260+ });
261+
262+ timer->start(10);
263+}
264+
265+
172266 void ScriptEngine::runInThread() {
173267 Q_ASSERT_X(!_isThreaded, "ScriptEngine::runInThread()", "runInThread should not be called more than once");
174268
@@ -260,6 +354,10 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { · 85 unmodified lines
260354 // FIXME - switch this to the new model of ScriptCache callbacks
261355 void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
262356 _scriptContents = scriptContents;
357+ static const QString DEBUG_FLAG("#debug");
358+ if (QRegularExpression(DEBUG_FLAG).match(scriptContents).hasMatch()) {
359+ _debuggable = true;
360+ }
263361 if (_wantSignals) {
264362 emit scriptLoaded(url.toString());
265363 }
@@ -723,7 +821,7 @@ void ScriptEngine::run() { · 457 unmodified lines
723821 auto nodeList = DependencyManager::get<NodeList>();
724822 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
725823
726− qint64 lastUpdate = usecTimestampNow();
824+ _lastUpdate = usecTimestampNow();
727825
728826 // TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptEngine
729827 while (!_isFinished) {
@@ -771,15 +869,15 @@ void ScriptEngine::run() { · 41 unmodified lines
771869 qint64 now = usecTimestampNow();
772870
773871 // we check for 'now' in the past in case people set their clock back
774− if (lastUpdate < now) {
775− float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND;
872+ if (_lastUpdate < now) {
873+ float deltaTime = (float) (now - _lastUpdate) / (float) USECS_PER_SECOND;
776874 if (!_isFinished) {
777875 if (_wantSignals) {
778876 emit update(deltaTime);
779877 }
780878 }
781879 }
782− lastUpdate = now;
880+ _lastUpdate = now;
783881
784882 // Debug and clear exceptions
785883 hadUncaughtExceptions(*this, _fileNameString);