Compare commits
5 Commits
spacecruft
...
command-li
Author | SHA1 | Date |
---|---|---|
Hleb Valoshka | cd32920fbd | |
Hleb Valoshka | 5c55b17caa | |
Hleb Valoshka | c4e426d70b | |
Hleb Valoshka | 803afffce6 | |
Hleb Valoshka | bfacc111a4 |
|
@ -5,6 +5,7 @@
|
|||
#include <celutil/winutil.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// M$VC++ build without C++ exceptions are not supported yet
|
||||
|
@ -594,5 +595,66 @@ bool create_directory(const path& p)
|
|||
return r;
|
||||
}
|
||||
|
||||
path current_path()
|
||||
{
|
||||
std::error_code ec;
|
||||
path p = current_path(ec);
|
||||
|
||||
if (ec)
|
||||
#if __cpp_exceptions
|
||||
throw filesystem_error(ec, "celfs::current_path error");
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
path current_path(std::error_code& ec)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::wstring buffer(MAX_PATH + 1, 0);
|
||||
DWORD r = GetModuleFileNameW(nullptr, &buffer[0], MAX_PATH);
|
||||
if (r == 0)
|
||||
{
|
||||
ec = std::error_code(errno, std::system_category());
|
||||
return path();
|
||||
}
|
||||
auto pos = buffer.find_last_of(L"\\/");
|
||||
return buffer.substr(0, pos);
|
||||
#else
|
||||
std::string buffer(256, 0);
|
||||
char *r = getcwd(&buffer[0], buffer.size());
|
||||
if (r == nullptr)
|
||||
{
|
||||
ec = std::error_code(errno, std::system_category());
|
||||
return path();
|
||||
}
|
||||
return buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
void current_path(const path& p)
|
||||
{
|
||||
std::error_code ec;
|
||||
current_path(p, ec);
|
||||
if (ec)
|
||||
#if __cpp_exceptions
|
||||
throw filesystem_error(ec, "celfs::current_path error");
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void current_path(const path& p, std::error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _WIN32
|
||||
BOOL ret = SetCurrentDirectoryW(p.c_str());
|
||||
if (!ret)
|
||||
ec = std::error_code(errno, std::system_category());
|
||||
#else
|
||||
int ret = chdir(p.c_str());
|
||||
if (ret != 0)
|
||||
ec = std::error_code(errno, std::system_category());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -470,5 +470,10 @@ bool is_directory(const path& p, std::error_code& ec) noexcept;
|
|||
|
||||
bool create_directory(const path& p);
|
||||
bool create_directory(const path& p, std::error_code& ec) noexcept;
|
||||
|
||||
path current_path();
|
||||
path current_path(std::error_code& ec);
|
||||
void current_path(const path& p);
|
||||
void current_path(const path& p, std::error_code& ec) noexcept;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,8 +86,10 @@ std::ofstream hdrlog;
|
|||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#include <malloc.h>
|
||||
#ifndef alloca
|
||||
#define alloca(s) _alloca(s)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace cmod;
|
||||
using namespace Eigen;
|
||||
|
|
|
@ -131,7 +131,7 @@ void VertexObject::enableAttribArrays() noexcept
|
|||
auto n = t.first;
|
||||
auto& p = t.second;
|
||||
glEnableVertexAttribArray(n);
|
||||
glVertexAttribPointer(n, p.count, p.type, p.normalized, p.stride, (GLvoid*) p.offset);
|
||||
glVertexAttribPointer(n, p.count, p.type, p.normalized, p.stride, (GLvoid*) (size_t) p.offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1916,6 +1916,10 @@ void CelestiaCore::setStartURL(const string &url)
|
|||
}
|
||||
}
|
||||
|
||||
std::string_view CelestiaCore::getStartURL() const
|
||||
{
|
||||
return startURL;
|
||||
}
|
||||
|
||||
void CelestiaCore::tick()
|
||||
{
|
||||
|
@ -3680,13 +3684,15 @@ using StarLoader = CatalogLoader<StarDatabase>;
|
|||
using DeepSkyLoader = CatalogLoader<DSODatabase>;
|
||||
|
||||
|
||||
bool CelestiaCore::initSimulation(const fs::path& configFileName,
|
||||
const vector<fs::path>& extrasDirs,
|
||||
ProgressNotifier* progressNotifier)
|
||||
bool CelestiaCore::initSimulation(ProgressNotifier* progressNotifier)
|
||||
{
|
||||
if (!configFileName.empty())
|
||||
initDataPath();
|
||||
std::error_code ec;
|
||||
fs::current_path(m_dataPath, ec);
|
||||
|
||||
if (!m_configFileName.empty())
|
||||
{
|
||||
config = ReadCelestiaConfig(configFileName);
|
||||
config = ReadCelestiaConfig(m_configFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3723,12 +3729,12 @@ bool CelestiaCore::initSimulation(const fs::path& configFileName,
|
|||
// after the ones from the config file and the order in which they were
|
||||
// specified is preserved. This process in O(N*M), but the number of
|
||||
// additional extras directories should be small.
|
||||
for (const auto& dir : extrasDirs)
|
||||
for (const auto& dir : m_extrasDirs)
|
||||
{
|
||||
if (find(config->extrasDirs.begin(), config->extrasDirs.end(), dir.string()) ==
|
||||
if (find(config->extrasDirs.begin(), config->extrasDirs.end(), dir) ==
|
||||
config->extrasDirs.end())
|
||||
{
|
||||
config->extrasDirs.push_back(dir.string());
|
||||
config->extrasDirs.push_back(dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4764,7 +4770,7 @@ bool CelestiaCore::saveScreenShot(const fs::path& filename, ContentType type) co
|
|||
return false;
|
||||
}
|
||||
|
||||
void CelestiaCore::setLogFile(fs::path &fn)
|
||||
void CelestiaCore::setLogFile(const fs::path &fn)
|
||||
{
|
||||
m_logfile = std::ofstream(fn.string());
|
||||
if (m_logfile.good())
|
||||
|
@ -4779,6 +4785,39 @@ void CelestiaCore::setLogFile(fs::path &fn)
|
|||
}
|
||||
}
|
||||
|
||||
bool CelestiaCore::initDataPath()
|
||||
{
|
||||
// was set using command line
|
||||
if (!m_dataPath.empty())
|
||||
return true;
|
||||
|
||||
#ifdef _WIN32
|
||||
const wchar_t *d = _wgetenv(L"CELESTIA_DATA_DIR");
|
||||
#else
|
||||
const char *d = getenv("CELESTIA_DATA_DIR");
|
||||
#endif
|
||||
if (d != nullptr)
|
||||
{
|
||||
m_dataPath = fs::path(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef NATIVE_OSX_APP
|
||||
// On macOS data directory is in a fixed position relative to the
|
||||
// application bundle
|
||||
error_code ec;
|
||||
auto curDir = fs::current_path(ec);
|
||||
if (ec != error_code())
|
||||
return false;
|
||||
assert(curDir.is_absolute());
|
||||
m_dataPath = curDir.parent_path() / "Resources";
|
||||
#else
|
||||
m_dataPath = fs::path(CONFIG_DATA_DIR);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
auto CelestiaCore::getSupportedMovieSizes() const
|
||||
-> celestia::util::array_view<MovieSize>
|
||||
|
@ -4800,9 +4839,9 @@ auto CelestiaCore::getSupportedMovieSizes() const
|
|||
auto CelestiaCore::getSupportedMovieFramerates() const
|
||||
-> celestia::util::array_view<float>
|
||||
{
|
||||
static std::array<float, 5> MovieFramerates =
|
||||
static std::array<float, 6> MovieFramerates =
|
||||
{
|
||||
15.0f, 24.0f, 25.0f, 29.97f, 30.0f
|
||||
15.0f, 24.0f, 25.0f, 29.97f, 30.0f, 60.0f
|
||||
};
|
||||
return MovieFramerates;
|
||||
}
|
||||
|
@ -4818,3 +4857,30 @@ auto CelestiaCore::getSupportedMovieCodecs() const
|
|||
return MovieCodecs;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void CommandLineError(const char *message)
|
||||
{
|
||||
cout << message << '\n';
|
||||
}
|
||||
|
||||
util::CmdLineParser CelestiaCore::getCommandLineParser()
|
||||
{
|
||||
util::CmdLineParser parser;
|
||||
parser.on("conf", 'c', true,
|
||||
_("Configuration file name expected after --conf/-c"),
|
||||
[this](const char *v) { m_configFileName = v; return true; });
|
||||
parser.on("dir", 'd', true,
|
||||
_("Directory expected after --dir/-d"),
|
||||
[this](const char *v) { m_dataPath = v; return true; });
|
||||
parser.on("extrasdir", 'e', true,
|
||||
_("Directory expected after --extrasdir/-e"),
|
||||
[this](const char *v) { m_extrasDirs.push_back(v); return true; });
|
||||
parser.on("url", 'u', true,
|
||||
_("URL expected after --url/-u"),
|
||||
[this](const char *v) { setStartURL(v); return true; });
|
||||
parser.on("log", 'l', true,
|
||||
_("A filename expected after --log/-l"),
|
||||
[this](const char *v) { setLogFile(v); return true; });
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
|
|
@ -13,10 +13,14 @@
|
|||
#include <fstream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <celutil/array_view.h>
|
||||
#include <celutil/cmdline.h>
|
||||
#include <celutil/filetype.h>
|
||||
#include <celutil/tee.h>
|
||||
#include <celutil/timer.h>
|
||||
#include <celutil/watcher.h>
|
||||
// #include <celutil/watchable.h>
|
||||
#include <celcompat/string_view.h>
|
||||
#include <celengine/solarsys.h>
|
||||
#include <celengine/overlay.h>
|
||||
#include <celengine/texture.h>
|
||||
|
@ -25,7 +29,6 @@
|
|||
#include <celengine/simulation.h>
|
||||
#include <celengine/overlayimage.h>
|
||||
#include <celengine/viewporteffect.h>
|
||||
#include <celutil/tee.h>
|
||||
#include "configfile.h"
|
||||
#include "favorites.h"
|
||||
#include "destination.h"
|
||||
|
@ -195,9 +198,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
CelestiaCore();
|
||||
~CelestiaCore();
|
||||
|
||||
bool initSimulation(const fs::path& configFileName = fs::path(),
|
||||
const std::vector<fs::path>& extrasDirs = {},
|
||||
ProgressNotifier* progressNotifier = nullptr);
|
||||
bool initSimulation(ProgressNotifier* progressNotifier = nullptr);
|
||||
bool initRenderer();
|
||||
void start(double t);
|
||||
void start();
|
||||
|
@ -206,6 +207,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
|
||||
// URLs and history navigation
|
||||
void setStartURL(const std::string& url);
|
||||
std::string_view getStartURL() const;
|
||||
bool goToUrl(const std::string& urlStr);
|
||||
void addToHistory();
|
||||
void back();
|
||||
|
@ -322,12 +324,12 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
|
||||
void notifyWatchers(int);
|
||||
|
||||
void setLogFile(fs::path&);
|
||||
void setLogFile(const fs::path&);
|
||||
|
||||
class Alerter
|
||||
{
|
||||
public:
|
||||
virtual ~Alerter() {};
|
||||
virtual ~Alerter() = default;
|
||||
virtual void fatalError(const std::string&) = 0;
|
||||
};
|
||||
|
||||
|
@ -337,7 +339,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
class CursorHandler
|
||||
{
|
||||
public:
|
||||
virtual ~CursorHandler() {};
|
||||
virtual ~CursorHandler() = default;
|
||||
virtual void setCursorShape(CursorShape) = 0;
|
||||
virtual CursorShape getCursorShape() const = 0;
|
||||
};
|
||||
|
@ -389,6 +391,8 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
Image captureImage() const;
|
||||
bool saveScreenShot(const fs::path&, ContentType = Content_Unknown) const;
|
||||
|
||||
celestia::util::CmdLineParser getCommandLineParser();
|
||||
|
||||
protected:
|
||||
bool readStars(const CelestiaConfig&, ProgressNotifier*);
|
||||
void renderOverlay();
|
||||
|
@ -397,6 +401,8 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
#endif // CELX
|
||||
|
||||
private:
|
||||
bool initDataPath();
|
||||
|
||||
CelestiaConfig* config{ nullptr };
|
||||
|
||||
Universe* universe{ nullptr };
|
||||
|
@ -538,6 +544,12 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
std::ofstream m_logfile;
|
||||
teestream m_tee;
|
||||
|
||||
// options passed through command line
|
||||
fs::path m_dataPath;
|
||||
fs::path m_configFileName;
|
||||
fs::path m_logFilename;
|
||||
std::vector<fs::path> m_extrasDirs;
|
||||
|
||||
#ifdef CELX
|
||||
friend View* getViewByObserver(CelestiaCore*, Observer*);
|
||||
friend void getObservers(CelestiaCore*, std::vector<Observer*>&);
|
||||
|
|
|
@ -75,24 +75,9 @@ static void initRealize(GtkWidget* widget, AppData* app);
|
|||
|
||||
|
||||
/* Command-Line Options */
|
||||
static gchar* configFile = NULL;
|
||||
static gchar* installDir = NULL;
|
||||
static gchar** extrasDir = NULL;
|
||||
static gboolean fullScreen = FALSE;
|
||||
static gboolean noSplash = FALSE;
|
||||
|
||||
/* Command-Line Options specification */
|
||||
static GOptionEntry optionEntries[] =
|
||||
{
|
||||
{ "conf", 'c', 0, G_OPTION_ARG_FILENAME, &configFile, "Alternate configuration file", "file" },
|
||||
{ "dir", 'd', 0, G_OPTION_ARG_FILENAME, &installDir, "Alternate installation directory", "directory" },
|
||||
{ "extrasdir", 'e', 0, G_OPTION_ARG_FILENAME_ARRAY, &extrasDir, "Additional \"extras\" directory", "directory" },
|
||||
{ "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullScreen, "Start full-screen", NULL },
|
||||
{ "nosplash", 's', 0, G_OPTION_ARG_NONE, &noSplash, "Disable splash screen", NULL },
|
||||
{ NULL, '\0', 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* Initializes GtkActions and creates main menu */
|
||||
static void createMainMenu(GtkWidget* window, AppData* app)
|
||||
{
|
||||
|
@ -339,34 +324,6 @@ int main(int argc, char* argv[])
|
|||
/* Watcher enables sending signals from inside of core */
|
||||
GtkWatcher* gtkWatcher;
|
||||
|
||||
/* Command line option parsing */
|
||||
GError *error = NULL;
|
||||
GOptionContext* context = g_option_context_new("");
|
||||
g_option_context_add_main_entries(context, optionEntries, NULL);
|
||||
g_option_context_add_group(context, gtk_get_option_group(TRUE));
|
||||
g_option_context_parse(context, &argc, &argv, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_print("Error in command line options. Use --help for full list.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* At this point, the argument count should be 1 or 2, with the lastX
|
||||
* potentially being a cel:// URL. */
|
||||
|
||||
/* If there's an argument left, assume it's a URL. This happens here
|
||||
* because it's after the saved prefs are applied. The appCore gets
|
||||
* initialized elsewhere. */
|
||||
if (argc > 1)
|
||||
app->startURL = argv[argc - 1];
|
||||
|
||||
if (installDir == NULL)
|
||||
installDir = (gchar*)CONFIG_DATA_DIR;
|
||||
|
||||
if (chdir(installDir) == -1)
|
||||
cerr << "Cannot chdir to '" << installDir << "', probably due to improper installation.\n";
|
||||
|
||||
#ifdef GNOME
|
||||
/* GNOME Initialization */
|
||||
GnomeProgram *program;
|
||||
|
@ -384,34 +341,20 @@ int main(int argc, char* argv[])
|
|||
SetDebugVerbosity(0);
|
||||
|
||||
app->core = new CelestiaCore();
|
||||
if (app->core == NULL)
|
||||
{
|
||||
cerr << "Failed to initialize Celestia core.\n";
|
||||
return 1;
|
||||
}
|
||||
auto parser = app->core->getCommandLineParser();
|
||||
parser.on("fullscreen", 'f', false,
|
||||
_("Start full-screen"),
|
||||
[](bool) { fullScreen = TRUE; });
|
||||
parser.on("nosplash", 's', false,
|
||||
_("Disable splash screen"),
|
||||
[](bool) { noSplash = TRUE; });
|
||||
parser.parse(argc, argv);
|
||||
|
||||
app->renderer = app->core->getRenderer();
|
||||
g_assert(app->renderer);
|
||||
|
||||
/* Parse simulation arguments */
|
||||
string altConfig;
|
||||
if (configFile != NULL)
|
||||
altConfig = string(configFile);
|
||||
|
||||
vector<fs::path> configDirs;
|
||||
if (extrasDir != NULL)
|
||||
{
|
||||
/* Add each extrasDir to the vector */
|
||||
int i = 0;
|
||||
while (extrasDir[i] != NULL)
|
||||
{
|
||||
configDirs.push_back(extrasDir[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the simulation */
|
||||
if (!app->core->initSimulation(altConfig, configDirs, ss->notifier))
|
||||
if (!app->core->initSimulation(ss->notifier))
|
||||
return 1;
|
||||
|
||||
app->simulation = app->core->getSimulation();
|
||||
|
|
|
@ -187,43 +187,12 @@ CelestiaAppWindow::~CelestiaAppWindow()
|
|||
}
|
||||
|
||||
|
||||
void CelestiaAppWindow::init(const QString& qConfigFileName,
|
||||
const QStringList& qExtrasDirectories,
|
||||
const QString& logFilename)
|
||||
void CelestiaAppWindow::init(int argc, char *argv[])
|
||||
{
|
||||
QString celestia_data_dir = QString::fromLocal8Bit(::getenv("CELESTIA_DATA_DIR"));
|
||||
|
||||
if (celestia_data_dir.isEmpty()) {
|
||||
#ifdef NATIVE_OSX_APP
|
||||
// On macOS data directory is in a fixed position relative to the application bundle
|
||||
QString dataDir = QApplication::applicationDirPath() + "/../Resources";
|
||||
#else
|
||||
QString dataDir = CONFIG_DATA_DIR;
|
||||
#endif
|
||||
QString celestia_data_dir = dataDir;
|
||||
QDir::setCurrent(celestia_data_dir);
|
||||
} else if (QDir(celestia_data_dir).isReadable()) {
|
||||
QDir::setCurrent(celestia_data_dir);
|
||||
} else {
|
||||
QMessageBox::critical(0, "Celestia",
|
||||
_("Celestia is unable to run because the data directory was not "
|
||||
"found, probably due to improper installation."));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Get the config file name
|
||||
string configFileName;
|
||||
if (!qConfigFileName.isEmpty())
|
||||
configFileName = qConfigFileName.toStdString();
|
||||
|
||||
// Translate extras directories from QString -> std::string
|
||||
vector<fs::path> extrasDirectories;
|
||||
for (const auto& dir : qExtrasDirectories)
|
||||
extrasDirectories.push_back(dir.toUtf8().data());
|
||||
|
||||
initAppDataDirectory();
|
||||
|
||||
m_appCore = new CelestiaCore();
|
||||
m_appCore->getCommandLineParser().parse(argc, argv);
|
||||
|
||||
auto* progress = new AppProgressNotifier(this);
|
||||
alerter = new AppAlerter(this);
|
||||
|
@ -231,15 +200,7 @@ void CelestiaAppWindow::init(const QString& qConfigFileName,
|
|||
|
||||
setWindowIcon(QIcon(":/icons/celestia.png"));
|
||||
|
||||
if (!logFilename.isEmpty())
|
||||
{
|
||||
fs::path fn(logFilename.toStdString());
|
||||
m_appCore->setLogFile(fn);
|
||||
}
|
||||
|
||||
if (!m_appCore->initSimulation(configFileName,
|
||||
extrasDirectories,
|
||||
progress))
|
||||
if (!m_appCore->initSimulation(progress))
|
||||
{
|
||||
// Error message is shown by celestiacore so we silently exit here.
|
||||
exit(1);
|
||||
|
|
|
@ -40,9 +40,7 @@ class CelestiaAppWindow : public QMainWindow, public CelestiaCore::ContextMenuHa
|
|||
CelestiaAppWindow(QWidget* parent = nullptr);
|
||||
~CelestiaAppWindow();
|
||||
|
||||
void init(const QString& configFileName,
|
||||
const QStringList& extrasDirectories,
|
||||
const QString& logFilename);
|
||||
void init(int argc, char *argv[]);
|
||||
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
|
|
|
@ -33,22 +33,6 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
//static const char *description = "Celestia";
|
||||
|
||||
// Command line options
|
||||
static bool startFullscreen = false;
|
||||
static bool runOnce = false;
|
||||
static QString startURL;
|
||||
static QString logFilename;
|
||||
static QString startDirectory;
|
||||
static QString startScript;
|
||||
static QStringList extrasDirectories;
|
||||
static QString configFileName;
|
||||
static bool useAlternateConfigFile = false;
|
||||
static bool skipSplashScreen = false;
|
||||
|
||||
static bool ParseCommandLine();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifndef GL_ES
|
||||
|
@ -71,8 +55,6 @@ int main(int argc, char *argv[])
|
|||
QCoreApplication::setOrganizationName("Celestia Development Team");
|
||||
QCoreApplication::setApplicationName("Celestia QT");
|
||||
|
||||
ParseCommandLine();
|
||||
|
||||
#ifdef NATIVE_OSX_APP
|
||||
// On macOS data directory is in a fixed position relative to the application bundle
|
||||
QDir splashDir(QApplication::applicationDirPath() + "/../Resources/splash");
|
||||
|
@ -112,7 +94,7 @@ int main(int argc, char *argv[])
|
|||
QObject::connect(&window, SIGNAL(progressUpdate(const QString&, int, const QColor&)),
|
||||
&splash, SLOT(showMessage(const QString&, int, const QColor&)));
|
||||
|
||||
window.init(configFileName, extrasDirectories, logFilename);
|
||||
window.init(argc, argv);
|
||||
window.show();
|
||||
|
||||
splash.finish(&window);
|
||||
|
@ -122,103 +104,3 @@ int main(int argc, char *argv[])
|
|||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CommandLineError(const char* /*unused*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ParseCommandLine()
|
||||
{
|
||||
QStringList args = QCoreApplication::arguments();
|
||||
|
||||
int i = 1;
|
||||
|
||||
while (i < args.size())
|
||||
{
|
||||
bool isLastArg = (i == args.size() - 1);
|
||||
#if 0
|
||||
if (strcmp(argv[i], "--verbose") == 0)
|
||||
{
|
||||
SetDebugVerbosity(1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (args.at(i) == "--fullscreen")
|
||||
{
|
||||
startFullscreen = true;
|
||||
}
|
||||
else if (args.at(i) == "--once")
|
||||
{
|
||||
runOnce = true;
|
||||
}
|
||||
else if (args.at(i) == "--dir")
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
CommandLineError(_("Directory expected after --dir"));
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
startDirectory = args.at(i);
|
||||
}
|
||||
else if (args.at(i) == "--conf")
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
CommandLineError(_("Configuration file name expected after --conf"));
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
configFileName = args.at(i);
|
||||
useAlternateConfigFile = true;
|
||||
}
|
||||
else if (args.at(i) == "--extrasdir")
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
CommandLineError(_("Directory expected after --extrasdir"));
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
extrasDirectories.push_back(args.at(i));
|
||||
}
|
||||
else if (args.at(i) == "-u" || args.at(i) == "--url")
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
CommandLineError(_("URL expected after --url"));
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
startURL = args.at(i);
|
||||
}
|
||||
else if (args.at(i) == "-s" || args.at(i) == "--nosplash")
|
||||
{
|
||||
skipSplashScreen = true;
|
||||
}
|
||||
else if (args.at(i) == "-l" || args.at(i) == "--log")
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
CommandLineError(_("A filename expected after --log/-l"));
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
logFilename = args.at(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
string buf = fmt::sprintf(_("Invalid command line option '%s'"), args.at(i).toUtf8().data());
|
||||
CommandLineError(buf.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,11 @@ typedef vector<IntStrPair> IntStrPairVec;
|
|||
|
||||
char AppName[] = "Celestia";
|
||||
|
||||
// command line options
|
||||
static bool startFullscreen = false;
|
||||
static bool runOnce = false;
|
||||
static bool skipSplashScreen = false;
|
||||
|
||||
static CelestiaCore* appCore = NULL;
|
||||
|
||||
// Display modes for full screen operation
|
||||
|
@ -2997,110 +3002,6 @@ static char** splitCommandLine(LPSTR cmdLine,
|
|||
}
|
||||
|
||||
|
||||
static bool startFullscreen = false;
|
||||
static bool runOnce = false;
|
||||
static string startURL;
|
||||
static string startDirectory;
|
||||
static string startScript;
|
||||
static vector<fs::path> extrasDirectories;
|
||||
static string configFileName;
|
||||
static bool useAlternateConfigFile = false;
|
||||
static bool skipSplashScreen = false;
|
||||
|
||||
static bool parseCommandLine(int argc, char* argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < argc)
|
||||
{
|
||||
bool isLastArg = (i == argc - 1);
|
||||
if (strcmp(argv[i], "--verbose") == 0)
|
||||
{
|
||||
SetDebugVerbosity(1);
|
||||
}
|
||||
else if (strcmp(argv[i], "--fullscreen") == 0)
|
||||
{
|
||||
startFullscreen = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "--once") == 0)
|
||||
{
|
||||
runOnce = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "--dir") == 0)
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
MessageBox(NULL,
|
||||
_("Directory expected after --dir"),
|
||||
_("Celestia Command Line Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
startDirectory = string(argv[i]);
|
||||
}
|
||||
else if (strcmp(argv[i], "--conf") == 0)
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
MessageBox(NULL,
|
||||
_("Configuration file name expected after --conf"),
|
||||
_("Celestia Command Line Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
configFileName = string(argv[i]);
|
||||
useAlternateConfigFile = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "--extrasdir") == 0)
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
MessageBox(NULL,
|
||||
_("Directory expected after --extrasdir"),
|
||||
_("Celestia Command Line Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
extrasDirectories.push_back(string(argv[i]));
|
||||
}
|
||||
else if (strcmp(argv[i], "-u") == 0 || strcmp(argv[i], "--url") == 0)
|
||||
{
|
||||
if (isLastArg)
|
||||
{
|
||||
MessageBox(NULL,
|
||||
_("URL expected after --url"),
|
||||
_("Celestia Command Line Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
startURL = string(argv[i]);
|
||||
}
|
||||
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--nosplash") == 0)
|
||||
{
|
||||
skipSplashScreen = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* buf = new char[strlen(argv[i]) + 256];
|
||||
sprintf(buf, _("Invalid command line option '%s'"), argv[i]);
|
||||
MessageBox(NULL,
|
||||
buf, _("Celestia Command Line Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
delete[] buf;
|
||||
return false;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
class WinSplashProgressNotifier : public ProgressNotifier
|
||||
{
|
||||
public:
|
||||
|
@ -3130,9 +3031,19 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
int argc;
|
||||
char** argv;
|
||||
argv = splitCommandLine(lpCmdLine, argc);
|
||||
bool cmdLineOK = parseCommandLine(argc, argv);
|
||||
if (!cmdLineOK)
|
||||
return 1;
|
||||
|
||||
appCore = new CelestiaCore();
|
||||
auto parser = appCore->getCommandLineParser();
|
||||
parser.on("fullscreen", 'f', false,
|
||||
_("Start full-screen"),
|
||||
[](bool) { startFullscreen = true; });
|
||||
parser.on("nosplash", 's', false,
|
||||
_("Disable splash screen"),
|
||||
[](bool) { skipSplashScreen = true; });
|
||||
parser.on("once", 'o', false,
|
||||
_("Run only one Celestia instance"),
|
||||
[](bool) { runOnce = true; });
|
||||
parser.parse(argc, argv);
|
||||
|
||||
// If Celestia was invoked with the --once command line parameter,
|
||||
// check to see if there's already an instance of Celestia running.
|
||||
|
@ -3147,12 +3058,13 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
// If there's an existing instance and we've been given a
|
||||
// URL on the command line, send the URL to the running instance
|
||||
// of Celestia before terminating.
|
||||
if (startURL != "")
|
||||
auto startURL = appCore->getStartURL();
|
||||
if (!startURL.empty())
|
||||
{
|
||||
COPYDATASTRUCT cd;
|
||||
cd.dwData = 0;
|
||||
cd.cbData = startURL.length();
|
||||
cd.lpData = reinterpret_cast<void*>(const_cast<char*>(startURL.c_str()));
|
||||
cd.lpData = reinterpret_cast<void*>(const_cast<char*>(startURL.data()));
|
||||
SendMessage(existingWnd, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cd));
|
||||
}
|
||||
SetForegroundWindow(existingWnd);
|
||||
|
@ -3161,11 +3073,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
}
|
||||
}
|
||||
|
||||
// If a start directory was given on the command line, switch to it
|
||||
// now.
|
||||
if (startDirectory != "")
|
||||
SetCurrentDirectory(startDirectory.c_str());
|
||||
|
||||
s_splash = new SplashWindow(SPLASH_DIR "\\" "splash.png");
|
||||
s_splash->setMessage(_("Loading data files..."));
|
||||
if (!skipSplashScreen)
|
||||
|
@ -3252,8 +3159,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
lastFullScreenMode = fallbackFullScreenMode;
|
||||
}
|
||||
|
||||
appCore = new CelestiaCore();
|
||||
|
||||
// Gettext integration
|
||||
setlocale(LC_ALL, "");
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
@ -3282,8 +3187,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
if (!skipSplashScreen)
|
||||
progressNotifier = new WinSplashProgressNotifier(s_splash);
|
||||
|
||||
bool initSucceeded = appCore->initSimulation(configFileName, extrasDirectories, progressNotifier);
|
||||
|
||||
bool initSucceeded = appCore->initSimulation(progressNotifier);
|
||||
delete progressNotifier;
|
||||
|
||||
// Close the splash screen after all data has been loaded
|
||||
|
@ -3298,9 +3202,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
if (!initSucceeded)
|
||||
return 1;
|
||||
|
||||
if (startURL != "")
|
||||
appCore->setStartURL(startURL);
|
||||
|
||||
menuBar = CreateMenuBar();
|
||||
acceleratorTable = LoadAccelerators(hRes,
|
||||
MAKEINTRESOURCE(IDR_ACCELERATORS));
|
||||
|
@ -3464,15 +3365,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
|
||||
appCore->start();
|
||||
|
||||
if (startURL != "")
|
||||
{
|
||||
COPYDATASTRUCT cd;
|
||||
cd.dwData = 0;
|
||||
cd.cbData = startURL.length();
|
||||
cd.lpData = reinterpret_cast<void*>(const_cast<char*>(startURL.c_str()));
|
||||
SendMessage(mainWindow, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cd));
|
||||
}
|
||||
|
||||
// Initial tick required before first frame is rendered; this gives
|
||||
// start up scripts a chance to run.
|
||||
appCore->tick();
|
||||
|
|
|
@ -3,6 +3,8 @@ set(CELUTIL_SOURCES
|
|||
bigfix.h
|
||||
blockarray.h
|
||||
bytes.h
|
||||
cmdline.cpp
|
||||
cmdline.h
|
||||
color.cpp
|
||||
color.h
|
||||
debug.cpp
|
||||
|
|
|
@ -39,13 +39,22 @@ class array_view
|
|||
~array_view() noexcept = default;
|
||||
|
||||
/**
|
||||
* Wrap a C-style array.
|
||||
* Wrap a compile-time C-style array.
|
||||
*/
|
||||
template<size_t N> constexpr array_view(const T (&ary)[N]) noexcept :
|
||||
m_ptr(ary),
|
||||
m_size(N)
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* Wrap a run-time C-style array.
|
||||
*/
|
||||
constexpr array_view(const T ary[], size_t n) noexcept :
|
||||
m_ptr(ary),
|
||||
m_size(n)
|
||||
{};
|
||||
|
||||
/**
|
||||
* Wrap a std::array or std::vector or other classes which have the same
|
||||
* memory layout and interface.
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
#include "cmdline.h"
|
||||
|
||||
namespace celestia
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
CmdLineParser::Option::Option(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
std::function<bool(const char*)> handler) :
|
||||
hasValue(hasValue),
|
||||
handler1(handler)
|
||||
{
|
||||
this->longOption = fmt::format("--{}", longOption);
|
||||
this->shortOption = fmt::format("-{}", shortOption);
|
||||
}
|
||||
|
||||
CmdLineParser::Option::Option(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
std::function<void(bool)> handler) :
|
||||
hasValue(hasValue),
|
||||
handler0(handler)
|
||||
{
|
||||
this->longOption = fmt::format("--{}", longOption);
|
||||
this->shortOption = fmt::format("-{}", shortOption);
|
||||
}
|
||||
|
||||
CmdLineParser&
|
||||
CmdLineParser::on(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
const char *errorMessage,
|
||||
std::function<bool(const char*)> handler)
|
||||
{
|
||||
(void) errorMessage;
|
||||
m_options.emplace_back(longOption, shortOption, hasValue, handler);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CmdLineParser&
|
||||
CmdLineParser::on(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
const char *errorMessage,
|
||||
std::function<void(bool)> handler)
|
||||
{
|
||||
(void) errorMessage;
|
||||
m_options.emplace_back(longOption, shortOption, hasValue, handler);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CmdLineParser&
|
||||
CmdLineParser::on(const CmdLineParser::Option &option)
|
||||
{
|
||||
m_options.push_back(option);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char*
|
||||
CmdLineParser::getBadOption() const noexcept
|
||||
{
|
||||
return m_badOption;
|
||||
}
|
||||
|
||||
CmdLineParser::ErrorClass
|
||||
CmdLineParser::getError() const noexcept
|
||||
{
|
||||
return m_ec;
|
||||
}
|
||||
|
||||
const char*
|
||||
CmdLineParser::getErrorString() const noexcept
|
||||
{
|
||||
switch (m_ec)
|
||||
{
|
||||
case NoError:
|
||||
return "no error";
|
||||
case ArgumentMissing:
|
||||
return "argument missing";
|
||||
case UnknownOption:
|
||||
return "unknown option";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CmdLineParser::parse(int argc, char *argv[])
|
||||
{
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
const char* arg = argv[i];
|
||||
auto op = [arg](const Option &option) {
|
||||
return option.longOption == arg || option.shortOption == arg;
|
||||
};
|
||||
|
||||
auto it = std::find_if(m_options.begin(), m_options.end(), op);
|
||||
if (it == m_options.end())
|
||||
{
|
||||
m_ec = UnknownOption;
|
||||
m_badOption = argv[i];
|
||||
return false;
|
||||
}
|
||||
if (it->hasValue)
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
m_ec = ArgumentMissing;
|
||||
m_badOption = argv[i];
|
||||
return false;
|
||||
}
|
||||
|
||||
it->handler1(argv[++i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->handler0(true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
using namespace celestia::util;
|
||||
#include <iostream>
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
CmdLineParser cmdline;
|
||||
cmdline.on("value", 'v', true, "", [](const char *value) { std::cout << value << '\n'; return true; })
|
||||
.on("bool", 'b', false, "", [](bool on) { std::cout << "bool=" << on << '\n'; });
|
||||
if (!cmdline.parse(argc, argv))
|
||||
{
|
||||
std::cerr << "Bad option: " << cmdline.getBadOption() << ", " << cmdline.getErrorString() << '\n';
|
||||
}
|
||||
std::cout << sizeof(std::function<void(const char*)>) << ' ' << sizeof(std::function<void()>) << '\n';
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace celestia
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
class CmdLineParser
|
||||
{
|
||||
public:
|
||||
enum ErrorClass
|
||||
{
|
||||
NoError = 0,
|
||||
ArgumentMissing = 1,
|
||||
UnknownOption = 2,
|
||||
};
|
||||
|
||||
struct Option
|
||||
{
|
||||
std::string longOption;
|
||||
std::string shortOption;
|
||||
bool hasValue;
|
||||
std::function<bool(const char*)> handler1;
|
||||
std::function<void(bool)> handler0;
|
||||
|
||||
Option(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
std::function<bool(const char*)> handler);
|
||||
|
||||
Option(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
std::function<void(bool)> handler);
|
||||
};
|
||||
|
||||
bool parse(int argc, char *argv[]);
|
||||
const char* getBadOption() const noexcept;
|
||||
ErrorClass getError() const noexcept;
|
||||
const char* getErrorString() const noexcept;
|
||||
|
||||
CmdLineParser& on(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
const char *errorMessage,
|
||||
std::function<bool(const char*)> handler);
|
||||
|
||||
CmdLineParser& on(const char *longOption,
|
||||
char shortOption,
|
||||
bool hasValue,
|
||||
const char *errorMessage,
|
||||
std::function<void(bool)> handler);
|
||||
|
||||
CmdLineParser& on(const Option &option);
|
||||
|
||||
private:
|
||||
std::vector<Option> m_options;
|
||||
const char* m_badOption { nullptr };
|
||||
ErrorClass m_ec { NoError };
|
||||
};
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ add_subdirectory(charm2)
|
|||
add_subdirectory(cmod)
|
||||
add_subdirectory(galaxies)
|
||||
add_subdirectory(globulars)
|
||||
add_subdirectory(qttxf)
|
||||
add_subdirectory(spice2xyzv)
|
||||
add_subdirectory(stardb)
|
||||
add_subdirectory(vsop)
|
||||
|
|
Loading…
Reference in New Issue