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>
|
#include <celutil/winutil.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MSC_VER) && !defined(__clang__)
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
// M$VC++ build without C++ exceptions are not supported yet
|
// M$VC++ build without C++ exceptions are not supported yet
|
||||||
|
@ -594,5 +595,66 @@ bool create_directory(const path& p)
|
||||||
return r;
|
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);
|
||||||
bool create_directory(const path& p, std::error_code& ec) noexcept;
|
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
|
#endif
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#ifndef alloca
|
||||||
#define alloca(s) _alloca(s)
|
#define alloca(s) _alloca(s)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace cmod;
|
using namespace cmod;
|
||||||
using namespace Eigen;
|
using namespace Eigen;
|
||||||
|
|
|
@ -131,7 +131,7 @@ void VertexObject::enableAttribArrays() noexcept
|
||||||
auto n = t.first;
|
auto n = t.first;
|
||||||
auto& p = t.second;
|
auto& p = t.second;
|
||||||
glEnableVertexAttribArray(n);
|
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()
|
void CelestiaCore::tick()
|
||||||
{
|
{
|
||||||
|
@ -3680,13 +3684,15 @@ using StarLoader = CatalogLoader<StarDatabase>;
|
||||||
using DeepSkyLoader = CatalogLoader<DSODatabase>;
|
using DeepSkyLoader = CatalogLoader<DSODatabase>;
|
||||||
|
|
||||||
|
|
||||||
bool CelestiaCore::initSimulation(const fs::path& configFileName,
|
bool CelestiaCore::initSimulation(ProgressNotifier* progressNotifier)
|
||||||
const vector<fs::path>& extrasDirs,
|
|
||||||
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
|
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
|
// 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
|
// specified is preserved. This process in O(N*M), but the number of
|
||||||
// additional extras directories should be small.
|
// 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.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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CelestiaCore::setLogFile(fs::path &fn)
|
void CelestiaCore::setLogFile(const fs::path &fn)
|
||||||
{
|
{
|
||||||
m_logfile = std::ofstream(fn.string());
|
m_logfile = std::ofstream(fn.string());
|
||||||
if (m_logfile.good())
|
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
|
#ifdef USE_FFMPEG
|
||||||
auto CelestiaCore::getSupportedMovieSizes() const
|
auto CelestiaCore::getSupportedMovieSizes() const
|
||||||
-> celestia::util::array_view<MovieSize>
|
-> celestia::util::array_view<MovieSize>
|
||||||
|
@ -4800,9 +4839,9 @@ auto CelestiaCore::getSupportedMovieSizes() const
|
||||||
auto CelestiaCore::getSupportedMovieFramerates() const
|
auto CelestiaCore::getSupportedMovieFramerates() const
|
||||||
-> celestia::util::array_view<float>
|
-> 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;
|
return MovieFramerates;
|
||||||
}
|
}
|
||||||
|
@ -4818,3 +4857,30 @@ auto CelestiaCore::getSupportedMovieCodecs() const
|
||||||
return MovieCodecs;
|
return MovieCodecs;
|
||||||
}
|
}
|
||||||
#endif
|
#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 <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <celutil/array_view.h>
|
||||||
|
#include <celutil/cmdline.h>
|
||||||
#include <celutil/filetype.h>
|
#include <celutil/filetype.h>
|
||||||
|
#include <celutil/tee.h>
|
||||||
#include <celutil/timer.h>
|
#include <celutil/timer.h>
|
||||||
#include <celutil/watcher.h>
|
#include <celutil/watcher.h>
|
||||||
// #include <celutil/watchable.h>
|
// #include <celutil/watchable.h>
|
||||||
|
#include <celcompat/string_view.h>
|
||||||
#include <celengine/solarsys.h>
|
#include <celengine/solarsys.h>
|
||||||
#include <celengine/overlay.h>
|
#include <celengine/overlay.h>
|
||||||
#include <celengine/texture.h>
|
#include <celengine/texture.h>
|
||||||
|
@ -25,7 +29,6 @@
|
||||||
#include <celengine/simulation.h>
|
#include <celengine/simulation.h>
|
||||||
#include <celengine/overlayimage.h>
|
#include <celengine/overlayimage.h>
|
||||||
#include <celengine/viewporteffect.h>
|
#include <celengine/viewporteffect.h>
|
||||||
#include <celutil/tee.h>
|
|
||||||
#include "configfile.h"
|
#include "configfile.h"
|
||||||
#include "favorites.h"
|
#include "favorites.h"
|
||||||
#include "destination.h"
|
#include "destination.h"
|
||||||
|
@ -195,9 +198,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
CelestiaCore();
|
CelestiaCore();
|
||||||
~CelestiaCore();
|
~CelestiaCore();
|
||||||
|
|
||||||
bool initSimulation(const fs::path& configFileName = fs::path(),
|
bool initSimulation(ProgressNotifier* progressNotifier = nullptr);
|
||||||
const std::vector<fs::path>& extrasDirs = {},
|
|
||||||
ProgressNotifier* progressNotifier = nullptr);
|
|
||||||
bool initRenderer();
|
bool initRenderer();
|
||||||
void start(double t);
|
void start(double t);
|
||||||
void start();
|
void start();
|
||||||
|
@ -206,6 +207,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
|
|
||||||
// URLs and history navigation
|
// URLs and history navigation
|
||||||
void setStartURL(const std::string& url);
|
void setStartURL(const std::string& url);
|
||||||
|
std::string_view getStartURL() const;
|
||||||
bool goToUrl(const std::string& urlStr);
|
bool goToUrl(const std::string& urlStr);
|
||||||
void addToHistory();
|
void addToHistory();
|
||||||
void back();
|
void back();
|
||||||
|
@ -322,12 +324,12 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
|
|
||||||
void notifyWatchers(int);
|
void notifyWatchers(int);
|
||||||
|
|
||||||
void setLogFile(fs::path&);
|
void setLogFile(const fs::path&);
|
||||||
|
|
||||||
class Alerter
|
class Alerter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Alerter() {};
|
virtual ~Alerter() = default;
|
||||||
virtual void fatalError(const std::string&) = 0;
|
virtual void fatalError(const std::string&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -337,7 +339,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
class CursorHandler
|
class CursorHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~CursorHandler() {};
|
virtual ~CursorHandler() = default;
|
||||||
virtual void setCursorShape(CursorShape) = 0;
|
virtual void setCursorShape(CursorShape) = 0;
|
||||||
virtual CursorShape getCursorShape() const = 0;
|
virtual CursorShape getCursorShape() const = 0;
|
||||||
};
|
};
|
||||||
|
@ -389,6 +391,8 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
Image captureImage() const;
|
Image captureImage() const;
|
||||||
bool saveScreenShot(const fs::path&, ContentType = Content_Unknown) const;
|
bool saveScreenShot(const fs::path&, ContentType = Content_Unknown) const;
|
||||||
|
|
||||||
|
celestia::util::CmdLineParser getCommandLineParser();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool readStars(const CelestiaConfig&, ProgressNotifier*);
|
bool readStars(const CelestiaConfig&, ProgressNotifier*);
|
||||||
void renderOverlay();
|
void renderOverlay();
|
||||||
|
@ -397,6 +401,8 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
#endif // CELX
|
#endif // CELX
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool initDataPath();
|
||||||
|
|
||||||
CelestiaConfig* config{ nullptr };
|
CelestiaConfig* config{ nullptr };
|
||||||
|
|
||||||
Universe* universe{ nullptr };
|
Universe* universe{ nullptr };
|
||||||
|
@ -538,6 +544,12 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
||||||
std::ofstream m_logfile;
|
std::ofstream m_logfile;
|
||||||
teestream m_tee;
|
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
|
#ifdef CELX
|
||||||
friend View* getViewByObserver(CelestiaCore*, Observer*);
|
friend View* getViewByObserver(CelestiaCore*, Observer*);
|
||||||
friend void getObservers(CelestiaCore*, std::vector<Observer*>&);
|
friend void getObservers(CelestiaCore*, std::vector<Observer*>&);
|
||||||
|
|
|
@ -75,24 +75,9 @@ static void initRealize(GtkWidget* widget, AppData* app);
|
||||||
|
|
||||||
|
|
||||||
/* Command-Line Options */
|
/* Command-Line Options */
|
||||||
static gchar* configFile = NULL;
|
|
||||||
static gchar* installDir = NULL;
|
|
||||||
static gchar** extrasDir = NULL;
|
|
||||||
static gboolean fullScreen = FALSE;
|
static gboolean fullScreen = FALSE;
|
||||||
static gboolean noSplash = 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 */
|
/* Initializes GtkActions and creates main menu */
|
||||||
static void createMainMenu(GtkWidget* window, AppData* app)
|
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 */
|
/* Watcher enables sending signals from inside of core */
|
||||||
GtkWatcher* gtkWatcher;
|
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
|
#ifdef GNOME
|
||||||
/* GNOME Initialization */
|
/* GNOME Initialization */
|
||||||
GnomeProgram *program;
|
GnomeProgram *program;
|
||||||
|
@ -384,34 +341,20 @@ int main(int argc, char* argv[])
|
||||||
SetDebugVerbosity(0);
|
SetDebugVerbosity(0);
|
||||||
|
|
||||||
app->core = new CelestiaCore();
|
app->core = new CelestiaCore();
|
||||||
if (app->core == NULL)
|
auto parser = app->core->getCommandLineParser();
|
||||||
{
|
parser.on("fullscreen", 'f', false,
|
||||||
cerr << "Failed to initialize Celestia core.\n";
|
_("Start full-screen"),
|
||||||
return 1;
|
[](bool) { fullScreen = TRUE; });
|
||||||
}
|
parser.on("nosplash", 's', false,
|
||||||
|
_("Disable splash screen"),
|
||||||
|
[](bool) { noSplash = TRUE; });
|
||||||
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
app->renderer = app->core->getRenderer();
|
app->renderer = app->core->getRenderer();
|
||||||
g_assert(app->renderer);
|
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 */
|
/* Initialize the simulation */
|
||||||
if (!app->core->initSimulation(altConfig, configDirs, ss->notifier))
|
if (!app->core->initSimulation(ss->notifier))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
app->simulation = app->core->getSimulation();
|
app->simulation = app->core->getSimulation();
|
||||||
|
|
|
@ -187,43 +187,12 @@ CelestiaAppWindow::~CelestiaAppWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CelestiaAppWindow::init(const QString& qConfigFileName,
|
void CelestiaAppWindow::init(int argc, char *argv[])
|
||||||
const QStringList& qExtrasDirectories,
|
|
||||||
const QString& logFilename)
|
|
||||||
{
|
{
|
||||||
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();
|
initAppDataDirectory();
|
||||||
|
|
||||||
m_appCore = new CelestiaCore();
|
m_appCore = new CelestiaCore();
|
||||||
|
m_appCore->getCommandLineParser().parse(argc, argv);
|
||||||
|
|
||||||
auto* progress = new AppProgressNotifier(this);
|
auto* progress = new AppProgressNotifier(this);
|
||||||
alerter = new AppAlerter(this);
|
alerter = new AppAlerter(this);
|
||||||
|
@ -231,15 +200,7 @@ void CelestiaAppWindow::init(const QString& qConfigFileName,
|
||||||
|
|
||||||
setWindowIcon(QIcon(":/icons/celestia.png"));
|
setWindowIcon(QIcon(":/icons/celestia.png"));
|
||||||
|
|
||||||
if (!logFilename.isEmpty())
|
if (!m_appCore->initSimulation(progress))
|
||||||
{
|
|
||||||
fs::path fn(logFilename.toStdString());
|
|
||||||
m_appCore->setLogFile(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_appCore->initSimulation(configFileName,
|
|
||||||
extrasDirectories,
|
|
||||||
progress))
|
|
||||||
{
|
{
|
||||||
// Error message is shown by celestiacore so we silently exit here.
|
// Error message is shown by celestiacore so we silently exit here.
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -40,9 +40,7 @@ class CelestiaAppWindow : public QMainWindow, public CelestiaCore::ContextMenuHa
|
||||||
CelestiaAppWindow(QWidget* parent = nullptr);
|
CelestiaAppWindow(QWidget* parent = nullptr);
|
||||||
~CelestiaAppWindow();
|
~CelestiaAppWindow();
|
||||||
|
|
||||||
void init(const QString& configFileName,
|
void init(int argc, char *argv[]);
|
||||||
const QStringList& extrasDirectories,
|
|
||||||
const QString& logFilename);
|
|
||||||
|
|
||||||
void readSettings();
|
void readSettings();
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
|
|
|
@ -33,22 +33,6 @@
|
||||||
|
|
||||||
using namespace std;
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#ifndef GL_ES
|
#ifndef GL_ES
|
||||||
|
@ -71,8 +55,6 @@ int main(int argc, char *argv[])
|
||||||
QCoreApplication::setOrganizationName("Celestia Development Team");
|
QCoreApplication::setOrganizationName("Celestia Development Team");
|
||||||
QCoreApplication::setApplicationName("Celestia QT");
|
QCoreApplication::setApplicationName("Celestia QT");
|
||||||
|
|
||||||
ParseCommandLine();
|
|
||||||
|
|
||||||
#ifdef NATIVE_OSX_APP
|
#ifdef NATIVE_OSX_APP
|
||||||
// On macOS data directory is in a fixed position relative to the application bundle
|
// On macOS data directory is in a fixed position relative to the application bundle
|
||||||
QDir splashDir(QApplication::applicationDirPath() + "/../Resources/splash");
|
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&)),
|
QObject::connect(&window, SIGNAL(progressUpdate(const QString&, int, const QColor&)),
|
||||||
&splash, SLOT(showMessage(const QString&, int, const QColor&)));
|
&splash, SLOT(showMessage(const QString&, int, const QColor&)));
|
||||||
|
|
||||||
window.init(configFileName, extrasDirectories, logFilename);
|
window.init(argc, argv);
|
||||||
window.show();
|
window.show();
|
||||||
|
|
||||||
splash.finish(&window);
|
splash.finish(&window);
|
||||||
|
@ -122,103 +104,3 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
return app.exec();
|
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";
|
char AppName[] = "Celestia";
|
||||||
|
|
||||||
|
// command line options
|
||||||
|
static bool startFullscreen = false;
|
||||||
|
static bool runOnce = false;
|
||||||
|
static bool skipSplashScreen = false;
|
||||||
|
|
||||||
static CelestiaCore* appCore = NULL;
|
static CelestiaCore* appCore = NULL;
|
||||||
|
|
||||||
// Display modes for full screen operation
|
// 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
|
class WinSplashProgressNotifier : public ProgressNotifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -3130,9 +3031,19 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
int argc;
|
int argc;
|
||||||
char** argv;
|
char** argv;
|
||||||
argv = splitCommandLine(lpCmdLine, argc);
|
argv = splitCommandLine(lpCmdLine, argc);
|
||||||
bool cmdLineOK = parseCommandLine(argc, argv);
|
|
||||||
if (!cmdLineOK)
|
appCore = new CelestiaCore();
|
||||||
return 1;
|
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,
|
// If Celestia was invoked with the --once command line parameter,
|
||||||
// check to see if there's already an instance of Celestia running.
|
// 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
|
// If there's an existing instance and we've been given a
|
||||||
// URL on the command line, send the URL to the running instance
|
// URL on the command line, send the URL to the running instance
|
||||||
// of Celestia before terminating.
|
// of Celestia before terminating.
|
||||||
if (startURL != "")
|
auto startURL = appCore->getStartURL();
|
||||||
|
if (!startURL.empty())
|
||||||
{
|
{
|
||||||
COPYDATASTRUCT cd;
|
COPYDATASTRUCT cd;
|
||||||
cd.dwData = 0;
|
cd.dwData = 0;
|
||||||
cd.cbData = startURL.length();
|
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));
|
SendMessage(existingWnd, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cd));
|
||||||
}
|
}
|
||||||
SetForegroundWindow(existingWnd);
|
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 = new SplashWindow(SPLASH_DIR "\\" "splash.png");
|
||||||
s_splash->setMessage(_("Loading data files..."));
|
s_splash->setMessage(_("Loading data files..."));
|
||||||
if (!skipSplashScreen)
|
if (!skipSplashScreen)
|
||||||
|
@ -3252,8 +3159,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
lastFullScreenMode = fallbackFullScreenMode;
|
lastFullScreenMode = fallbackFullScreenMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
appCore = new CelestiaCore();
|
|
||||||
|
|
||||||
// Gettext integration
|
// Gettext integration
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
setlocale(LC_NUMERIC, "C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
@ -3282,8 +3187,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
if (!skipSplashScreen)
|
if (!skipSplashScreen)
|
||||||
progressNotifier = new WinSplashProgressNotifier(s_splash);
|
progressNotifier = new WinSplashProgressNotifier(s_splash);
|
||||||
|
|
||||||
bool initSucceeded = appCore->initSimulation(configFileName, extrasDirectories, progressNotifier);
|
bool initSucceeded = appCore->initSimulation(progressNotifier);
|
||||||
|
|
||||||
delete progressNotifier;
|
delete progressNotifier;
|
||||||
|
|
||||||
// Close the splash screen after all data has been loaded
|
// Close the splash screen after all data has been loaded
|
||||||
|
@ -3298,9 +3202,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
if (!initSucceeded)
|
if (!initSucceeded)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (startURL != "")
|
|
||||||
appCore->setStartURL(startURL);
|
|
||||||
|
|
||||||
menuBar = CreateMenuBar();
|
menuBar = CreateMenuBar();
|
||||||
acceleratorTable = LoadAccelerators(hRes,
|
acceleratorTable = LoadAccelerators(hRes,
|
||||||
MAKEINTRESOURCE(IDR_ACCELERATORS));
|
MAKEINTRESOURCE(IDR_ACCELERATORS));
|
||||||
|
@ -3464,15 +3365,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
|
|
||||||
appCore->start();
|
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
|
// Initial tick required before first frame is rendered; this gives
|
||||||
// start up scripts a chance to run.
|
// start up scripts a chance to run.
|
||||||
appCore->tick();
|
appCore->tick();
|
||||||
|
|
|
@ -3,6 +3,8 @@ set(CELUTIL_SOURCES
|
||||||
bigfix.h
|
bigfix.h
|
||||||
blockarray.h
|
blockarray.h
|
||||||
bytes.h
|
bytes.h
|
||||||
|
cmdline.cpp
|
||||||
|
cmdline.h
|
||||||
color.cpp
|
color.cpp
|
||||||
color.h
|
color.h
|
||||||
debug.cpp
|
debug.cpp
|
||||||
|
|
|
@ -39,13 +39,22 @@ class array_view
|
||||||
~array_view() noexcept = default;
|
~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 :
|
template<size_t N> constexpr array_view(const T (&ary)[N]) noexcept :
|
||||||
m_ptr(ary),
|
m_ptr(ary),
|
||||||
m_size(N)
|
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
|
* Wrap a std::array or std::vector or other classes which have the same
|
||||||
* memory layout and interface.
|
* 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(cmod)
|
||||||
add_subdirectory(galaxies)
|
add_subdirectory(galaxies)
|
||||||
add_subdirectory(globulars)
|
add_subdirectory(globulars)
|
||||||
add_subdirectory(qttxf)
|
|
||||||
add_subdirectory(spice2xyzv)
|
add_subdirectory(spice2xyzv)
|
||||||
add_subdirectory(stardb)
|
add_subdirectory(stardb)
|
||||||
add_subdirectory(vsop)
|
add_subdirectory(vsop)
|
||||||
|
|
Loading…
Reference in New Issue