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
17#include <QtCore/QFileInfo>17#include <QtCore/QFileInfo>
18#include <QtCore/QTimer>18#include <QtCore/QTimer>
19#include <QtCore/QThread>19#include <QtCore/QThread>
20#include <QtCore/QRegularExpression>
21
22#include <QtWidgets/QMainWindow>
23#include <QtWidgets/QApplication>
24
20#include <QtNetwork/QNetworkRequest>25#include <QtNetwork/QNetworkRequest>
21#include <QtNetwork/QNetworkReply>26#include <QtNetwork/QNetworkReply>
22#include <QtScript/QScriptEngine>27
23#include <QtScript/QScriptValue>28#include <QtScript/QScriptValue>
24#include <QtScript/QScriptValueIterator>29#include <QtScript/QScriptValueIterator>
25#include <QtCore/QStringList>30
31#include <QtScriptTools/QScriptEngineDebugger>
26 32
27#include <AudioConstants.h>33#include <AudioConstants.h>
28#include <AudioEffectOptions.h>34#include <AudioEffectOptions.h>
@@ -34,6 +40,7 @@ · 5 unmodified lines
34#include <NodeList.h>40#include <NodeList.h>
35#include <udt/PacketHeaders.h>41#include <udt/PacketHeaders.h>
36#include <UUID.h>42#include <UUID.h>
43#include <ui/Menu.h>
37 44
38#include <controllers/ScriptingInterface.h>45#include <controllers/ScriptingInterface.h>
39#include <AnimationObject.h>46#include <AnimationObject.h>
@@ -169,6 +176,93 @@ void ScriptEngine::disconnectNonEssentialSignals() { · 129 unmodified lines
169 }176 }
170}177}
171 178
179void 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
172void ScriptEngine::runInThread() {266void ScriptEngine::runInThread() {
173 Q_ASSERT_X(!_isThreaded, "ScriptEngine::runInThread()", "runInThread should not be called more than once");267 Q_ASSERT_X(!_isThreaded, "ScriptEngine::runInThread()", "runInThread should not be called more than once");
174 268
@@ -260,6 +354,10 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { · 85 unmodified lines
260// FIXME - switch this to the new model of ScriptCache callbacks354// FIXME - switch this to the new model of ScriptCache callbacks
261void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {355void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
262 _scriptContents = scriptContents;356 _scriptContents = scriptContents;
357 static const QString DEBUG_FLAG("#debug");
358 if (QRegularExpression(DEBUG_FLAG).match(scriptContents).hasMatch()) {
359 _debuggable = true;
360 }
263 if (_wantSignals) {361 if (_wantSignals) {
264 emit scriptLoaded(url.toString());362 emit scriptLoaded(url.toString());
265 }363 }
@@ -723,7 +821,7 @@ void ScriptEngine::run() { · 457 unmodified lines
723 auto nodeList = DependencyManager::get<NodeList>();821 auto nodeList = DependencyManager::get<NodeList>();
724 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();822 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
725 823
726 qint64 lastUpdate = usecTimestampNow();824 _lastUpdate = usecTimestampNow();
727 825
728 // TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptEngine826 // TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptEngine
729 while (!_isFinished) {827 while (!_isFinished) {
@@ -771,15 +869,15 @@ void ScriptEngine::run() { · 41 unmodified lines
771 qint64 now = usecTimestampNow();869 qint64 now = usecTimestampNow();
772 870
773 // we check for 'now' in the past in case people set their clock back871 // we check for 'now' in the past in case people set their clock back
774 if (lastUpdate < now) {872 if (_lastUpdate < now) {
775 float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND;873 float deltaTime = (float) (now - _lastUpdate) / (float) USECS_PER_SECOND;
776 if (!_isFinished) {874 if (!_isFinished) {
777 if (_wantSignals) {875 if (_wantSignals) {
778 emit update(deltaTime);876 emit update(deltaTime);
779 }877 }
780 }878 }
781 }879 }
782 lastUpdate = now;880 _lastUpdate = now;
783 881
784 // Debug and clear exceptions882 // Debug and clear exceptions
785 hadUncaughtExceptions(*this, _fileNameString);883 hadUncaughtExceptions(*this, _fileNameString);