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
11 11
12#include <QtCore/QCoreApplication>12#include <QtCore/QCoreApplication>
13#include <QtCore/QEventLoop>13#include <QtCore/QEventLoop>
14#include <QtCore/QFileInfo>
14#include <QtCore/QTimer>15#include <QtCore/QTimer>
15#include <QtCore/QThread>16#include <QtCore/QThread>
16#include <QtNetwork/QNetworkRequest>17#include <QtNetwork/QNetworkRequest>
17#include <QtNetwork/QNetworkReply>18#include <QtNetwork/QNetworkReply>
18#include <QScriptEngine>19#include <QtScript/QScriptEngine>
19#include <QScriptValue>20#include <QtScript/QScriptValue>
20 21
21#include <AudioConstants.h>22#include <AudioConstants.h>
22#include <AudioEffectOptions.h>23#include <AudioEffectOptions.h>
@@ -942,6 +943,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 919 unmodified lines
942 #endif943 #endif
943 944
944 auto scriptCache = DependencyManager::get<ScriptCache>();945 auto scriptCache = DependencyManager::get<ScriptCache>();
946 bool isFileUrl = isURL && scriptOrURL.startsWith("file://");
945 947
946 // first check the syntax of the script contents948 // first check the syntax of the script contents
947 QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents);949 QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents);
@@ -950,7 +952,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 2 unmodified lines
950 qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":"952 qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":"
951 << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();953 << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
952 qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;954 qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
953 scriptCache->addScriptToBadScriptList(scriptOrURL);955 if (!isFileUrl) {
956 scriptCache->addScriptToBadScriptList(scriptOrURL);
957 }
954 return; // done processing script958 return; // done processing script
955 }959 }
956 960
@@ -965,14 +969,21 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 8 unmodified lines
965 qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;969 qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
966 qCDebug(scriptengine) << " NOT CONSTRUCTOR";970 qCDebug(scriptengine) << " NOT CONSTRUCTOR";
967 qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;971 qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
968 scriptCache->addScriptToBadScriptList(scriptOrURL);972 if (!isFileUrl) {
973 scriptCache->addScriptToBadScriptList(scriptOrURL);
974 }
969 return; // done processing script975 return; // done processing script
970 }976 }
971 977
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 }
973 983
984 QScriptValue entityScriptConstructor = evaluate(contents);
974 QScriptValue entityScriptObject = entityScriptConstructor.construct();985 QScriptValue entityScriptObject = entityScriptConstructor.construct();
975 EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject };986 EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified };
976 _entityScripts[entityID] = newDetails;987 _entityScripts[entityID] = newDetails;
977 if (isURL) {988 if (isURL) {
978 setParentURL("");989 setParentURL("");
@@ -1022,6 +1033,41 @@ void ScriptEngine::unloadAllEntityScripts() { · 43 unmodified lines
1022 _entityScripts.clear();1033 _entityScripts.clear();
1023}1034}
1024 1035
1036void 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
1025void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) {1071void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) {
1026 if (QThread::currentThread() != thread()) {1072 if (QThread::currentThread() != thread()) {
1027 #ifdef THREAD_DEBUGGING1073 #ifdef THREAD_DEBUGGING
@@ -1039,6 +1085,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 11 unmodified lines
1039 "entityID:" << entityID << "methodName:" << methodName;1085 "entityID:" << entityID << "methodName:" << methodName;
1040 #endif1086 #endif
1041 1087
1088 refreshFileScript(entityID);
1042 if (_entityScripts.contains(entityID)) {1089 if (_entityScripts.contains(entityID)) {
1043 EntityScriptDetails details = _entityScripts[entityID];1090 EntityScriptDetails details = _entityScripts[entityID];
1044 QScriptValue entityScript = details.scriptObject; // previously loaded1091 QScriptValue entityScript = details.scriptObject; // previously loaded
@@ -1069,6 +1116,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 24 unmodified lines
1069 "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";1116 "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
1070 #endif1117 #endif
1071 1118
1119 refreshFileScript(entityID);
1072 if (_entityScripts.contains(entityID)) {1120 if (_entityScripts.contains(entityID)) {
1073 EntityScriptDetails details = _entityScripts[entityID];1121 EntityScriptDetails details = _entityScripts[entityID];
1074 QScriptValue entityScript = details.scriptObject; // previously loaded1122 QScriptValue entityScript = details.scriptObject; // previously loaded
@@ -1101,6 +1149,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 26 unmodified lines
1101 "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";1149 "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
1102 #endif1150 #endif
1103 1151
1152 refreshFileScript(entityID);
1104 if (_entityScripts.contains(entityID)) {1153 if (_entityScripts.contains(entityID)) {
1105 EntityScriptDetails details = _entityScripts[entityID];1154 EntityScriptDetails details = _entityScripts[entityID];
1106 QScriptValue entityScript = details.scriptObject; // previously loaded1155 QScriptValue entityScript = details.scriptObject; // previously loaded