diff --git a/examples/edit.js b/examples/edit.js
index 92e4737f29..23cc942192 100644
--- a/examples/edit.js
+++ b/examples/edit.js
@@ -1321,6 +1321,15 @@ PropertiesTool = function(opts) {
pushCommandForSelections();
selectionManager._update();
}
+ } else if (data.action == "reloadScript") {
+ if (selectionManager.hasSelection()) {
+ var timestamp = Date.now();
+ for (var i = 0; i < selectionManager.selections.length; i++) {
+ Entities.editEntity(selectionManager.selections[i], {
+ scriptTimestamp: timestamp,
+ });
+ }
+ }
} else if (data.action == "centerAtmosphereToZone") {
if (selectionManager.hasSelection()) {
selectionManager.saveProperties();
diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html
index c974845585..8a15147f16 100644
--- a/examples/html/entityProperties.html
+++ b/examples/html/entityProperties.html
@@ -250,6 +250,8 @@
var elCollisionSoundURL = document.getElementById("property-collision-sound-url");
var elLifetime = document.getElementById("property-lifetime");
var elScriptURL = document.getElementById("property-script-url");
+ var elScriptTimestamp = document.getElementById("property-script-timestamp");
+ var elReloadScriptButton = document.getElementById("reload-script-button");
var elUserData = document.getElementById("property-user-data");
var elColorSection = document.getElementById("color-section");
@@ -470,6 +472,7 @@
elCollisionSoundURL.value = properties.collisionSoundURL;
elLifetime.value = properties.lifetime;
elScriptURL.value = properties.script;
+ elScriptTimestamp.value = properties.scriptTimestamp;
elUserData.value = properties.userData;
elHyperlinkHref.value = properties.href;
@@ -688,6 +691,7 @@
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script'));
+ elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp'));
elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData'));
var colorChangeFunction = createEmitColorPropertyUpdateFunction(
@@ -889,6 +893,12 @@
percentage: parseInt(elRescaleDimensionsPct.value),
}));
});
+ elReloadScriptButton.addEventListener("click", function() {
+ EventBridge.emitWebEvent(JSON.stringify({
+ type: "action",
+ action: "reloadScript"
+ }));
+ });
elCenterAtmosphereToZone.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({
type: "action",
@@ -1181,7 +1191,10 @@
-
Script URL
+
Script URL
+
+
+
diff --git a/examples/html/style.css b/examples/html/style.css
index f12cfb6dd0..e63b6338fc 100644
--- a/examples/html/style.css
+++ b/examples/html/style.css
@@ -260,6 +260,11 @@ table#properties-list {
height: 1.2em;
}
+#properties-list .label input[type=button] {
+ float: right;
+ padding: 0 5px 1px;
+}
+
#properties-list .value > div{
padding: 3pt 0;
}
diff --git a/interface/resources/images/reload-script.svg b/interface/resources/images/reload-script.svg
new file mode 100644
index 0000000000..a33de448dc
--- /dev/null
+++ b/interface/resources/images/reload-script.svg
@@ -0,0 +1,50 @@
+
+
\ No newline at end of file
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index d9c5589631..eb6a53f765 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -4048,6 +4048,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
connect(scriptEngine, SIGNAL(finished(const QString&)), this, SLOT(scriptFinished(const QString&)));
connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool)));
+ connect(scriptEngine, SIGNAL(reloadScript(const QString&, bool)), this, SLOT(reloadScript(const QString&, bool)));
scriptEngine->registerGlobalObject("Overlays", &_overlays);
qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
@@ -4263,7 +4264,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
}
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
- bool loadScriptFromEditor, bool activateMainWindow) {
+ bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
if (isAboutToQuit()) {
return NULL;
@@ -4292,7 +4293,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError);
// get the script engine object to load the script at the designated script URL
- scriptEngine->loadURL(scriptUrl);
+ scriptEngine->loadURL(scriptUrl, reload);
}
// restore the main window's active state
@@ -4303,6 +4304,10 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
return scriptEngine;
}
+void Application::reloadScript(const QString& scriptName, bool isUserLoaded) {
+ loadScript(scriptName, isUserLoaded, false, false, true);
+}
+
void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
ScriptEngine* scriptEngine = qobject_cast
(sender());
@@ -4330,14 +4335,25 @@ void Application::scriptFinished(const QString& scriptName) {
}
void Application::stopAllScripts(bool restart) {
- // stops all current running scripts
+ if (restart) {
+ // Delete all running scripts from cache so that they are re-downloaded when they are restarted
+ auto scriptCache = DependencyManager::get();
+ for (QHash::const_iterator it = _scriptEnginesHash.constBegin();
+ it != _scriptEnginesHash.constEnd(); it++) {
+ if (!it.value()->isFinished()) {
+ scriptCache->deleteScript(it.key());
+ }
+ }
+ }
+
+ // Stop and possibly restart all currently running scripts
for (QHash::const_iterator it = _scriptEnginesHash.constBegin();
it != _scriptEnginesHash.constEnd(); it++) {
if (it.value()->isFinished()) {
continue;
}
if (restart && it.value()->isUserLoaded()) {
- connect(it.value(), SIGNAL(finished(const QString&)), SLOT(loadScript(const QString&)));
+ connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
}
it.value()->stop();
qCDebug(interfaceapp) << "stopping script..." << it.key();
@@ -4345,13 +4361,20 @@ void Application::stopAllScripts(bool restart) {
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
// whenever a script stops in case it happened to have been setting joint rotations.
// TODO: expose animation priorities and provide a layered animation control system.
+ _myAvatar->clearJointAnimationPriorities();
_myAvatar->clearScriptableSettings();
}
-void Application::stopScript(const QString &scriptName) {
+void Application::stopScript(const QString &scriptName, bool restart) {
const QString& scriptURLString = QUrl(scriptName).toString();
if (_scriptEnginesHash.contains(scriptURLString)) {
- _scriptEnginesHash.value(scriptURLString)->stop();
+ ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
+ if (restart) {
+ auto scriptCache = DependencyManager::get();
+ scriptCache->deleteScript(scriptName);
+ connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
+ }
+ scriptEngine->stop();
qCDebug(interfaceapp) << "stopping script..." << scriptName;
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
// whenever a script stops in case it happened to have been setting joint rotations.
@@ -4367,6 +4390,10 @@ void Application::reloadAllScripts() {
stopAllScripts(true);
}
+void Application::reloadOneScript(const QString& scriptName) {
+ stopScript(scriptName, true);
+}
+
void Application::loadDefaultScripts() {
if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
loadScript(DEFAULT_SCRIPTS_JS_URL);
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 2c78327f02..0787cffbdc 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -409,15 +409,19 @@ public slots:
bool acceptSnapshot(const QString& urlString);
bool askToSetAvatarUrl(const QString& url);
bool askToLoadScript(const QString& scriptFilenameOrURL);
+
ScriptEngine* loadScript(const QString& scriptFilename = QString(), bool isUserLoaded = true,
- bool loadScriptFromEditor = false, bool activateMainWindow = false);
+ bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
+ void reloadScript(const QString& scriptName, bool isUserLoaded = true);
void scriptFinished(const QString& scriptName);
void stopAllScripts(bool restart = false);
- void stopScript(const QString& scriptName);
+ void stopScript(const QString& scriptName, bool restart = false);
void reloadAllScripts();
+ void reloadOneScript(const QString& scriptName);
void loadDefaultScripts();
void toggleRunningScriptsWidget();
void saveScripts();
+
void showFriendsWindow();
void friendsWindowClosed();
diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp
index 31c9271c22..1165de7592 100644
--- a/interface/src/ui/RunningScriptsWidget.cpp
+++ b/interface/src/ui/RunningScriptsWidget.cpp
@@ -32,7 +32,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint |
Qt::WindowCloseButtonHint),
ui(new Ui::RunningScriptsWidget),
- _signalMapper(this),
+ _reloadSignalMapper(this),
+ _stopSignalMapper(this),
_scriptsModelFilter(this),
_scriptsModel(this) {
ui->setupUi(this);
@@ -64,7 +65,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
Application::getInstance(), &Application::loadDialog);
connect(ui->loadScriptFromURLButton, &QPushButton::clicked,
Application::getInstance(), &Application::loadScriptURLDialog);
- connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
+ connect(&_reloadSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(reloadOneScript(const QString&)));
+ connect(&_stopSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
UIUtil::scaleWidgetFontSizes(this);
}
@@ -115,6 +117,17 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
name->setText(name->text() + "(" + QString::number(hash.find(list.at(i)).value()) + ")");
}
++hash[list.at(i)];
+
+ QPushButton* reloadButton = new QPushButton(row);
+ reloadButton->setFlat(true);
+ reloadButton->setIcon(
+ QIcon(QPixmap(PathUtils::resourcesPath() + "images/reload-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT)));
+ reloadButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ reloadButton->setStyleSheet("border: 0;");
+ reloadButton->setCursor(Qt::PointingHandCursor);
+ connect(reloadButton, SIGNAL(clicked()), &_reloadSignalMapper, SLOT(map()));
+ _reloadSignalMapper.setMapping(reloadButton, url.toString());
+
QPushButton* closeButton = new QPushButton(row);
closeButton->setFlat(true);
closeButton->setIcon(
@@ -122,9 +135,8 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
closeButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
closeButton->setStyleSheet("border: 0;");
closeButton->setCursor(Qt::PointingHandCursor);
-
- connect(closeButton, SIGNAL(clicked()), &_signalMapper, SLOT(map()));
- _signalMapper.setMapping(closeButton, url.toString());
+ connect(closeButton, SIGNAL(clicked()), &_stopSignalMapper, SLOT(map()));
+ _stopSignalMapper.setMapping(closeButton, url.toString());
row->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
@@ -132,6 +144,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
row->layout()->setSpacing(0);
row->layout()->addWidget(name);
+ row->layout()->addWidget(reloadButton);
row->layout()->addWidget(closeButton);
row->setToolTip(url.toString());
diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h
index 5d3f6843af..c09bce5443 100644
--- a/interface/src/ui/RunningScriptsWidget.h
+++ b/interface/src/ui/RunningScriptsWidget.h
@@ -36,7 +36,7 @@ public:
const ScriptsModel* getScriptsModel() { return &_scriptsModel; }
signals:
- void stopScriptName(const QString& name);
+ void stopScriptName(const QString& name, bool restart = false);
protected:
virtual bool eventFilter(QObject* sender, QEvent* event);
@@ -59,7 +59,8 @@ private slots:
private:
Ui::RunningScriptsWidget* ui;
- QSignalMapper _signalMapper;
+ QSignalMapper _reloadSignalMapper;
+ QSignalMapper _stopSignalMapper;
ScriptsModelFilter _scriptsModelFilter;
ScriptsModel _scriptsModel;
ScriptsTableWidget* _recentlyLoadedScriptsTable;
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index 0ea6080165..03d88200c5 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -122,9 +122,9 @@ void EntityTreeRenderer::init() {
// first chance, we'll check for enter/leave entity events.
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
- connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity);
- connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity);
- connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging);
+ connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection);
+ connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection);
+ connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging, Qt::QueuedConnection);
}
void EntityTreeRenderer::shutdown() {
@@ -148,13 +148,14 @@ void EntityTreeRenderer::errorInLoadingScript(const QUrl& url) {
}
}
-QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload) {
+QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload, bool reload) {
EntityItemPointer entity = static_cast(_tree)->findEntityByEntityItemID(entityItemID);
- return loadEntityScript(entity, isPreload);
+ return loadEntityScript(entity, isPreload, reload);
}
-QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut) {
+QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut,
+ bool& reload) {
isPending = false;
QUrl url(scriptMaybeURLorText);
@@ -192,7 +193,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
auto scriptCache = DependencyManager::get();
if (!scriptCache->isInBadScriptList(url)) {
- scriptContents = scriptCache->getScript(url, this, isPending);
+ scriptContents = scriptCache->getScript(url, this, isPending, reload);
}
}
}
@@ -201,7 +202,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
}
-QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload) {
+QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload, bool reload) {
if (_shuttingDown) {
return QScriptValue(); // since we're shutting down, we don't load any more scripts
}
@@ -221,8 +222,8 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
if (_entityScripts.contains(entityID)) {
EntityScriptDetails details = _entityScripts[entityID];
- // check to make sure our script text hasn't changed on us since we last loaded it
- if (details.scriptText == entityScript) {
+ // check to make sure our script text hasn't changed on us since we last loaded it and we're not redownloading it
+ if (details.scriptText == entityScript && !reload) {
return details.scriptObject; // previously loaded
}
@@ -237,7 +238,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
bool isURL = false; // loadScriptContents() will tell us if this is a URL or just text.
bool isPending = false;
QUrl url;
- QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url);
+ QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url, reload);
if (isPending && isPreload && isURL) {
_waitingOnPreload.insert(url, entityID);
@@ -1030,17 +1031,17 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) {
}
-void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
+void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const bool reload) {
if (_tree && !_shuttingDown) {
checkAndCallUnload(entityID);
- checkAndCallPreload(entityID);
+ checkAndCallPreload(entityID, reload);
}
}
-void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) {
+void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) {
if (_tree && !_shuttingDown) {
// load the entity script if needed...
- QScriptValue entityScript = loadEntityScript(entityID, true); // is preload!
+ QScriptValue entityScript = loadEntityScript(entityID, true, reload); // is preload!
if (entityScript.property("preload").isValid()) {
QScriptValueList entityArgs = createEntityArgs(entityID);
entityScript.property("preload").call(entityScript, entityArgs);
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h
index 56a8208eb4..bd6044516f 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.h
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.h
@@ -110,7 +110,7 @@ signals:
public slots:
void addingEntity(const EntityItemID& entityID);
void deletingEntity(const EntityItemID& entityID);
- void entitySciptChanging(const EntityItemID& entityID);
+ void entitySciptChanging(const EntityItemID& entityID, const bool reload);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
// optional slots that can be wired to menu items
@@ -127,7 +127,7 @@ private:
void applyZonePropertiesToScene(std::shared_ptr zone);
void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args);
- void checkAndCallPreload(const EntityItemID& entityID);
+ void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false);
void checkAndCallUnload(const EntityItemID& entityID);
QList _releasedModels;
@@ -148,10 +148,10 @@ private:
ScriptEngine* _entitiesScriptEngine;
ScriptEngine* _sandboxScriptEngine;
- QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false);
- QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false);
+ QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false, bool reload = false);
+ QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false, bool reload = false);
QScriptValue getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID);
- QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url);
+ QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url, bool& reload);
QScriptValueList createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID);
QScriptValueList createMouseEventArgs(const EntityItemID& entityID, const MouseEvent& mouseEvent);
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index da5f96f503..74b7a36504 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -54,6 +54,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
_friction(ENTITY_ITEM_DEFAULT_FRICTION),
_lifetime(ENTITY_ITEM_DEFAULT_LIFETIME),
_script(ENTITY_ITEM_DEFAULT_SCRIPT),
+ _scriptTimestamp(ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP),
_collisionSoundURL(ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
_registrationPoint(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT),
_angularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY),
@@ -107,6 +108,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
requestedProperties += PROP_FRICTION;
requestedProperties += PROP_LIFETIME;
requestedProperties += PROP_SCRIPT;
+ requestedProperties += PROP_SCRIPT_TIMESTAMP;
requestedProperties += PROP_COLLISION_SOUND_URL;
requestedProperties += PROP_REGISTRATION_POINT;
requestedProperties += PROP_ANGULAR_VELOCITY;
@@ -238,6 +240,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
APPEND_ENTITY_PROPERTY(PROP_FRICTION, getFriction());
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, getLifetime());
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript());
+ APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, getScriptTimestamp());
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getAngularVelocity());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
@@ -555,6 +558,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
+ READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
//READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
@@ -901,6 +905,7 @@ EntityItemProperties EntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(created, getCreated);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript);
+ COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getAngularVelocity);
@@ -967,6 +972,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
// non-simulation properties below
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
+ SET_ENTITY_PROPERTY_FROM_PROPERTIES(scriptTimestamp, setScriptTimestamp);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h
index b27129c124..3ce3a8e269 100644
--- a/libraries/entities/src/EntityItem.h
+++ b/libraries/entities/src/EntityItem.h
@@ -276,6 +276,10 @@ public:
const QString& getScript() const { return _script; }
void setScript(const QString& value) { _script = value; }
+
+ quint64 getScriptTimestamp() const { return _scriptTimestamp; }
+ void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
+
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
void setCollisionSoundURL(const QString& value) { _collisionSoundURL = value; }
@@ -412,6 +416,7 @@ protected:
float _friction;
float _lifetime;
QString _script;
+ quint64 _scriptTimestamp;
QString _collisionSoundURL;
glm::vec3 _registrationPoint;
glm::vec3 _angularVelocity;
diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp
index cab96eb2e6..f755cd49fb 100644
--- a/libraries/entities/src/EntityItemProperties.cpp
+++ b/libraries/entities/src/EntityItemProperties.cpp
@@ -51,6 +51,7 @@ CONSTRUCT_PROPERTY(friction, ENTITY_ITEM_DEFAULT_FRICTION),
CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME),
CONSTRUCT_PROPERTY(created, UNKNOWN_CREATED_TIME),
CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT),
+CONSTRUCT_PROPERTY(scriptTimestamp, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP),
CONSTRUCT_PROPERTY(collisionSoundURL, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
CONSTRUCT_PROPERTY(color, ),
CONSTRUCT_PROPERTY(modelURL, ""),
@@ -300,6 +301,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_FRICTION, friction);
CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime);
CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script);
+ CHECK_PROPERTY_CHANGE(PROP_SCRIPT_TIMESTAMP, scriptTimestamp);
CHECK_PROPERTY_CHANGE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
CHECK_PROPERTY_CHANGE(PROP_COLOR, color);
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
@@ -393,6 +395,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(created, created.toString(Qt::ISODate));
COPY_PROPERTY_TO_QSCRIPTVALUE(script);
+ COPY_PROPERTY_TO_QSCRIPTVALUE(scriptTimestamp);
COPY_PROPERTY_TO_QSCRIPTVALUE(registrationPoint);
COPY_PROPERTY_TO_QSCRIPTVALUE(angularVelocity);
COPY_PROPERTY_TO_QSCRIPTVALUE(angularDamping);
@@ -506,6 +509,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(friction, float, setFriction);
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifetime, float, setLifetime);
COPY_PROPERTY_FROM_QSCRIPTVALUE(script, QString, setScript);
+ COPY_PROPERTY_FROM_QSCRIPTVALUE(scriptTimestamp, quint64, setScriptTimestamp);
COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, glmVec3, setRegistrationPoint);
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
@@ -713,6 +717,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_FRICTION, properties.getFriction());
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, properties.getLifetime());
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, properties.getScript());
+ APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, properties.getScriptTimestamp());
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, properties.getRegistrationPoint());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity());
@@ -966,7 +971,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RESTITUTION, float, setRestitution);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FRICTION, float, setFriction);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFETIME, float, setLifetime);
- READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT,QString, setScript);
+ READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT, QString, setScript);
+ READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
@@ -1106,6 +1112,7 @@ void EntityItemProperties::markAllChanged() {
_userDataChanged = true;
_simulatorIDChanged = true;
_scriptChanged = true;
+ _scriptTimestampChanged = true;
_collisionSoundURLChanged = true;
_registrationPointChanged = true;
_angularVelocityChanged = true;
diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h
index 4772d08c44..fdf01c4761 100644
--- a/libraries/entities/src/EntityItemProperties.h
+++ b/libraries/entities/src/EntityItemProperties.h
@@ -98,6 +98,7 @@ public:
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float);
DEFINE_PROPERTY(PROP_CREATED, Created, created, quint64);
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString);
+ DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64);
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString);
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor);
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
@@ -262,6 +263,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Friction, friction, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifetime, lifetime, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, "");
+ DEBUG_PROPERTY_IF_CHANGED(debug, properties, ScriptTimestamp, scriptTimestamp, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionSoundURL, collisionSoundURL, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");
diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h
index 1e3a016049..0cdfe73040 100644
--- a/libraries/entities/src/EntityItemPropertiesDefaults.h
+++ b/libraries/entities/src/EntityItemPropertiesDefaults.h
@@ -32,6 +32,7 @@ const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f;
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
+const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0;
const QString ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL = QString("");
const glm::vec3 ENTITY_ITEM_DEFAULT_REGISTRATION_POINT = ENTITY_ITEM_HALF_VEC3; // center
diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h
index 0f3459e5d2..d4fcfa8cab 100644
--- a/libraries/entities/src/EntityItemPropertiesMacros.h
+++ b/libraries/entities/src/EntityItemPropertiesMacros.h
@@ -92,6 +92,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { r
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, quint32 v) { return QScriptValue(v); }
+inline QScriptValue convertScriptValue(QScriptEngine* e, quint64 v) { return QScriptValue((qsreal)v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { return xColorToScriptValue(e, v); }
@@ -134,6 +135,7 @@ typedef glm::vec3 glmVec3;
typedef glm::quat glmQuat;
typedef QVector qVectorVec3;
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
+inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }
diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h
index 5e35419ba2..e83a69227f 100644
--- a/libraries/entities/src/EntityPropertyFlags.h
+++ b/libraries/entities/src/EntityPropertyFlags.h
@@ -123,6 +123,7 @@ enum EntityPropertyList {
PROP_DESCRIPTION,
PROP_FACE_CAMERA,
+ PROP_SCRIPT_TIMESTAMP,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties ABOVE this line
diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp
index 363f3c56d7..752082932b 100644
--- a/libraries/entities/src/EntityTree.cpp
+++ b/libraries/entities/src/EntityTree.cpp
@@ -185,6 +185,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
// else client accepts what the server says
QString entityScriptBefore = entity->getScript();
+ quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
uint32_t preFlags = entity->getDirtyFlags();
UpdateEntityOperator theOperator(this, containingElement, entity, properties);
@@ -206,8 +207,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
}
QString entityScriptAfter = entity->getScript();
- if (entityScriptBefore != entityScriptAfter) {
- emitEntityScriptChanging(entity->getEntityItemID()); // the entity script has changed
+ quint64 entityScriptTimestampAfter = entity->getScriptTimestamp();
+ bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
+ if (entityScriptBefore != entityScriptAfter || reload) {
+ emitEntityScriptChanging(entity->getEntityItemID(), reload); // the entity script has changed
}
maybeNotifyNewCollisionSoundURL(collisionSoundURLBefore, entity->getCollisionSoundURL());
}
@@ -266,9 +269,10 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
return result;
}
-void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) {
- emit entityScriptChanging(entityItemID);
+void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload) {
+ emit entityScriptChanging(entityItemID, reload);
}
+
void EntityTree::maybeNotifyNewCollisionSoundURL(const QString& previousCollisionSoundURL, const QString& nextCollisionSoundURL) {
if (!nextCollisionSoundURL.isEmpty() && (nextCollisionSoundURL != previousCollisionSoundURL)) {
emit newCollisionSoundURL(QUrl(nextCollisionSoundURL));
diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h
index 1ad3ef6b1c..9c4be9a86f 100644
--- a/libraries/entities/src/EntityTree.h
+++ b/libraries/entities/src/EntityTree.h
@@ -155,7 +155,7 @@ public:
void entityChanged(EntityItemPointer entity);
- void emitEntityScriptChanging(const EntityItemID& entityItemID);
+ void emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload);
void setSimulation(EntitySimulation* simulation);
EntitySimulation* getSimulation() const { return _simulation; }
@@ -171,7 +171,7 @@ public:
signals:
void deletingEntity(const EntityItemID& entityID);
void addingEntity(const EntityItemID& entityID);
- void entityScriptChanging(const EntityItemID& entityItemID);
+ void entityScriptChanging(const EntityItemID& entityItemID, const bool reload);
void newCollisionSoundURL(const QUrl& url);
void clearingEntities();
diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp
index 80333a44e5..4bc81e1da6 100644
--- a/libraries/entities/src/EntityTreeElement.cpp
+++ b/libraries/entities/src/EntityTreeElement.cpp
@@ -733,6 +733,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
// 3) remember the old cube for the entity so we can mark it as dirty
if (entityItem) {
QString entityScriptBefore = entityItem->getScript();
+ quint64 entityScriptTimestampBefore = entityItem->getScriptTimestamp();
bool bestFitBefore = bestFitEntityBounds(entityItem);
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
@@ -755,8 +756,10 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
}
QString entityScriptAfter = entityItem->getScript();
- if (entityScriptBefore != entityScriptAfter) {
- _myTree->emitEntityScriptChanging(entityItemID); // the entity script has changed
+ quint64 entityScriptTimestampAfter = entityItem->getScriptTimestamp();
+ bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
+ if (entityScriptBefore != entityScriptAfter || reload) {
+ _myTree->emitEntityScriptChanging(entityItemID, reload); // the entity script has changed
}
} else {
diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp
index 29a670761a..5fe9bbbb99 100644
--- a/libraries/networking/src/PacketHeaders.cpp
+++ b/libraries/networking/src/PacketHeaders.cpp
@@ -73,7 +73,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketTypeEntityAdd:
case PacketTypeEntityEdit:
case PacketTypeEntityData:
- return VERSION_ENTITIES_FACE_CAMERA;
+ return VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX;
case PacketTypeEntityErase:
return 2;
case PacketTypeAudioStreamStats:
diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h
index 1d064c3399..789675ec00 100644
--- a/libraries/networking/src/PacketHeaders.h
+++ b/libraries/networking/src/PacketHeaders.h
@@ -184,5 +184,7 @@ const PacketVersion VERSION_NO_ENTITY_ID_SWAP = 27;
const PacketVersion VERSION_ENTITIES_PARTICLE_FIX = 28;
const PacketVersion VERSION_ENTITIES_LINE_POINTS = 29;
const PacketVersion VERSION_ENTITIES_FACE_CAMERA = 30;
+const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP = 31;
+const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX = 32;
#endif // hifi_PacketHeaders_h
diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp
index 8f854cfdc3..2047442ce6 100644
--- a/libraries/script-engine/src/ScriptCache.cpp
+++ b/libraries/script-engine/src/ScriptCache.cpp
@@ -16,18 +16,22 @@
#include
#include
+#include
#include
#include
-#include "ScriptEngineLogging.h"
+
#include "ScriptCache.h"
+#include "ScriptEngineLogging.h"
ScriptCache::ScriptCache(QObject* parent) {
// nothing to do here...
}
-QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending) {
+QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending, bool reload) {
+ assert(!_scriptCache.contains(url) || !reload);
+
QString scriptContents;
- if (_scriptCache.contains(url)) {
+ if (_scriptCache.contains(url) && !reload) {
qCDebug(scriptengine) << "Found script in cache:" << url.toString();
scriptContents = _scriptCache[url];
scriptUser->scriptContentsAvailable(url, scriptContents);
@@ -43,8 +47,13 @@ QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& is
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
+ if (reload) {
+ networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
+ qCDebug(scriptengine) << "Redownloading script at:" << url.toString();
+ } else {
+ qCDebug(scriptengine) << "Downloading script at:" << url.toString();
+ }
- qCDebug(scriptengine) << "Downloading script at" << url.toString();
QNetworkReply* reply = networkAccessManager.get(networkRequest);
connect(reply, &QNetworkReply::finished, this, &ScriptCache::scriptDownloaded);
}
@@ -52,6 +61,13 @@ QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& is
return scriptContents;
}
+void ScriptCache::deleteScript(const QUrl& url) {
+ if (_scriptCache.contains(url)) {
+ qCDebug(scriptengine) << "Delete script from cache:" << url.toString();
+ _scriptCache.remove(url);
+ }
+}
+
void ScriptCache::scriptDownloaded() {
QNetworkReply* reply = qobject_cast(sender());
QUrl url = reply->url();
diff --git a/libraries/script-engine/src/ScriptCache.h b/libraries/script-engine/src/ScriptCache.h
index 16bf04c53e..25a36c04d8 100644
--- a/libraries/script-engine/src/ScriptCache.h
+++ b/libraries/script-engine/src/ScriptCache.h
@@ -26,7 +26,8 @@ class ScriptCache : public QObject, public Dependency {
SINGLETON_DEPENDENCY
public:
- QString getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending);
+ QString getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending, bool redownload = false);
+ void deleteScript(const QUrl& url);
void addScriptToBadScriptList(const QUrl& url) { _badScripts.insert(url); }
bool isInBadScriptList(const QUrl& url) { return _badScripts.contains(url); }
diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index 0945a556f2..55cf9e9890 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -94,6 +94,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
_vec3Library(),
_uuidLibrary(),
_isUserLoaded(false),
+ _isReloading(false),
_arrayBufferClass(new ArrayBufferClass(this))
{
_allScriptsMutex.lock();
@@ -251,12 +252,13 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin
return true;
}
-void ScriptEngine::loadURL(const QUrl& scriptURL) {
+void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
if (_isRunning) {
return;
}
_fileNameString = scriptURL.toString();
+ _isReloading = reload;
QUrl url(scriptURL);
@@ -283,8 +285,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL) {
} else {
bool isPending;
auto scriptCache = DependencyManager::get();
- scriptCache->getScript(url, this, isPending);
-
+ scriptCache->getScript(url, this, isPending, reload);
}
}
}
@@ -904,7 +905,13 @@ void ScriptEngine::load(const QString& loadFile) {
}
QUrl url = resolvePath(loadFile);
- emit loadScript(url.toString(), false);
+ if (_isReloading) {
+ auto scriptCache = DependencyManager::get();
+ scriptCache->deleteScript(url.toString());
+ emit reloadScript(url.toString(), false);
+ } else {
+ emit loadScript(url.toString(), false);
+ }
}
void ScriptEngine::nodeKilled(SharedNodePointer node) {
diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h
index ec28804049..a96042184d 100644
--- a/libraries/script-engine/src/ScriptEngine.h
+++ b/libraries/script-engine/src/ScriptEngine.h
@@ -104,7 +104,7 @@ public:
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
public slots:
- void loadURL(const QUrl& scriptURL);
+ void loadURL(const QUrl& scriptURL, bool reload);
void stop();
QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
@@ -132,6 +132,7 @@ signals:
void runningStateChanged();
void evaluationFinished(QScriptValue result, bool isException);
void loadScript(const QString& scriptName, bool isUserLoaded);
+ void reloadScript(const QString& scriptName, bool isUserLoaded);
void doneRunning();
protected:
@@ -165,6 +166,7 @@ private:
Vec3 _vec3Library;
ScriptUUID _uuidLibrary;
bool _isUserLoaded;
+ bool _isReloading;
ArrayBufferClass* _arrayBufferClass;