History

Support reload-on-change for local scripts

Brad Davis committed 11 years ago

Commit 99d1e171 parent 039d9a62 files · +57 −6Browse files

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

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+55−6
@@ -11,12 +11,13 @@ · 10 unmodified lines
1111
1212 #include <QtCore/QCoreApplication>
1313 #include <QtCore/QEventLoop>
14+#include <QtCore/QFileInfo>
1415 #include <QtCore/QTimer>
1516 #include <QtCore/QThread>
1617 #include <QtNetwork/QNetworkRequest>
1718 #include <QtNetwork/QNetworkReply>
18−#include <QScriptEngine>
19−#include <QScriptValue>
19+#include <QtScript/QScriptEngine>
20+#include <QtScript/QScriptValue>
2021
2122 #include <AudioConstants.h>
2223 #include <AudioEffectOptions.h>
@@ -942,6 +943,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 919 unmodified lines
942943 #endif
943944
944945 auto scriptCache = DependencyManager::get<ScriptCache>();
946+ bool isFileUrl = isURL && scriptOrURL.startsWith("file://");
945947
946948 // first check the syntax of the script contents
947949 QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents);
@@ -950,7 +952,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 2 unmodified lines
950952 qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":"
951953 << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
952954 qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
953− scriptCache->addScriptToBadScriptList(scriptOrURL);
955+ if (!isFileUrl) {
956+ scriptCache->addScriptToBadScriptList(scriptOrURL);
957+ }
954958 return; // done processing script
955959 }
956960
@@ -965,14 +969,21 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 8 unmodified lines
965969 qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
966970 qCDebug(scriptengine) << " NOT CONSTRUCTOR";
967971 qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
968− scriptCache->addScriptToBadScriptList(scriptOrURL);
972+ if (!isFileUrl) {
973+ scriptCache->addScriptToBadScriptList(scriptOrURL);
974+ }
969975 return; // done processing script
970976 }
971977
972− QScriptValue entityScriptConstructor = evaluate(contents);
978+ int64_t lastModified = 0;
979+ if (isFileUrl) {
980+ QString file = QUrl(scriptOrURL).toLocalFile();
981+ lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch();
982+ }
973983
984+ QScriptValue entityScriptConstructor = evaluate(contents);
974985 QScriptValue entityScriptObject = entityScriptConstructor.construct();
975− EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject };
986+ EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified };
976987 _entityScripts[entityID] = newDetails;
977988 if (isURL) {
978989 setParentURL("");
@@ -1022,6 +1033,41 @@ void ScriptEngine::unloadAllEntityScripts() { · 43 unmodified lines
10221033 _entityScripts.clear();
10231034 }
10241035
1036+void ScriptEngine::refreshFileScript(const EntityItemID& entityID) {
1037+ if (!_entityScripts.contains(entityID)) {
1038+ return;
1039+ }
1040+
1041+ static bool recurseGuard = false;
1042+ if (recurseGuard) {
1043+ return;
1044+ }
1045+ recurseGuard = true;
1046+
1047+ EntityScriptDetails details = _entityScripts[entityID];
1048+ // Check to see if a file based script needs to be reloaded (easier debugging)
1049+ if (details.lastModified > 0) {
1050+ QString filePath = QUrl(details.scriptText).toLocalFile();
1051+ auto lastModified = QFileInfo(filePath).lastModified().toMSecsSinceEpoch();
1052+ if (lastModified > details.lastModified) {
1053+ qDebug() << "Reloading modified script " << details.scriptText;
1054+
1055+ QFile file(filePath);
1056+ file.open(QIODevice::ReadOnly);
1057+ QString scriptContents = QTextStream(&file).readAll();
1058+ this->unloadEntityScript(entityID);
1059+ this->entityScriptContentAvailable(entityID, details.scriptText, scriptContents, true, true);
1060+ if (!_entityScripts.contains(entityID)) {
1061+ qWarning() << "Reload script " << details.scriptText << " failed";
1062+ } else {
1063+ details = _entityScripts[entityID];
1064+ }
1065+ }
1066+ }
1067+ recurseGuard = false;
1068+}
1069+
1070+
10251071 void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) {
10261072 if (QThread::currentThread() != thread()) {
10271073 #ifdef THREAD_DEBUGGING
@@ -1039,6 +1085,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 11 unmodified lines
10391085 "entityID:" << entityID << "methodName:" << methodName;
10401086 #endif
10411087
1088+ refreshFileScript(entityID);
10421089 if (_entityScripts.contains(entityID)) {
10431090 EntityScriptDetails details = _entityScripts[entityID];
10441091 QScriptValue entityScript = details.scriptObject; // previously loaded
@@ -1069,6 +1116,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 24 unmodified lines
10691116 "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
10701117 #endif
10711118
1119+ refreshFileScript(entityID);
10721120 if (_entityScripts.contains(entityID)) {
10731121 EntityScriptDetails details = _entityScripts[entityID];
10741122 QScriptValue entityScript = details.scriptObject; // previously loaded
@@ -1101,6 +1149,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 26 unmodified lines
11011149 "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
11021150 #endif
11031151
1152+ refreshFileScript(entityID);
11041153 if (_entityScripts.contains(entityID)) {
11051154 EntityScriptDetails details = _entityScripts[entityID];
11061155 QScriptValue entityScript = details.scriptObject; // previously loaded