mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 01:46:18 +02:00
Merge pull request #66 from Penguin-Guru/FixingParameters
Overhaul command-line parameter functionality.
This commit is contained in:
commit
1283c5230d
3 changed files with 357 additions and 219 deletions
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <QtCore/QResource>
|
||||
#include <QtCore/QAbstractNativeEventFilter>
|
||||
#include <QtCore/QCommandLineParser>
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QThreadPool>
|
||||
#include <QtCore/QFileSelector>
|
||||
|
@ -724,67 +723,24 @@ extern DisplayPluginList getDisplayPlugins();
|
|||
extern InputPluginList getInputPlugins();
|
||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||
|
||||
// Parameters used for running tests from teh command line
|
||||
const QString TEST_SCRIPT_COMMAND{ "--testScript" };
|
||||
const QString TEST_QUIT_WHEN_FINISHED_OPTION{ "quitWhenFinished" };
|
||||
const QString TEST_RESULTS_LOCATION_COMMAND{ "--testResultsLocation" };
|
||||
|
||||
bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||
bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, bool runningMarkerExisted) {
|
||||
const char** constArgv = const_cast<const char**>(argv);
|
||||
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
// HRS: I could not figure out how to move these any earlier in startup, so when using this option, be sure to also supply
|
||||
// --allowMultipleInstances
|
||||
auto reportAndQuit = [&](const char* commandSwitch, std::function<void(FILE* fp)> report) {
|
||||
const char* reportfile = getCmdOption(argc, constArgv, commandSwitch);
|
||||
// Reports to the specified file, because stdout is set up to be captured for logging.
|
||||
if (reportfile) {
|
||||
FILE* fp = fopen(reportfile, "w");
|
||||
if (fp) {
|
||||
report(fp);
|
||||
fclose(fp);
|
||||
if (!runningMarkerExisted) { // don't leave ours around
|
||||
RunningMarker runingMarker(RUNNING_MARKER_FILENAME);
|
||||
runingMarker.deleteRunningMarkerFile(); // happens in deleter, but making the side-effect explicit.
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
reportAndQuit("--protocolVersion", [&](FILE* fp) {
|
||||
auto version = protocolVersionsSignatureBase64();
|
||||
fputs(version.toLatin1().data(), fp);
|
||||
});
|
||||
reportAndQuit("--version", [&](FILE* fp) {
|
||||
fputs(BuildInfo::VERSION.toLatin1().data(), fp);
|
||||
});
|
||||
|
||||
const char* portStr = getCmdOption(argc, constArgv, "--listenPort");
|
||||
const int listenPort = portStr ? atoi(portStr) : INVALID_PORT;
|
||||
const int listenPort = parser.isSet("listenPort") ? parser.value("listenPort").toInt() : INVALID_PORT;
|
||||
|
||||
static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
|
||||
bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
|
||||
bool suppressPrompt = parser.isSet("suppress-settings-reset");
|
||||
|
||||
// set the OCULUS_STORE property so the oculus plugin can know if we ran from the Oculus Store
|
||||
static const auto OCULUS_STORE_ARG = "--oculus-store";
|
||||
bool isStore = cmdOptionExists(argc, const_cast<const char**>(argv), OCULUS_STORE_ARG);
|
||||
qApp->setProperty(hifi::properties::OCULUS_STORE, isStore);
|
||||
qApp->setProperty(hifi::properties::OCULUS_STORE, parser.isSet("oculus-store"));
|
||||
|
||||
// emulate standalone device
|
||||
static const auto STANDALONE_ARG = "--standalone";
|
||||
bool isStandalone = cmdOptionExists(argc, const_cast<const char**>(argv), STANDALONE_ARG);
|
||||
qApp->setProperty(hifi::properties::STANDALONE, isStandalone);
|
||||
qApp->setProperty(hifi::properties::STANDALONE, parser.isSet("standalone"));
|
||||
|
||||
// Ignore any previous crashes if running from command line with a test script.
|
||||
bool inTestMode { false };
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
QString parameter(argv[i]);
|
||||
if (parameter == TEST_SCRIPT_COMMAND) {
|
||||
inTestMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool inTestMode = parser.isSet("testScript");
|
||||
|
||||
bool previousSessionCrashed { false };
|
||||
if (!inTestMode) {
|
||||
|
@ -792,10 +748,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
}
|
||||
|
||||
// get dir to use for cache
|
||||
static const auto CACHE_SWITCH = "--cache";
|
||||
QString cacheDir = getCmdOption(argc, const_cast<const char**>(argv), CACHE_SWITCH);
|
||||
if (!cacheDir.isEmpty()) {
|
||||
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
|
||||
if (parser.isSet("cache")) {
|
||||
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, parser.value("cache"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -837,7 +791,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
QCoreApplication::addLibraryPath(audioDLLPath);
|
||||
#endif
|
||||
|
||||
QString defaultScriptsOverrideOption = getCmdOption(argc, constArgv, "--defaultScriptsOverride");
|
||||
QString defaultScriptsOverrideOption = parser.value("defaultScriptsOverride");
|
||||
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
|
||||
|
@ -963,7 +917,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
});
|
||||
|
||||
|
||||
QString setBookmarkValue = getCmdOption(argc, constArgv, "--setBookmark");
|
||||
QString setBookmarkValue = parser.value("setBookmark");
|
||||
if (!setBookmarkValue.isEmpty()) {
|
||||
// Bookmarks are expected to be in a name=url form.
|
||||
// An `=` character in the name or url is unsupported.
|
||||
|
@ -1020,14 +974,19 @@ QSharedPointer<OffscreenUi> getOffscreenUI() {
|
|||
#endif
|
||||
}
|
||||
|
||||
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) :
|
||||
Application::Application(
|
||||
int& argc, char** argv,
|
||||
const QCommandLineParser& parser,
|
||||
QElapsedTimer& startupTimer,
|
||||
bool runningMarkerExisted
|
||||
) :
|
||||
QApplication(argc, argv),
|
||||
_window(new MainWindow(desktop())),
|
||||
_sessionRunTimer(startupTimer),
|
||||
#ifndef Q_OS_ANDROID
|
||||
_logger(new FileLogger(this)),
|
||||
#endif
|
||||
_previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)),
|
||||
_previousSessionCrashed(setupEssentials(argc, argv, parser, runningMarkerExisted)),
|
||||
_entitySimulation(std::make_shared<PhysicalEntitySimulation>()),
|
||||
_physicsEngine(std::make_shared<PhysicsEngine>(Vectors::ZERO)),
|
||||
_entityClipboard(std::make_shared<EntityTree>()),
|
||||
|
@ -1064,12 +1023,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
LogHandler::getInstance().setupRepeatedMessageFlusher();
|
||||
|
||||
{
|
||||
const QStringList args = arguments();
|
||||
|
||||
for (int i = 0; i < args.size() - 1; ++i) {
|
||||
if (args.at(i) == TEST_SCRIPT_COMMAND && (i + 1) < args.size()) {
|
||||
QString testScriptPath = args.at(i + 1);
|
||||
|
||||
if (parser.isSet("testScript")) {
|
||||
QString testScriptPath = parser.value("testScript");
|
||||
// If the URL scheme is http(s) or ftp, then use as is, else - treat it as a local file
|
||||
// This is done so as not break previous command line scripts
|
||||
if (testScriptPath.left(HIFI_URL_SCHEME_HTTP.length()) == HIFI_URL_SCHEME_HTTP ||
|
||||
|
@ -1080,20 +1035,20 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath));
|
||||
}
|
||||
|
||||
// quite when finished parameter must directly follow the test script
|
||||
if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED_OPTION) {
|
||||
if (parser.isSet("quitWhenFinished")) {
|
||||
quitWhenFinished = true;
|
||||
}
|
||||
} else if (args.at(i) == TEST_RESULTS_LOCATION_COMMAND) {
|
||||
// Set test snapshot location only if it is a writeable directory
|
||||
QString path(args.at(i + 1));
|
||||
}
|
||||
if (parser.isSet("testResultsLocation")) {
|
||||
// Set test snapshot location only if it is a writeable directory
|
||||
QString path = parser.value("testResultsLocation");
|
||||
|
||||
QFileInfo fileInfo(path);
|
||||
if (fileInfo.isDir() && fileInfo.isWritable()) {
|
||||
TestScriptingInterface::getInstance()->setTestResultsLocation(path);
|
||||
}
|
||||
QFileInfo fileInfo(path);
|
||||
if (fileInfo.isDir() && fileInfo.isWritable()) {
|
||||
TestScriptingInterface::getInstance()->setTestResultsLocation(path);
|
||||
}
|
||||
}
|
||||
_urlParam = parser.value("url");
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1159,8 +1114,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
addressManager->moveToThread(nodeList->thread());
|
||||
|
||||
const char** constArgv = const_cast<const char**>(argv);
|
||||
if (cmdOptionExists(argc, constArgv, "--disableWatchdog")) {
|
||||
if (parser.isSet("disableWatchdog")) {
|
||||
DISABLE_WATCHDOG = true;
|
||||
}
|
||||
// Set up a watchdog thread to intentionally crash the application on deadlocks
|
||||
|
@ -1383,25 +1337,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
|
||||
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount);
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, [=](){
|
||||
qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode());
|
||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
if (parser.isSet("system-cursor")) {
|
||||
_preferredCursor.set(Cursor::Manager::getIconName(Cursor::Icon::SYSTEM));
|
||||
|
||||
if (displayPlugin->isHmd()) {
|
||||
if (_preferredCursor.get() == Cursor::Manager::getIconName(Cursor::Icon::RETICLE)) {
|
||||
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::RETICLE));
|
||||
}
|
||||
else {
|
||||
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::ARROW));
|
||||
}
|
||||
}
|
||||
else {
|
||||
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::SYSTEM));
|
||||
}
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, [=](){
|
||||
qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode());
|
||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
|
||||
setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString());
|
||||
setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0");
|
||||
});
|
||||
if (displayPlugin->isHmd()) {
|
||||
if (_preferredCursor.get() == Cursor::Manager::getIconName(Cursor::Icon::RETICLE)) {
|
||||
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::RETICLE));
|
||||
} else {
|
||||
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::ARROW));
|
||||
}
|
||||
} else {
|
||||
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::SYSTEM));
|
||||
}
|
||||
|
||||
setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString());
|
||||
setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0");
|
||||
});
|
||||
}
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode);
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, [&](){
|
||||
if (getLoginDialogPoppedUp()) {
|
||||
|
@ -1481,24 +1437,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent);
|
||||
connect(&_entityEditSender, &EntityEditPacketSender::addingEntityWithCertificate, this, &Application::addingEntityWithCertificate);
|
||||
|
||||
QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads");
|
||||
bool success;
|
||||
uint32_t concurrentDownloads = concurrentDownloadsStr.toUInt(&success);
|
||||
if (!success) {
|
||||
concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS;
|
||||
if (parser.isSet("concurrent-downloads")) {
|
||||
bool success;
|
||||
uint32_t concurrentDownloads = parser.value("concurrent-downloads").toUInt(&success);
|
||||
if (!success) {
|
||||
concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS;
|
||||
}
|
||||
ResourceCache::setRequestLimit(concurrentDownloads);
|
||||
}
|
||||
ResourceCache::setRequestLimit(concurrentDownloads);
|
||||
|
||||
// perhaps override the avatar url. Since we will test later for validity
|
||||
// we don't need to do so here.
|
||||
QString avatarURL = getCmdOption(argc, constArgv, "--avatarURL");
|
||||
_avatarOverrideUrl = QUrl::fromUserInput(avatarURL);
|
||||
if (parser.isSet("avatarURL")) {
|
||||
_avatarOverrideUrl = QUrl::fromUserInput(parser.value("avatarURL"));
|
||||
}
|
||||
|
||||
// If someone specifies both --avatarURL and --replaceAvatarURL,
|
||||
// the replaceAvatarURL wins. So only set the _overrideUrl if this
|
||||
// does have a non-empty string.
|
||||
QString replaceURL = getCmdOption(argc, constArgv, "--replaceAvatarURL");
|
||||
if (!replaceURL.isEmpty()) {
|
||||
if (parser.isSet("replaceAvatarURL")) {
|
||||
QString replaceURL = parser.value("replaceAvatarURL");
|
||||
_avatarOverrideUrl = QUrl::fromUserInput(replaceURL);
|
||||
_saveAvatarOverrideUrl = true;
|
||||
}
|
||||
|
@ -1516,9 +1474,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_glWidget->setFocusPolicy(Qt::StrongFocus);
|
||||
_glWidget->setFocus();
|
||||
|
||||
if (cmdOptionExists(argc, constArgv, "--system-cursor")) {
|
||||
_preferredCursor.set(Cursor::Manager::getIconName(Cursor::Icon::SYSTEM));
|
||||
}
|
||||
showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get()));
|
||||
|
||||
// enable mouse tracking; otherwise, we only get drag events
|
||||
|
@ -1585,21 +1540,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
}
|
||||
});
|
||||
|
||||
#if defined(Q_OS_ANDROID) || defined(DISABLE_QML)
|
||||
connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() {
|
||||
#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML)
|
||||
// Do not show login dialog if requested not to on the command line
|
||||
QString hifiNoLoginCommandLineKey = QString("--").append(HIFI_NO_LOGIN_COMMAND_LINE_KEY);
|
||||
int index = arguments().indexOf(hifiNoLoginCommandLineKey);
|
||||
if (index != -1 || _disableLoginScreen) {
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
return;
|
||||
}
|
||||
|
||||
showLoginScreen();
|
||||
#else
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
#endif
|
||||
});
|
||||
#else
|
||||
// Do not show login dialog if requested not to on the command line
|
||||
if (_disableLoginScreen || parser.isSet("no-login-suggestion")) {
|
||||
connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() {
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
});
|
||||
} else {
|
||||
connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() {
|
||||
showLoginScreen();
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initialize the user interface and menu system
|
||||
// Needs to happen AFTER the render engine initialization to access its configuration
|
||||
|
@ -1961,13 +1918,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice());
|
||||
}
|
||||
|
||||
QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
|
||||
_defaultScriptsLocation.setPath(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()));
|
||||
if (parser.isSet("scripts")) {
|
||||
_defaultScriptsLocation.setPath(parser.value("scripts")); // Might need to be done in "main.cpp".
|
||||
_overrideDefaultScriptsLocation = true;
|
||||
} else {
|
||||
_overrideDefaultScriptsLocation = false;
|
||||
}
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
|
||||
loadSettings();
|
||||
loadSettings(parser);
|
||||
|
||||
updateVerboseLogging();
|
||||
|
||||
|
@ -2018,11 +1979,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
|
||||
// If launched from Steam, let it handle updates
|
||||
const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater";
|
||||
bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1;
|
||||
bool buildCanUpdate = BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable
|
||||
|| BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Master;
|
||||
if (!noUpdater && buildCanUpdate) {
|
||||
if (!parser.isSet("no-updater") && buildCanUpdate) {
|
||||
constexpr auto INSTALLER_TYPE_CLIENT_ONLY = "client_only";
|
||||
|
||||
auto applicationUpdater = DependencyManager::set<AutoUpdater>();
|
||||
|
@ -2191,8 +2150,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
||||
|
||||
// setup the stats interval depending on if the 1s faster hearbeat was requested
|
||||
static const QString FAST_STATS_ARG = "--fast-heartbeat";
|
||||
static int SEND_STATS_INTERVAL_MS = arguments().indexOf(FAST_STATS_ARG) != -1 ? 1000 : 10000;
|
||||
static int SEND_STATS_INTERVAL_MS;
|
||||
if (parser.isSet("fast-heartbeat")) {
|
||||
SEND_STATS_INTERVAL_MS = 1000;
|
||||
} else {
|
||||
SEND_STATS_INTERVAL_MS = 10000;
|
||||
}
|
||||
|
||||
static glm::vec3 lastAvatarPosition = myAvatar->getWorldPosition();
|
||||
static glm::mat4 lastHMDHeadPose = getHMDSensorPose();
|
||||
|
@ -4022,16 +3985,11 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
QString addressLookupString;
|
||||
|
||||
// when --url in command line, teleport to location
|
||||
QCommandLineParser parser;
|
||||
QCommandLineOption urlOption("url", "", "value");
|
||||
parser.addOption(urlOption);
|
||||
parser.parse(arguments());
|
||||
if (parser.isSet(urlOption)) {
|
||||
QUrl url = QUrl(parser.value(urlOption));
|
||||
if (url.scheme() == URL_SCHEME_VIRCADIAAPP) {
|
||||
Setting::Handle<QVariant>("startUpApp").set(url.path());
|
||||
if (!_urlParam.isEmpty()) { // Not sure if format supported by isValid().
|
||||
if (_urlParam.scheme() == URL_SCHEME_VIRCADIAAPP) {
|
||||
Setting::Handle<QVariant>("startUpApp").set(_urlParam.path());
|
||||
} else {
|
||||
addressLookupString = url.toString();
|
||||
addressLookupString = _urlParam.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5514,7 +5472,7 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa
|
|||
return exportEntities(filename, entities, ¢er);
|
||||
}
|
||||
|
||||
void Application::loadSettings() {
|
||||
void Application::loadSettings(const QCommandLineParser& parser) {
|
||||
|
||||
sessionRunTime.set(0); // Just clean living. We're about to saveSettings, which will update value.
|
||||
DependencyManager::get<AudioClient>()->loadSettings();
|
||||
|
@ -5544,7 +5502,7 @@ void Application::loadSettings() {
|
|||
}
|
||||
|
||||
bool isFirstPerson = false;
|
||||
if (arguments().contains("--no-launcher")) {
|
||||
if (parser.isSet("no-launcher")) {
|
||||
const auto& displayPlugins = pluginManager->getDisplayPlugins();
|
||||
for (const auto& plugin : displayPlugins) {
|
||||
if (!plugin->isHmd()) {
|
||||
|
@ -5849,7 +5807,7 @@ void Application::resumeAfterLoginDialogActionTaken() {
|
|||
scriptEngines->reloadLocalFiles();
|
||||
|
||||
// if the --scripts command-line argument was used.
|
||||
if (_defaultScriptsLocation.exists() && (arguments().indexOf(QString("--").append(SCRIPTS_SWITCH))) != -1) {
|
||||
if (_overrideDefaultScriptsLocation && _defaultScriptsLocation.exists()) {
|
||||
scriptEngines->loadDefaultScripts();
|
||||
scriptEngines->defaultScriptsLocationOverridden(true);
|
||||
} else {
|
||||
|
@ -5869,7 +5827,7 @@ void Application::resumeAfterLoginDialogActionTaken() {
|
|||
// Set last parameter to exit interface when the test script finishes, if so requested
|
||||
DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
|
||||
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
|
||||
if (arguments().contains("--url")) {
|
||||
if (!_urlParam.isEmpty()) {
|
||||
auto reply = SandboxUtils::getStatus();
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); });
|
||||
}
|
||||
|
@ -8831,31 +8789,21 @@ void Application::sendLambdaEvent(const std::function<void()>& f) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::initPlugins(const QStringList& arguments) {
|
||||
QCommandLineOption display("display", "Preferred displays", "displays");
|
||||
QCommandLineOption disableDisplays("disable-displays", "Displays to disable", "displays");
|
||||
QCommandLineOption disableInputs("disable-inputs", "Inputs to disable", "inputs");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addOption(display);
|
||||
parser.addOption(disableDisplays);
|
||||
parser.addOption(disableInputs);
|
||||
parser.parse(arguments);
|
||||
|
||||
if (parser.isSet(display)) {
|
||||
auto preferredDisplays = parser.value(display).split(',', Qt::SkipEmptyParts);
|
||||
void Application::initPlugins(const QCommandLineParser& parser) {
|
||||
if (parser.isSet("display")) {
|
||||
auto preferredDisplays = parser.value("display").split(',', Qt::SkipEmptyParts);
|
||||
qInfo() << "Setting prefered display plugins:" << preferredDisplays;
|
||||
PluginManager::getInstance()->setPreferredDisplayPlugins(preferredDisplays);
|
||||
}
|
||||
|
||||
if (parser.isSet(disableDisplays)) {
|
||||
auto disabledDisplays = parser.value(disableDisplays).split(',', Qt::SkipEmptyParts);
|
||||
if (parser.isSet("disable-displays")) {
|
||||
auto disabledDisplays = parser.value("disableDisplays").split(',', Qt::SkipEmptyParts);
|
||||
qInfo() << "Disabling following display plugins:" << disabledDisplays;
|
||||
PluginManager::getInstance()->disableDisplays(disabledDisplays);
|
||||
}
|
||||
|
||||
if (parser.isSet(disableInputs)) {
|
||||
auto disabledInputs = parser.value(disableInputs).split(',', Qt::SkipEmptyParts);
|
||||
if (parser.isSet("disable-inputs")) {
|
||||
auto disabledInputs = parser.value("disableInputs").split(',', Qt::SkipEmptyParts);
|
||||
qInfo() << "Disabling following input plugins:" << disabledInputs;
|
||||
PluginManager::getInstance()->disableInputs(disabledInputs);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QCommandLineParser>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QSet>
|
||||
|
@ -96,8 +97,6 @@ namespace controller {
|
|||
|
||||
|
||||
static const QString RUNNING_MARKER_FILENAME = "Interface.running";
|
||||
static const QString SCRIPTS_SWITCH = "scripts";
|
||||
static const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "no-login-suggestion";
|
||||
|
||||
class Application;
|
||||
#if defined(qApp)
|
||||
|
@ -130,10 +129,15 @@ public:
|
|||
virtual DisplayPluginPointer getActiveDisplayPlugin() const override;
|
||||
|
||||
// FIXME? Empty methods, do we still need them?
|
||||
static void initPlugins(const QStringList& arguments);
|
||||
static void initPlugins(const QCommandLineParser& parser);
|
||||
static void shutdownPlugins();
|
||||
|
||||
Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runningMarkerExisted);
|
||||
Application(
|
||||
int& argc, char** argv,
|
||||
const QCommandLineParser& parser,
|
||||
QElapsedTimer& startup_time,
|
||||
bool runningMarkerExisted
|
||||
);
|
||||
~Application();
|
||||
|
||||
void postLambdaEvent(const std::function<void()>& f) override;
|
||||
|
@ -505,7 +509,7 @@ private slots:
|
|||
|
||||
void notifyPacketVersionMismatch();
|
||||
|
||||
void loadSettings();
|
||||
void loadSettings(const QCommandLineParser& parser);
|
||||
void saveSettings() const;
|
||||
void setFailedToConnectToEntityServer();
|
||||
|
||||
|
@ -705,6 +709,8 @@ private:
|
|||
QPointer<LogDialog> _logDialog;
|
||||
QPointer<EntityScriptServerLogDialog> _entityScriptServerLogDialog;
|
||||
QDir _defaultScriptsLocation;
|
||||
// If above is only set by parameter, below is unnecessary.
|
||||
bool _overrideDefaultScriptsLocation;
|
||||
|
||||
TouchEvent _lastTouchEvent;
|
||||
|
||||
|
@ -830,6 +836,8 @@ private:
|
|||
|
||||
bool quitWhenFinished { false };
|
||||
|
||||
QUrl _urlParam;
|
||||
|
||||
bool _showTrackedObjects { false };
|
||||
bool _prevShowTrackedObjects { false };
|
||||
|
||||
|
|
|
@ -64,59 +64,219 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
setupHifiApplication(BuildInfo::INTERFACE_NAME);
|
||||
|
||||
QStringList arguments;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
arguments << argv[i];
|
||||
}
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Overte");
|
||||
QCommandLineOption versionOption = parser.addVersionOption();
|
||||
parser.setApplicationDescription("Overte -- A free/libre and open-source metaverse client");
|
||||
QCommandLineOption helpOption = parser.addHelpOption();
|
||||
QCommandLineOption versionOption = parser.addVersionOption();
|
||||
|
||||
QCommandLineOption urlOption("url", "", "value");
|
||||
QCommandLineOption noLauncherOption("no-launcher", "Do not execute the launcher");
|
||||
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater");
|
||||
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
|
||||
QCommandLineOption runServerOption("runServer", "Whether to run the server");
|
||||
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content <path>", "serverContentPath");
|
||||
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
|
||||
QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache <dir>", "dir");
|
||||
QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts <path>", "path");
|
||||
QCommandLineOption responseTokensOption("tokens", "set response tokens <json>", "json");
|
||||
QCommandLineOption displayNameOption("displayName", "set user display name <string>", "string");
|
||||
QCommandLineOption setBookmarkOption("setBookmark", "set bookmark key=value pair", "string");
|
||||
QCommandLineOption defaultScriptOverrideOption("defaultScriptsOverride", "override defaultsScripts.js", "string");
|
||||
QCommandLineOption forceCrashReportingOption("forceCrashReporting", "Force crash reporting to initialize");
|
||||
QCommandLineOption urlOption(
|
||||
"url",
|
||||
"Start at specified URL location.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption protocolVersionOption(
|
||||
"protocolVersion",
|
||||
"Writes the protocol version base64 signature to a file?",
|
||||
"path"
|
||||
);
|
||||
QCommandLineOption noUpdaterOption(
|
||||
"no-updater",
|
||||
"Do not show auto-updater."
|
||||
);
|
||||
QCommandLineOption checkMinSpecOption(
|
||||
"checkMinSpec",
|
||||
"Check if machine meets minimum specifications. The program will run if check passes."
|
||||
);
|
||||
QCommandLineOption runServerOption(
|
||||
"runServer",
|
||||
"Run the server."
|
||||
);
|
||||
QCommandLineOption listenPortOption(
|
||||
"listenPort",
|
||||
"Port to listen on.",
|
||||
"port_number"
|
||||
);
|
||||
QCommandLineOption serverContentPathOption(
|
||||
"serverContentPath",
|
||||
"Path to find server content.", // What content??
|
||||
"path"
|
||||
);
|
||||
QCommandLineOption overrideAppLocalDataPathOption(
|
||||
"cache",
|
||||
"Set test cache.",
|
||||
"dir"
|
||||
);
|
||||
QCommandLineOption scriptsOption(
|
||||
"scripts",
|
||||
"Set path for defaultScripts. These are probably scripts that run automatically. This parameter does not seem to work.",
|
||||
"dir"
|
||||
);
|
||||
QCommandLineOption allowMultipleInstancesOption(
|
||||
"allowMultipleInstances",
|
||||
"Allow multiple instances to run."
|
||||
);
|
||||
QCommandLineOption displaysOption(
|
||||
"display",
|
||||
"Preferred display.",
|
||||
"displays"
|
||||
);
|
||||
QCommandLineOption disableDisplaysOption(
|
||||
"disable-displays",
|
||||
"Displays to disable.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption disableInputsOption(
|
||||
"disable-inputs",
|
||||
"Inputs to disable.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption suppressSettingsResetOption(
|
||||
"suppress-settings-reset",
|
||||
"Suppress the prompt to reset interface settings."
|
||||
);
|
||||
QCommandLineOption oculusStoreOption(
|
||||
"oculus-store",
|
||||
"Let the Oculus plugin know if interface was run from the Oculus Store."
|
||||
);
|
||||
QCommandLineOption standaloneOption(
|
||||
"standalone",
|
||||
"Emulate a standalone device."
|
||||
);
|
||||
QCommandLineOption disableWatchdogOption(
|
||||
"disableWatchdog",
|
||||
"Disable the watchdog thread. The interface will crash on deadlocks."
|
||||
);
|
||||
QCommandLineOption systemCursorOption(
|
||||
"system-cursor",
|
||||
"Use the default system cursor."
|
||||
);
|
||||
QCommandLineOption concurrentDownloadsOption(
|
||||
"concurrent-downloads",
|
||||
"Maximum concurrent resource downloads. Default is 16, except for Android where it is 4.",
|
||||
"integer"
|
||||
);
|
||||
QCommandLineOption avatarURLOption(
|
||||
"avatarURL",
|
||||
"Override the avatar U.R.L.",
|
||||
"url"
|
||||
);
|
||||
QCommandLineOption replaceAvatarURLOption(
|
||||
"replace-avatar-url",
|
||||
"Replaces the avatar U.R.L. When used with --avatarURL, this takes precedence.",
|
||||
"url"
|
||||
);
|
||||
QCommandLineOption setBookmarkOption(
|
||||
"setBookmark",
|
||||
"Set bookmark as key=value pair. Including the '=' symbol in either string is unsupported.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption forceCrashReportingOption(
|
||||
"forceCrashReporting",
|
||||
"Force crash reporting to initialize."
|
||||
);
|
||||
// The documented "--disable-lod" does not seem to exist.
|
||||
// Below are undocumented.
|
||||
QCommandLineOption noLauncherOption(
|
||||
"no-launcher",
|
||||
"Supposedly does something for the server, unrelated to the application launcher. The feature may never have been implemented."
|
||||
);
|
||||
QCommandLineOption overrideScriptsPathOption(
|
||||
"overrideScriptsPath",
|
||||
"Specifies path to default directory where the application will look for scripts to load.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption defaultScriptsOverrideOption(
|
||||
"defaultScriptsOverride",
|
||||
"Override default script to run automatically on start. Default is \"defaultsScripts.js\".",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption responseTokensOption(
|
||||
"tokens",
|
||||
"Set response tokens <json>.",
|
||||
"json"
|
||||
);
|
||||
QCommandLineOption displayNameOption(
|
||||
"displayName",
|
||||
"Set user display name <string>.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption noLoginOption(
|
||||
"no-login-suggestion",
|
||||
"Do not show log-in dialogue."
|
||||
);
|
||||
QCommandLineOption traceFileOption(
|
||||
"traceFile",
|
||||
"Writes a trace to a file in the documents folder. Only works if \"--traceDuration\" is specified.",
|
||||
"path"
|
||||
);
|
||||
QCommandLineOption traceDurationOption(
|
||||
"traceDuration",
|
||||
"Automatically quit interface after duration. Only works if \"--traceFile\" is specified.",
|
||||
"seconds"
|
||||
);
|
||||
QCommandLineOption clockSkewOption(
|
||||
"clockSkew",
|
||||
"Forces client instance's clock to skew for demonstration purposes.",
|
||||
"integer"
|
||||
); // This should probably be removed.
|
||||
QCommandLineOption testScriptOption(
|
||||
"testScript",
|
||||
"Undocumented. Accepts parameter as U.R.L.",
|
||||
"string"
|
||||
);
|
||||
QCommandLineOption testResultsLocationOption(
|
||||
"testResultsLocation",
|
||||
"Undocumented",
|
||||
"path"
|
||||
);
|
||||
QCommandLineOption quitWhenFinishedOption(
|
||||
"quitWhenFinished",
|
||||
"Only works if \"--testScript\" is provided."
|
||||
); // Should probably also be made to work on testResultsLocationOption.
|
||||
QCommandLineOption fastHeartbeatOption(
|
||||
"fast-heartbeat",
|
||||
"Change stats polling interval from 10000ms to 1000ms."
|
||||
);
|
||||
// "--qmljsdebugger", which appears in output from "--help-all".
|
||||
// Those below don't seem to be optional.
|
||||
// --ignore-gpu-blacklist
|
||||
// --suppress-settings-reset
|
||||
|
||||
parser.addOption(urlOption);
|
||||
parser.addOption(noLauncherOption);
|
||||
parser.addOption(protocolVersionOption);
|
||||
parser.addOption(noUpdaterOption);
|
||||
parser.addOption(checkMinSpecOption);
|
||||
parser.addOption(runServerOption);
|
||||
parser.addOption(listenPortOption);
|
||||
parser.addOption(serverContentPathOption);
|
||||
parser.addOption(overrideAppLocalDataPathOption);
|
||||
parser.addOption(overrideScriptsPathOption);
|
||||
parser.addOption(scriptsOption);
|
||||
parser.addOption(allowMultipleInstancesOption);
|
||||
parser.addOption(displaysOption);
|
||||
parser.addOption(disableDisplaysOption);
|
||||
parser.addOption(disableInputsOption);
|
||||
parser.addOption(suppressSettingsResetOption);
|
||||
parser.addOption(oculusStoreOption);
|
||||
parser.addOption(standaloneOption);
|
||||
parser.addOption(disableWatchdogOption);
|
||||
parser.addOption(systemCursorOption);
|
||||
parser.addOption(concurrentDownloadsOption);
|
||||
parser.addOption(avatarURLOption);
|
||||
parser.addOption(replaceAvatarURLOption);
|
||||
parser.addOption(setBookmarkOption);
|
||||
parser.addOption(forceCrashReportingOption);
|
||||
parser.addOption(noLauncherOption);
|
||||
parser.addOption(responseTokensOption);
|
||||
parser.addOption(displayNameOption);
|
||||
parser.addOption(setBookmarkOption);
|
||||
parser.addOption(defaultScriptOverrideOption);
|
||||
parser.addOption(forceCrashReportingOption);
|
||||
|
||||
if (!parser.parse(arguments)) {
|
||||
std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam
|
||||
}
|
||||
|
||||
if (parser.isSet(versionOption)) {
|
||||
parser.showVersion();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
if (parser.isSet(helpOption)) {
|
||||
QCoreApplication mockApp(argc, const_cast<char**>(argv)); // required for call to showHelp()
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
parser.addOption(overrideScriptsPathOption);
|
||||
parser.addOption(defaultScriptsOverrideOption);
|
||||
parser.addOption(traceFileOption);
|
||||
parser.addOption(traceDurationOption);
|
||||
parser.addOption(clockSkewOption);
|
||||
parser.addOption(testScriptOption);
|
||||
parser.addOption(testResultsLocationOption);
|
||||
parser.addOption(quitWhenFinishedOption);
|
||||
parser.addOption(fastHeartbeatOption);
|
||||
|
||||
QString applicationPath;
|
||||
// A temporary application instance is needed to get the location of the running executable
|
||||
|
@ -125,6 +285,9 @@ int main(int argc, const char* argv[]) {
|
|||
// cross-platform implementation.
|
||||
{
|
||||
QCoreApplication tempApp(argc, const_cast<char**>(argv));
|
||||
|
||||
parser.process(QCoreApplication::arguments()); // Must be run after QCoreApplication is initalised.
|
||||
|
||||
#ifdef Q_OS_OSX
|
||||
if (QFileInfo::exists(QCoreApplication::applicationDirPath() + "/../../../config.json")) {
|
||||
applicationPath = QCoreApplication::applicationDirPath() + "/../../../";
|
||||
|
@ -135,6 +298,29 @@ int main(int argc, const char* argv[]) {
|
|||
applicationPath = QCoreApplication::applicationDirPath();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Act on arguments for early termination.
|
||||
if (parser.isSet(versionOption)) {
|
||||
parser.showVersion();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
if (parser.isSet(helpOption)) {
|
||||
QCoreApplication mockApp(argc, const_cast<char**>(argv)); // required for call to showHelp()
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
if (parser.isSet(protocolVersionOption)) {
|
||||
FILE* fp = fopen(parser.value(protocolVersionOption).toStdString().c_str(), "w");
|
||||
if (fp) {
|
||||
fputs(protocolVersionsSignatureBase64().toStdString().c_str(), fp);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
} else {
|
||||
qWarning() << "Failed to open file specified for --protocolVersion.";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const QString APPLICATION_CONFIG_FILENAME = "config.json";
|
||||
QDir applicationDir(applicationPath);
|
||||
QString configFileName = applicationDir.filePath(APPLICATION_CONFIG_FILENAME);
|
||||
|
@ -173,20 +359,17 @@ int main(int argc, const char* argv[]) {
|
|||
// Early check for --traceFile argument
|
||||
auto tracer = DependencyManager::set<tracing::Tracer>();
|
||||
const char * traceFile = nullptr;
|
||||
const QString traceFileFlag("--traceFile");
|
||||
float traceDuration = 0.0f;
|
||||
for (int a = 1; a < argc; ++a) {
|
||||
if (traceFileFlag == argv[a] && argc > a + 1) {
|
||||
traceFile = argv[a + 1];
|
||||
if (argc > a + 2) {
|
||||
traceDuration = atof(argv[a + 2]);
|
||||
}
|
||||
break;
|
||||
if (parser.isSet(traceFileOption)) {
|
||||
traceFile = parser.value(traceFileOption).toStdString().c_str();
|
||||
if (parser.isSet(traceDurationOption)) {
|
||||
traceDuration = parser.value(traceDurationOption).toFloat();
|
||||
tracer->startTracing();
|
||||
} else {
|
||||
qWarning() << "\"--traceDuration\" must be specified along with \"--traceFile\"...";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (traceFile != nullptr) {
|
||||
tracer->startTracing();
|
||||
}
|
||||
|
||||
PROFILE_SYNC_BEGIN(startup, "main startup", "");
|
||||
|
||||
|
@ -242,7 +425,7 @@ int main(int argc, const char* argv[]) {
|
|||
instanceMightBeRunning = false;
|
||||
}
|
||||
// this needs to be done here in main, as the mechanism for setting the
|
||||
// scripts directory appears not to work. See the bug report
|
||||
// scripts directory appears not to work. See the bug report (dead link)
|
||||
// https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine
|
||||
if (parser.isSet(overrideScriptsPathOption)) {
|
||||
QDir scriptsPath(parser.value(overrideScriptsPathOption));
|
||||
|
@ -317,18 +500,17 @@ int main(int argc, const char* argv[]) {
|
|||
// Debug option to demonstrate that the client's local time does not
|
||||
// need to be in sync with any other network node. This forces clock
|
||||
// skew for the individual client
|
||||
const char* CLOCK_SKEW = "--clockSkew";
|
||||
const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
|
||||
if (clockSkewOption) {
|
||||
qint64 clockSkew = atoll(clockSkewOption);
|
||||
if (parser.isSet(clockSkewOption)) {
|
||||
const char* clockSkewValue = parser.value(clockSkewOption).toStdString().c_str();
|
||||
qint64 clockSkew = atoll(clockSkewValue);
|
||||
usecTimestampNowForceClockSkew(clockSkew);
|
||||
qCDebug(interfaceapp) << "clockSkewOption=" << clockSkewOption << "clockSkew=" << clockSkew;
|
||||
qCDebug(interfaceapp) << "clockSkewOption=" << clockSkewValue << "clockSkew=" << clockSkew;
|
||||
}
|
||||
|
||||
// Oculus initialization MUST PRECEDE OpenGL context creation.
|
||||
// The nature of the Application constructor means this has to be either here,
|
||||
// or in the main window ctor, before GL startup.
|
||||
Application::initPlugins(arguments);
|
||||
Application::initPlugins(parser);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// If we're running in steam mode, we need to do an explicit check to ensure we're up to the required min spec
|
||||
|
@ -376,7 +558,7 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
PROFILE_SYNC_END(startup, "main startup", "");
|
||||
PROFILE_SYNC_BEGIN(startup, "app full ctor", "");
|
||||
Application app(argcExtended, const_cast<char**>(argvExtended.data()), startupTime, runningMarkerExisted);
|
||||
Application app(argcExtended, const_cast<char**>(argvExtended.data()), parser, startupTime, runningMarkerExisted);
|
||||
PROFILE_SYNC_END(startup, "app full ctor", "");
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
|
|
Loading…
Reference in a new issue