mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #10790 from davidkelly/dk/scriptsSwitch
Command line switch to override default scripts location
This commit is contained in:
commit
63279f4525
8 changed files with 83 additions and 49 deletions
|
@ -903,6 +903,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_saveAvatarOverrideUrl = true;
|
||||
}
|
||||
|
||||
QString defaultScriptsLocation = getCmdOption(argc, constArgv, "--scripts");
|
||||
if (!defaultScriptsLocation.isEmpty()) {
|
||||
PathUtils::defaultScriptsLocation(defaultScriptsLocation);
|
||||
}
|
||||
|
||||
_glWidget = new GLCanvas();
|
||||
getApplicationCompositor().setRenderingWidget(_glWidget);
|
||||
_window->setCentralWidget(_glWidget);
|
||||
|
@ -1167,7 +1172,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
// force the model the look at the correct directory (weird order of operations issue)
|
||||
scriptEngines->setScriptsLocation(scriptEngines->getScriptsLocation());
|
||||
// do this as late as possible so that all required subsystems are initialized
|
||||
scriptEngines->loadScripts();
|
||||
// If we've overridden the default scripts location, just load default scripts
|
||||
// otherwise, load 'em all
|
||||
if (!defaultScriptsLocation.isEmpty()) {
|
||||
scriptEngines->loadDefaultScripts();
|
||||
scriptEngines->defaultScriptsLocationOverridden(true);
|
||||
} else {
|
||||
scriptEngines->loadScripts();
|
||||
}
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
|
||||
|
@ -5855,7 +5868,7 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const
|
|||
|
||||
void Application::showScriptLogs() {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js");
|
||||
scriptEngines->loadScript(defaultScriptsLoc.toString());
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ Menu::Menu() {
|
|||
// Settings > Avatar...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, "Avatar...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
qApp->showDialog(QString("hifi/dialogs/AvatarPreferencesDialog.qml"),
|
||||
qApp->showDialog(QString("hifi/dialogs/AvatarPreferencesDialog.qml"),
|
||||
QString("../../hifi/tablet/TabletAvatarPreferences.qml"), "AvatarPreferencesDialog");
|
||||
});
|
||||
|
||||
|
@ -629,7 +629,7 @@ Menu::Menu() {
|
|||
action = addActionToQMenuAndActionHash(audioDebugMenu, "Stats...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/audio/stats.js");
|
||||
scriptEngines->loadScript(defaultScriptsLoc.toString());
|
||||
});
|
||||
|
|
|
@ -172,7 +172,7 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const
|
|||
emit unhandledException(exception);
|
||||
}
|
||||
}, Qt::DirectConnection);
|
||||
|
||||
|
||||
setProcessEventsInterval(MSECS_PER_SECOND);
|
||||
if (isEntityServerScript()) {
|
||||
qCDebug(scriptengine) << "isEntityServerScript() -- limiting maxRetries to 1";
|
||||
|
@ -281,7 +281,7 @@ void ScriptEngine::runDebuggable() {
|
|||
scriptDebugMenu = nullptr;
|
||||
}
|
||||
}
|
||||
disconnect(timer);
|
||||
disconnect(timer);
|
||||
});
|
||||
|
||||
connect(timer, &QTimer::timeout, [this, timer] {
|
||||
|
@ -340,7 +340,7 @@ void ScriptEngine::runInThread() {
|
|||
QThread* workerThread = new QThread();
|
||||
workerThread->setObjectName(QString("js:") + getFilename().replace("about:",""));
|
||||
moveToThread(workerThread);
|
||||
|
||||
|
||||
// NOTE: If you connect any essential signals for proper shutdown or cleanup of
|
||||
// the script engine, make sure to add code to "reconnect" them to the
|
||||
// disconnectNonEssentialSignals() method
|
||||
|
@ -1047,26 +1047,26 @@ void ScriptEngine::run() {
|
|||
auto beforeSleep = clock::now();
|
||||
|
||||
// Throttle to SCRIPT_FPS
|
||||
// We'd like to try to keep the script at a solid SCRIPT_FPS update rate. And so we will
|
||||
// We'd like to try to keep the script at a solid SCRIPT_FPS update rate. And so we will
|
||||
// calculate a sleepUntil to be the time from our start time until the original target
|
||||
// sleepUntil for this frame. This approach will allow us to "catch up" in the event
|
||||
// that some of our script udpates/frames take a little bit longer than the target average
|
||||
// sleepUntil for this frame. This approach will allow us to "catch up" in the event
|
||||
// that some of our script udpates/frames take a little bit longer than the target average
|
||||
// to execute.
|
||||
// NOTE: if we go to variable SCRIPT_FPS, then we will need to reconsider this approach
|
||||
const std::chrono::microseconds TARGET_SCRIPT_FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1);
|
||||
clock::time_point targetSleepUntil(startTime + (thisFrame++ * TARGET_SCRIPT_FRAME_DURATION));
|
||||
|
||||
// However, if our sleepUntil is not at least our average update and timer execution time
|
||||
// into the future it means our script is taking too long in its updates, and we want to
|
||||
// punish the script a little bit. So we will force the sleepUntil to be at least our
|
||||
// However, if our sleepUntil is not at least our average update and timer execution time
|
||||
// into the future it means our script is taking too long in its updates, and we want to
|
||||
// punish the script a little bit. So we will force the sleepUntil to be at least our
|
||||
// averageUpdate + averageTimerPerFrame time into the future.
|
||||
auto averageUpdate = totalUpdates / thisFrame;
|
||||
auto averageTimerPerFrame = _totalTimerExecution / thisFrame;
|
||||
auto averageTimerAndUpdate = averageUpdate + averageTimerPerFrame;
|
||||
auto sleepUntil = std::max(targetSleepUntil, beforeSleep + averageTimerAndUpdate);
|
||||
|
||||
// We don't want to actually sleep for too long, because it causes our scripts to hang
|
||||
// on shutdown and stop... so we want to loop and sleep until we've spent our time in
|
||||
// We don't want to actually sleep for too long, because it causes our scripts to hang
|
||||
// on shutdown and stop... so we want to loop and sleep until we've spent our time in
|
||||
// purgatory, constantly checking to see if our script was asked to end
|
||||
bool processedEvents = false;
|
||||
while (!_isFinished && clock::now() < sleepUntil) {
|
||||
|
@ -1399,7 +1399,7 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re
|
|||
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
|
||||
return QString();
|
||||
}
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
QUrl url(moduleId);
|
||||
|
||||
auto displayId = moduleId;
|
||||
|
@ -1465,7 +1465,7 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re
|
|||
canonical.setPath(file.canonicalFilePath());
|
||||
}
|
||||
|
||||
bool disallowOutsideFiles = !defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile();
|
||||
bool disallowOutsideFiles = !PathUtils::defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile();
|
||||
if (disallowOutsideFiles && !PathUtils::isDescendantOf(canonical, currentSandboxURL)) {
|
||||
return throwResolveError(makeError(message.arg(
|
||||
QString("path '%1' outside of origin script '%2' '%3'")
|
||||
|
@ -1750,7 +1750,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
return;
|
||||
}
|
||||
if (DependencyManager::get<ScriptEngines>()->isStopped()) {
|
||||
scriptWarningMessage("Script.include() while shutting down is ignored... includeFiles:"
|
||||
scriptWarningMessage("Script.include() while shutting down is ignored... includeFiles:"
|
||||
+ includeFiles.join(",") + "parent script:" + getFilename());
|
||||
return; // bail early
|
||||
}
|
||||
|
@ -1762,7 +1762,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
bool isStandardLibrary = false;
|
||||
if (file.startsWith("/~/")) {
|
||||
thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file)));
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
if (!defaultScriptsLoc.isParentOf(thisURL)) {
|
||||
scriptWarningMessage("Script.include() -- skipping" + file + "-- outside of standard libraries");
|
||||
continue;
|
||||
|
@ -1774,7 +1774,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
|
||||
bool disallowOutsideFiles = thisURL.isLocalFile() && !isStandardLibrary && !currentSandboxURL.isLocalFile();
|
||||
if (disallowOutsideFiles && !PathUtils::isDescendantOf(thisURL, currentSandboxURL)) {
|
||||
scriptWarningMessage("Script.include() ignoring file path" + thisURL.toString()
|
||||
scriptWarningMessage("Script.include() ignoring file path" + thisURL.toString()
|
||||
+ "outside of original entity script" + currentSandboxURL.toString());
|
||||
} else {
|
||||
// We could also check here for CORS, but we don't yet.
|
||||
|
@ -1844,7 +1844,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
|
||||
void ScriptEngine::include(const QString& includeFile, QScriptValue callback) {
|
||||
if (DependencyManager::get<ScriptEngines>()->isStopped()) {
|
||||
scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:"
|
||||
scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:"
|
||||
+ includeFile + "parent script:" + getFilename());
|
||||
return; // bail early
|
||||
}
|
||||
|
@ -1862,12 +1862,12 @@ void ScriptEngine::load(const QString& loadFile) {
|
|||
return;
|
||||
}
|
||||
if (DependencyManager::get<ScriptEngines>()->isStopped()) {
|
||||
scriptWarningMessage("Script.load() while shutting down is ignored... loadFile:"
|
||||
scriptWarningMessage("Script.load() while shutting down is ignored... loadFile:"
|
||||
+ loadFile + "parent script:" + getFilename());
|
||||
return; // bail early
|
||||
}
|
||||
if (!currentEntityIdentifier.isInvalidID()) {
|
||||
scriptWarningMessage("Script.load() from entity script is ignored... loadFile:"
|
||||
scriptWarningMessage("Script.load() from entity script is ignored... loadFile:"
|
||||
+ loadFile + "parent script:" + getFilename() + "entity: " + currentEntityIdentifier.toString());
|
||||
return; // bail early
|
||||
}
|
||||
|
@ -2548,7 +2548,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
|
|||
qCDebug(scriptengine) << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] "
|
||||
"entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
|
||||
#endif
|
||||
|
||||
|
||||
if (HIFI_AUTOREFRESH_FILE_SCRIPTS) {
|
||||
refreshFileScript(entityID);
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ ScriptEngines::ScriptEngines(ScriptEngine::Context context)
|
|||
QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
|
||||
if (rawScriptURL.scheme() == "file") {
|
||||
QUrl fullNormal = rawScriptURL;
|
||||
QUrl defaultScriptLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptLoc = PathUtils::defaultScriptsLocation();
|
||||
|
||||
// if this url is something "beneath" the default script url, replace the local path with ~
|
||||
if (fullNormal.scheme() == defaultScriptLoc.scheme() &&
|
||||
|
@ -93,7 +93,7 @@ QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
|
|||
|
||||
QString expandScriptPath(const QString& rawPath) {
|
||||
QStringList splitPath = rawPath.split("/");
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
return defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/"); // 2 to skip the slashes in /~/
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ QUrl expandScriptUrl(const QUrl& rawScriptURL) {
|
|||
QFileInfo fileInfo(url.toLocalFile());
|
||||
url = QUrl::fromLocalFile(fileInfo.canonicalFilePath());
|
||||
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
if (!defaultScriptsLoc.isParentOf(url)) {
|
||||
qCWarning(scriptengine) << "Script.include() ignoring file path" << rawScriptURL
|
||||
<< "-- outside of standard libraries: "
|
||||
|
@ -327,6 +327,13 @@ void ScriptEngines::saveScripts() {
|
|||
return;
|
||||
}
|
||||
|
||||
// don't save scripts if we started with --scripts, as we would overwrite
|
||||
// the scripts that the user expects to be there when launched without the
|
||||
// --scripts override.
|
||||
if (_defaultScriptsLocationOverridden) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Saves all currently running user-loaded scripts
|
||||
QVariantList list;
|
||||
|
||||
|
@ -541,11 +548,11 @@ void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) {
|
|||
initializer(scriptEngine);
|
||||
}
|
||||
|
||||
// FIXME disabling 'shift key' debugging for now. If you start up the application with
|
||||
// the shift key held down, it triggers a deadlock because of script interfaces running
|
||||
// FIXME disabling 'shift key' debugging for now. If you start up the application with
|
||||
// the shift key held down, it triggers a deadlock because of script interfaces running
|
||||
// on the main thread
|
||||
auto const wantDebug = scriptEngine->isDebuggable(); // || (qApp->queryKeyboardModifiers() & Qt::ShiftModifier);
|
||||
|
||||
|
||||
if (HIFI_SCRIPT_DEBUGGABLES && wantDebug) {
|
||||
scriptEngine->runDebuggable();
|
||||
} else {
|
||||
|
@ -581,5 +588,5 @@ void ScriptEngines::onScriptEngineError(const QString& scriptFilename) {
|
|||
}
|
||||
|
||||
QString ScriptEngines::getDefaultScriptsLocation() const {
|
||||
return defaultScriptsLocation().toString();
|
||||
return PathUtils::defaultScriptsLocation().toString();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ public:
|
|||
|
||||
Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation)
|
||||
|
||||
void defaultScriptsLocationOverridden(bool overridden) { _defaultScriptsLocationOverridden = overridden; };
|
||||
|
||||
// Called at shutdown time
|
||||
void shutdownScripting();
|
||||
bool isStopped() const { return _isStopped; }
|
||||
|
@ -113,6 +115,7 @@ protected:
|
|||
ScriptsModelFilter _scriptsModelFilter;
|
||||
std::atomic<bool> _isStopped { false };
|
||||
std::atomic<bool> _isReloading { false };
|
||||
bool _defaultScriptsLocationOverridden { false };
|
||||
};
|
||||
|
||||
QUrl normalizeScriptURL(const QUrl& rawScriptURL);
|
||||
|
|
|
@ -125,15 +125,15 @@ int ScriptsModel::columnCount(const QModelIndex& parent) const {
|
|||
|
||||
void ScriptsModel::updateScriptsLocation(const QString& newPath) {
|
||||
_fsWatcher.removePath(_localDirectory.absolutePath());
|
||||
|
||||
|
||||
if (!newPath.isEmpty()) {
|
||||
_localDirectory.setPath(newPath);
|
||||
|
||||
|
||||
if (!_localDirectory.absolutePath().isEmpty()) {
|
||||
_fsWatcher.addPath(_localDirectory.absolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
reloadLocalFiles();
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ void ScriptsModel::reloadDefaultFiles() {
|
|||
}
|
||||
|
||||
void ScriptsModel::requestDefaultFiles(QString marker) {
|
||||
QUrl url(defaultScriptsLocation());
|
||||
QUrl url(PathUtils::defaultScriptsLocation());
|
||||
|
||||
// targets that don't have a scripts folder in the appropriate location will have an empty URL here
|
||||
if (!url.isEmpty()) {
|
||||
|
@ -244,7 +244,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
|
|||
lastKey = xml.text().toString();
|
||||
if (jsRegex.exactMatch(xml.text().toString())) {
|
||||
QString localPath = lastKey.split("/").mid(1).join("/");
|
||||
QUrl fullPath = defaultScriptsLocation();
|
||||
QUrl fullPath = PathUtils::defaultScriptsLocation();
|
||||
fullPath.setPath(fullPath.path() + lastKey);
|
||||
const QString fullPathStr = normalizeScriptURL(fullPath).toString();
|
||||
_treeNodes.append(new TreeNodeScript(localPath, fullPathStr, SCRIPT_ORIGIN_DEFAULT));
|
||||
|
|
|
@ -71,21 +71,33 @@ QString findMostRecentFileExtension(const QString& originalFileName, QVector<QSt
|
|||
return newestFileName;
|
||||
}
|
||||
|
||||
QUrl defaultScriptsLocation() {
|
||||
// return "http://s3.amazonaws.com/hifi-public";
|
||||
#ifdef Q_OS_WIN
|
||||
QString path = QCoreApplication::applicationDirPath() + "/scripts";
|
||||
#elif defined(Q_OS_OSX)
|
||||
QString path = QCoreApplication::applicationDirPath() + "/../Resources/scripts";
|
||||
#else
|
||||
QString path = QCoreApplication::applicationDirPath() + "/scripts";
|
||||
#endif
|
||||
QUrl PathUtils::defaultScriptsLocation(const QString& newDefaultPath) {
|
||||
static QString overriddenDefaultScriptsLocation = "";
|
||||
QString path;
|
||||
|
||||
// set overriddenDefaultScriptLocation if it was passed in
|
||||
if (!newDefaultPath.isEmpty()) {
|
||||
overriddenDefaultScriptsLocation = newDefaultPath;
|
||||
}
|
||||
|
||||
// use the overridden location if it is set
|
||||
if (!overriddenDefaultScriptsLocation.isEmpty()) {
|
||||
path = overriddenDefaultScriptsLocation;
|
||||
} else {
|
||||
#ifdef Q_OS_WIN
|
||||
path = QCoreApplication::applicationDirPath() + "/scripts";
|
||||
#elif defined(Q_OS_OSX)
|
||||
path = QCoreApplication::applicationDirPath() + "/../Resources/scripts";
|
||||
#else
|
||||
path = QCoreApplication::applicationDirPath() + "/scripts";
|
||||
#endif
|
||||
}
|
||||
|
||||
// turn the string into a legit QUrl
|
||||
QFileInfo fileInfo(path);
|
||||
return QUrl::fromLocalFile(fileInfo.canonicalFilePath());
|
||||
}
|
||||
|
||||
|
||||
QString PathUtils::stripFilename(const QUrl& url) {
|
||||
// Guard against meaningless query and fragment parts.
|
||||
// Do NOT use PreferLocalFile as its behavior is unpredictable (e.g., on defaultScriptsLocation())
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#define hifi_PathUtils_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
|
||||
/**jsdoc
|
||||
|
@ -38,11 +37,11 @@ public:
|
|||
static QString stripFilename(const QUrl& url);
|
||||
// note: this is FS-case-sensitive version of parentURL.isParentOf(childURL)
|
||||
static bool isDescendantOf(const QUrl& childURL, const QUrl& parentURL);
|
||||
static QUrl defaultScriptsLocation(const QString& newDefault = "");
|
||||
|
||||
};
|
||||
|
||||
QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions);
|
||||
QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions);
|
||||
|
||||
QUrl defaultScriptsLocation();
|
||||
|
||||
#endif // hifi_PathUtils_h
|
||||
|
|
Loading…
Reference in a new issue