main.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:15k
- /*
- * Celestia GTK+ Front-End
- * Copyright (C) 2005 Pat Suwalski <pat@suwalski.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: main.cpp,v 1.9 2008-01-21 04:55:19 suwalski Exp $
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif /* HAVE_CONFIG_H */
- #include <iostream>
- #include <fstream>
- #include <cstdlib>
- #include <cctype>
- #include <cstring>
- #include <time.h>
- #ifdef WIN32
- #include <direct.h>
- #else
- #include <unistd.h>
- #endif /* WIN32 */
- #include <gtk/gtk.h>
- #include <gtk/gtkgl.h>
- #include <celengine/astro.h>
- #include <celengine/celestia.h>
- #include <celengine/gl.h>
- #include <celengine/glext.h>
- #include <celengine/galaxy.h>
- #include <celengine/simulation.h>
- #include <celestia/celestiacore.h>
- #include <celutil/debug.h>
- /* Includes for the GNOME front-end */
- #ifdef GNOME
- #include <gnome.h>
- #include <libgnomeui/libgnomeui.h>
- #include <gconf/gconf-client.h>
- #endif /* GNOME */
- /* Includes for the GTK front-end */
- #include "common.h"
- #include "glwidget.h"
- #include "menu-context.h"
- #include "splash.h"
- #include "ui.h"
- /* Includes for the settings interface */
- #ifdef GNOME
- #include "settings-gconf.h"
- #else
- #include "settings-file.h"
- #endif /* GNOME */
- #ifndef DEBUG
- #define G_DISABLE_ASSERT
- #endif /* DEBUG */
- using namespace std;
- /* Function Definitions */
- static void createMainMenu(GtkWidget* window, AppData* app);
- 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 },
- };
- /* Initializes GtkActions and creates main menu */
- static void createMainMenu(GtkWidget* window, AppData* app)
- {
- GtkUIManager *ui_manager;
- GtkAccelGroup *accel_group;
- GError *error;
-
- app->agMain = gtk_action_group_new ("MenuActions");
- app->agRender = gtk_action_group_new("RenderActions");
- app->agLabel = gtk_action_group_new("LabelActions");
- app->agOrbit = gtk_action_group_new("OrbitActions");
- app->agVerbosity = gtk_action_group_new("VerbosityActions");
- app->agStarStyle = gtk_action_group_new("StarStyleActions");
- app->agAmbient = gtk_action_group_new("AmbientActions");
-
- /* All actions have the AppData structure passed */
- gtk_action_group_add_actions(app->agMain, actionsPlain, G_N_ELEMENTS(actionsPlain), app);
- gtk_action_group_add_toggle_actions(app->agMain, actionsToggle, G_N_ELEMENTS(actionsToggle), app);
- gtk_action_group_add_radio_actions(app->agVerbosity, actionsVerbosity, G_N_ELEMENTS(actionsVerbosity), 0, G_CALLBACK(actionVerbosity), app);
- gtk_action_group_add_radio_actions(app->agStarStyle, actionsStarStyle, G_N_ELEMENTS(actionsStarStyle), 0, G_CALLBACK(actionStarStyle), app);
- gtk_action_group_add_radio_actions(app->agAmbient, actionsAmbientLight, G_N_ELEMENTS(actionsAmbientLight), 0, G_CALLBACK(actionAmbientLight), app);
- gtk_action_group_add_toggle_actions(app->agRender, actionsRenderFlags, G_N_ELEMENTS(actionsRenderFlags), app);
- gtk_action_group_add_toggle_actions(app->agLabel, actionsLabelFlags, G_N_ELEMENTS(actionsLabelFlags), app);
- gtk_action_group_add_toggle_actions(app->agOrbit, actionsOrbitFlags, G_N_ELEMENTS(actionsOrbitFlags), app);
- ui_manager = gtk_ui_manager_new();
- gtk_ui_manager_insert_action_group(ui_manager, app->agMain, 0);
- gtk_ui_manager_insert_action_group(ui_manager, app->agRender, 0);
- gtk_ui_manager_insert_action_group(ui_manager, app->agLabel, 0);
- gtk_ui_manager_insert_action_group(ui_manager, app->agOrbit, 0);
- gtk_ui_manager_insert_action_group(ui_manager, app->agStarStyle, 0);
- gtk_ui_manager_insert_action_group(ui_manager, app->agAmbient, 0);
- gtk_ui_manager_insert_action_group(ui_manager, app->agVerbosity, 0);
- accel_group = gtk_ui_manager_get_accel_group(ui_manager);
- gtk_window_add_accel_group(GTK_WINDOW (window), accel_group);
- error = NULL;
- if (!gtk_ui_manager_add_ui_from_file(ui_manager, "celestiaui.xml", &error))
- {
- g_message("Building menus failed: %s", error->message);
- g_error_free(error);
- exit(EXIT_FAILURE);
- }
- app->mainMenu = gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
- }
- /* Our own watcher. Celestiacore will call notifyChange() to tell us
- * we need to recheck the check menu items and option buttons. */
- class GtkWatcher : public CelestiaWatcher
- {
- public:
- GtkWatcher(CelestiaCore*, AppData*);
- virtual void notifyChange(CelestiaCore*, int);
- private:
- AppData* app;
- };
- GtkWatcher::GtkWatcher(CelestiaCore* _appCore, AppData* _app) :
- CelestiaWatcher(*_appCore), app(_app)
- {
- }
- void GtkWatcher::notifyChange(CelestiaCore*, int property)
- {
- if (property & CelestiaCore::LabelFlagsChanged)
- resyncLabelActions(app);
- else if (property & CelestiaCore::RenderFlagsChanged)
- {
- resyncRenderActions(app);
- resyncOrbitActions(app);
- resyncStarStyleActions(app);
- resyncTextureResolutionActions(app);
- }
- else if (property & CelestiaCore::VerbosityLevelChanged)
- resyncVerbosityActions(app);
- else if (property & CelestiaCore::TimeZoneChanged)
- resyncTimeZoneAction(app);
- else if (property & CelestiaCore::AmbientLightChanged)
- resyncAmbientActions(app);
- /*
- else if (property & CelestiaCore::FaintestChanged) DEPRECATED?
- else if (property & CelestiaCore::HistoryChanged)
- */
- else if (property == CelestiaCore::TextEnterModeChanged)
- {
- if (app->core->getTextEnterMode() != 0)
- {
- /* Grey-out the menu */
- gtk_widget_set_sensitive(app->mainMenu, FALSE);
-
- /* Disable any actions that will interfere in typing and
- autocomplete */
- gtk_action_group_set_sensitive(app->agMain, FALSE);
- gtk_action_group_set_sensitive(app->agRender, FALSE);
- gtk_action_group_set_sensitive(app->agLabel, FALSE);
- }
- else
- {
- /* Set the menu normal */
- gtk_widget_set_sensitive(app->mainMenu, TRUE);
-
- /* Re-enable action groups */
- gtk_action_group_set_sensitive(app->agMain, TRUE);
- gtk_action_group_set_sensitive(app->agRender, TRUE);
- gtk_action_group_set_sensitive(app->agLabel, TRUE);
- }
- }
-
- else if (property & CelestiaCore::GalaxyLightGainChanged)
- resyncGalaxyGainActions(app);
- }
- /* END Watcher */
- /* CALLBACK: Event "realize" on the main GL area. Things that go here are those
- * that require the glArea to be set up. */
- static void initRealize(GtkWidget* widget, AppData* app)
- {
- if (!app->core->initRenderer())
- {
- cerr << "Failed to initialize renderer.n";
- }
- /* Read/Apply Settings */
- #ifdef GNOME
- applySettingsGConfMain(app, app->client);
- #else
- applySettingsFileMain(app, app->settingsFile);
- #endif /* GNOME */
-
- /* Synchronize all actions with core settings */
- resyncLabelActions(app);
- resyncRenderActions(app);
- resyncOrbitActions(app);
- resyncVerbosityActions(app);
- resyncAmbientActions(app);
- resyncStarStyleActions(app);
-
- /* If full-screen at startup, make it so. */
- if (app->fullScreen)
- gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(app->agMain, "FullScreen")), TRUE);
- /* If framerate limiting is off, set it so. */
- if (!app->renderer->getVideoSync())
- gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(app->agMain, "VideoSync")), FALSE);
- /* If URL at startup, make it so. */
- if (app->startURL != NULL)
- app->core->setStartURL(app->startURL);
-
- /* Set simulation time */
- app->core->start((double)time(NULL) / 86400.0 + (double)astro::Date(1970, 1, 1));
- updateTimeZone(app, app->showLocalTime);
-
- /* Setting time zone name not very useful, but makes space for "LT" status in
- * the top-right corner. Set to some default. */
- app->core->setTimeZoneName("UTC");
- /* Set the cursor to a crosshair */
- gdk_window_set_cursor(widget->window, gdk_cursor_new(GDK_CROSSHAIR));
- }
- /* MAIN */
- int main(int argc, char* argv[])
- {
- /* Initialize the structure that holds the application's vitals. */
- AppData* app = g_new0(AppData, 1);
- /* Not ready to render yet. */
- app->bReady = FALSE;
- /* Initialize variables in the AppData structure. */
- app->lastX = 0;
- app->lastY = 0;
- app->showLocalTime = FALSE;
- app->fullScreen = FALSE;
- app->startURL = NULL;
- /* 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;
- program = gnome_program_init("Celestia", VERSION, LIBGNOMEUI_MODULE,
- argc, argv, GNOME_PARAM_NONE);
- #else
- /* GTK-Only Initialization */
- gtk_init(&argc, &argv);
- #endif
- /* Turn on the splash screen */
- SplashData* ss = splashStart(app, !noSplash);
- splashSetText(ss, "Initializing...");
- SetDebugVerbosity(0);
- /* Force number displays into C locale. */
- setlocale(LC_NUMERIC, "C");
- setlocale(LC_ALL, "");
- #ifndef WIN32
- bindtextdomain(PACKAGE, LOCALEDIR);
- bind_textdomain_codeset(PACKAGE, "UTF-8");
- textdomain(PACKAGE);
- #endif /* WIN32 */
- app->core = new CelestiaCore();
- if (app->core == NULL)
- {
- cerr << "Failed to initialize Celestia core.n";
- return 1;
- }
- app->renderer = app->core->getRenderer();
- g_assert(app->renderer);
-
- /* Parse simulation arguments */
- string cf;
- if (configFile != NULL)
- cf = string(configFile);
-
- string* altConfig = (configFile != NULL) ? &cf : NULL;
- vector<string> 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))
- return 1;
-
- app->simulation = app->core->getSimulation();
- g_assert(app->simulation);
-
- #ifdef GNOME
- /* Create the main window (GNOME) */
- app->mainWindow = gnome_app_new("Celestia", "Celestia");
- #else
- /* Create the main window (GTK) */
- app->mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(app->mainWindow), "Celestia");
- #endif /* GNOME */
- /* Set pointer to AppData structure. This is for when a function is in a
- * *real* bind to get at this structure. */
- g_object_set_data(G_OBJECT(app->mainWindow), "CelestiaData", app);
-
- GtkWidget* mainBox = GTK_WIDGET(gtk_vbox_new(FALSE, 0));
- gtk_container_set_border_width(GTK_CONTAINER(mainBox), 0);
- g_signal_connect(GTK_OBJECT(app->mainWindow), "destroy",
- G_CALLBACK(actionQuit), app);
- /* Initialize the OpenGL widget */
- gtk_gl_init (&argc, &argv);
- /* Configure OpenGL. Try double-buffered visual. */
- GdkGLConfig* glconfig = gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>
- (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
- if (glconfig == NULL)
- {
- g_print("*** Cannot find the double-buffered visual.n");
- g_print("*** Trying single-buffered visual.n");
- /* Try single-buffered visual */
- glconfig = gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>
- (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH));
- if (glconfig == NULL)
- {
- g_print ("*** No appropriate OpenGL-capable visual found.n");
- exit(1);
- }
- }
- /* Initialize settings system */
- #ifdef GNOME
- initSettingsGConf(app);
- #else
- initSettingsFile(app);
- #endif /* GNOME */
-
- /* Create area to be used for OpenGL display */
- app->glArea = gtk_drawing_area_new();
-
- /* Set OpenGL-capability to the widget. */
- gtk_widget_set_gl_capability(app->glArea,
- glconfig,
- NULL,
- TRUE,
- GDK_GL_RGBA_TYPE);
-
- gtk_widget_set_events(GTK_WIDGET(app->glArea),
- GDK_EXPOSURE_MASK |
- GDK_KEY_PRESS_MASK |
- GDK_KEY_RELEASE_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK);
- /* Load settings the can be applied before the simulation is initialized */
- #ifdef GNOME
- applySettingsGConfPre(app, app->client);
- #else
- applySettingsFilePre(app, app->settingsFile);
- #endif /* GNOME */
- /* Full-Screen option from the command line (overrides above). */
- if (fullScreen)
- app->fullScreen = TRUE;
- /* Initialize handlers to all events in the glArea */
- initGLCallbacks(app);
- /* Handler than completes initialization when the glArea is realized */
- g_signal_connect(GTK_OBJECT(app->glArea), "realize",
- G_CALLBACK(initRealize), app);
- /* Create the main menu bar */
- createMainMenu(app->mainWindow, app);
-
- /* Initialize the context menu */
- initContext(app);
- /* Set context menu callback for the core */
- app->core->setContextMenuCallback(menuContext);
-
- #ifdef GNOME
- /* Set window contents (GNOME) */
- gnome_app_set_contents((GnomeApp *)app->mainWindow, GTK_WIDGET(mainBox));
- #else
- /* Set window contents (GTK) */
- gtk_container_add(GTK_CONTAINER(app->mainWindow), GTK_WIDGET(mainBox));
- #endif /* GNOME */
- gtk_box_pack_start(GTK_BOX(mainBox), app->mainMenu, FALSE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(mainBox), app->glArea, TRUE, TRUE, 0);
- gtk_window_set_default_icon_from_file("celestia-logo.png", NULL);
- /* Set focus to glArea widget */
- GTK_WIDGET_SET_FLAGS(app->glArea, GTK_CAN_FOCUS);
- gtk_widget_grab_focus(GTK_WIDGET(app->glArea));
- /* Initialize the Watcher */
- gtkWatcher = new GtkWatcher(app->core, app);
- /* Unload the splash screen */
- splashEnd(ss);
- gtk_widget_show_all(app->mainWindow);
- /* HACK: Now that window is drawn, set minimum window size */
- gtk_widget_set_size_request(app->glArea, 320, 240);
- #ifdef GNOME
- initSettingsGConfNotifiers(app);
- #endif /* GNOME */
-
- /* Set the ready flag */
- app->bReady = TRUE;
-
- /* Call Main GTK Loop */
- gtk_main();
-
- g_free(app);
- return 0;
- }
- #ifdef WIN32
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- return main(__argc, __argv);
- }
- #endif /* WIN32 */