From: david Date: Thu, 8 Aug 2002 23:25:47 +0000 (+0000) Subject: XML-configurable menu support from Erik Hofman. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=f0e40fa3f8b33e97ec9a0692c268b653b7d9f8b8;p=flightgear.git XML-configurable menu support from Erik Hofman. [dpm: removed an attempt to free a pointer to a function] --- diff --git a/src/GUI/Makefile.am b/src/GUI/Makefile.am index 850dce46a..7140523c8 100644 --- a/src/GUI/Makefile.am +++ b/src/GUI/Makefile.am @@ -8,7 +8,7 @@ endif libGUI_a_SOURCES = \ apt_dlg.cxx apt_dlg.hxx \ - gui.cxx gui.h \ + gui.cxx gui.h gui_funcs.cxx \ gui_local.cxx gui_local.hxx \ mouse.cxx \ $(NETWORK_SRCS) \ diff --git a/src/GUI/gui.cxx b/src/GUI/gui.cxx index 847c8e0fb..e14f94315 100644 --- a/src/GUI/gui.cxx +++ b/src/GUI/gui.cxx @@ -97,869 +97,197 @@ extern void fgInitVisuals( void ); extern void fgReshape( int width, int height ); extern void fgRenderFrame( void ); +extern void initDialog (void); +extern void mkDialogInit (void); +extern void ConfirmExitDialogInit(void); + + puFont guiFnt = 0; fntTexFont *guiFntHandle = 0; int gui_menu_on = 0; -static puMenuBar *mainMenuBar = 0; +puMenuBar *mainMenuBar = 0; //static puButton *hideMenuButton = 0; -static puDialogBox *dialogBox = 0; -static puFrame *dialogFrame = 0; -static puText *dialogBoxMessage = 0; -static puOneShot *dialogBoxOkButton = 0; - - -static puDialogBox *YNdialogBox = 0; -static puFrame *YNdialogFrame = 0; -static puText *YNdialogBoxMessage = 0; -static puOneShot *YNdialogBoxOkButton = 0; -static puOneShot *YNdialogBoxNoButton = 0; - -static char msg_OK[] = "OK"; -static char msg_NO[] = "NO"; -static char msg_YES[] = "YES"; -static char msg_CANCEL[] = "Cancel"; -static char msg_RESET[] = "Reset"; - -char *gui_msg_OK; // "OK" -char *gui_msg_NO; // "NO" -char *gui_msg_YES; // "YES" -char *gui_msg_CANCEL; // "CANCEL" -char *gui_msg_RESET; // "RESET" - -static char global_dialog_string[256]; - // from cockpit.cxx extern void fgLatLonFormatToggle( puObject *); - -/* ================ General Purpose Functions ================ */ - -// Intercept the Escape Key -void ConfirmExitDialog(void) -{ - FG_PUSH_PUI_DIALOG( YNdialogBox ); -} - -// General Purpose Message Box -void mkDialog (const char *txt) -{ - strncpy(global_dialog_string, txt, 256); - dialogBoxMessage->setLabel(global_dialog_string); - FG_PUSH_PUI_DIALOG( dialogBox ); -} - -// Message Box to report an error. -void guiErrorMessage (const char *txt) -{ - SG_LOG(SG_GENERAL, SG_ALERT, txt); - if (dialogBox != 0) - mkDialog(txt); -} - -// Message Box to report a throwable (usually an exception). -void guiErrorMessage (const char *txt, const sg_throwable &throwable) -{ - string msg = txt; - msg += '\n'; - msg += throwable.getFormattedMessage(); - if (!throwable.getOrigin().empty()) { - msg += "\n (reported by "; - msg += throwable.getOrigin(); - msg += ')'; - } - SG_LOG(SG_GENERAL, SG_ALERT, msg); - if (dialogBox != 0) - mkDialog(msg.c_str()); -} - -// Toggle the Menu and Mouse display state -void guiToggleMenu(void) -{ - if( gui_menu_on ) { - // printf("Hiding Menu\n"); - mainMenuBar->hide (); -#if defined(WIN32_CURSOR_TWEAKS_OFF) - if( mouse_mode == MOUSE_POINTER ) - TurnCursorOff(); -#endif // WIN32_CURSOR_TWEAKS_OFF - } else { - // printf("Showing Menu\n"); - mainMenuBar->reveal(); -#ifdef WIN32 - TurnCursorOn(); -#endif // WIN32 - } - gui_menu_on = ~gui_menu_on; -} - -/* ----------------------------------------------------------------------- -the Gui callback functions -____________________________________________________________________*/ - - -// Hier Neu :-) This is my newly added code -// Added by David Findlay -// on Sunday 3rd of December - -// Start new Save Dialog Box -static puDialogBox *SaveDialog = 0; -static puFrame *SaveDialogFrame = 0; -static puText *SaveDialogMessage = 0; -static puInput *SaveDialogInput = 0; - -static puOneShot *SaveDialogOkButton = 0; -static puOneShot *SaveDialogCancelButton = 0; -// static puOneShot *SaveDialogResetButton = 0; - -// Default save filename -static char saveFile[256] = "fgfs.sav"; - -// Cancel Button -void SaveDialogCancel(puObject *) { - FG_POP_PUI_DIALOG( SaveDialog ); -} - -// If press OK do this -void SaveDialogOk(puObject*) { - - FG_POP_PUI_DIALOG( SaveDialog ); - - char *s; - SaveDialogInput->getValue(&s); - - ofstream output(s); - cout << saveFile << endl; - if (output.good() && fgSaveFlight(output)) { - output.close(); - mkDialog("Saved flight"); - SG_LOG(SG_INPUT, SG_INFO, "Saved flight"); - } else { - mkDialog("Cannot save flight"); - SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight"); - } -} - -// Create Dialog -static void saveFlight(puObject *cv) { - SaveDialog = new puDialogBox (150, 50); - { - SaveDialogFrame = new puFrame (0,0,350, 150); - SaveDialogMessage - = new puText( (150 - puGetDefaultLabelFont().getStringWidth( "File Name:" ) / 2), 110 ); - SaveDialogMessage -> setLabel ("File Name:"); - - SaveDialogInput = new puInput (50, 70, 300, 100); - SaveDialogInput -> setValue (saveFile); - SaveDialogInput -> acceptInput(); - - SaveDialogOkButton = new puOneShot (50, 10, 110, 50); - SaveDialogOkButton -> setLegend (gui_msg_OK); - SaveDialogOkButton -> setCallback ( SaveDialogOk ); - SaveDialogOkButton -> makeReturnDefault(TRUE); - - SaveDialogCancelButton = new puOneShot (140, 10, 210, 50); - SaveDialogCancelButton -> setLegend (gui_msg_CANCEL); - SaveDialogCancelButton -> setCallback ( SaveDialogCancel ); - } - FG_FINALIZE_PUI_DIALOG( SaveDialog ); - - SaveDialog -> reveal(); -} - -// Load Dialog Start -static puDialogBox *LoadDialog = 0; -static puFrame *LoadDialogFrame = 0; -static puText *LoadDialogMessage = 0; -static puInput *LoadDialogInput = 0; - -static puOneShot *LoadDialogOkButton = 0; -static puOneShot *LoadDialogCancelButton = 0; -// static puOneShot *LoadDialogResetButton = 0; - -// Default load filename -static char loadFile[256] = "fgfs.sav"; - -// Do this if the person click okay -void LoadDialogOk(puObject *) { - - FG_POP_PUI_DIALOG( LoadDialog ); - - char *l; - LoadDialogInput->getValue(&l); - - ifstream input(l); - if (input.good() && fgLoadFlight(input)) { - input.close(); - mkDialog("Loaded flight"); - SG_LOG(SG_INPUT, SG_INFO, "Restored flight"); - } else { - mkDialog("Failed to load flight"); - SG_LOG(SG_INPUT, SG_ALERT, "Cannot load flight"); - } -} - -// Do this if the person presses cancel -void LoadDialogCancel(puObject *) { - FG_POP_PUI_DIALOG( LoadDialog ); -} - -// Create Load Dialog -static void loadFlight(puObject *cb) -{ - LoadDialog = new puDialogBox (150, 50); - { - LoadDialogFrame = new puFrame (0,0,350, 150); - LoadDialogMessage - = new puText( (150 - puGetDefaultLabelFont().getStringWidth( "File Name:" ) / 2), 110 ); - LoadDialogMessage -> setLabel ("File Name:"); - - LoadDialogInput = new puInput (50, 70, 300, 100); - LoadDialogInput -> setValue (loadFile); - LoadDialogInput -> acceptInput(); - - LoadDialogOkButton = new puOneShot (50, 10, 110, 50); - LoadDialogOkButton -> setLegend (gui_msg_OK); - LoadDialogOkButton -> setCallback ( LoadDialogOk ); - LoadDialogOkButton -> makeReturnDefault(TRUE); - - LoadDialogCancelButton = new puOneShot (140, 10, 210, 50); - LoadDialogCancelButton -> setLegend (gui_msg_CANCEL); - LoadDialogCancelButton -> setCallback ( LoadDialogCancel ); - } - FG_FINALIZE_PUI_DIALOG( LoadDialog ); - - LoadDialog -> reveal(); -} - -// This is the accessor function -void guiTogglePanel(puObject *cb) -{ - if (fgGetBool("/sim/panel/visibility")) - fgSetBool("/sim/panel/visibility", false); - else - fgSetBool("/sim/panel/visibility", true); - - fgReshape(fgGetInt("/sim/startup/xsize"), - fgGetInt("/sim/startup/ysize")); -} - -//void MenuHideMenuCb(puObject *cb) -void hideMenuCb (puObject *cb) -{ - guiToggleMenu(); -} - -void goodBye(puObject *) -{ - // SG_LOG( SG_INPUT, SG_ALERT, - // "Program exiting normally at user request." ); - cout << "Program exiting normally at user request." << endl; - -#ifdef FG_NETWORK_OLK - if ( fgGetBool("/sim/networking/network-olk") ) { - if ( net_is_registered == 0 ) fgd_send_com( "8", FGFS_host); - } +// from gui_funcs.cxx +extern void saveFlight(puObject *); +extern void loadFlight(puObject *); +extern void reInit(puObject *); +extern void dumpSnapShot(puObject *); +#ifdef TR_HIRES_SNAP +extern void dumpHiResSnapShot(puObject *); #endif - - // close all external I/O connections - fgIOShutdownAll(); - - exit(0); -} - - -void goAwayCb (puObject *me) -{ - FG_POP_PUI_DIALOG( dialogBox ); -} - -void mkDialogInit (void) -{ - // printf("mkDialogInit\n"); - int x = (fgGetInt("/sim/startup/xsize")/2 - 400/2); - int y = (fgGetInt("/sim/startup/ysize")/2 - 100/2); - dialogBox = new puDialogBox (x, y); // 150, 50 - { - dialogFrame = new puFrame (0,0,400,100); - dialogBoxMessage = new puText (10, 70); - dialogBoxMessage -> setLabel (""); - dialogBoxOkButton = new puOneShot (180, 10, 240, 50); - dialogBoxOkButton -> setLegend (gui_msg_OK); - dialogBoxOkButton -> makeReturnDefault (TRUE ); - dialogBoxOkButton -> setCallback (goAwayCb); - } - FG_FINALIZE_PUI_DIALOG( dialogBox ); -} - -void MayBeGoodBye(puObject *) -{ - ConfirmExitDialog(); -} - -void goAwayYesNoCb(puObject *me) -{ - FG_POP_PUI_DIALOG( YNdialogBox); -} - -void ConfirmExitDialogInit(void) -{ - char msg[] = "Really Quit"; - char *s; - - // printf("ConfirmExitDialogInit\n"); - int len = 200 - puGetDefaultLabelFont().getStringWidth ( msg ) / 2; - - int x = (fgGetInt("/sim/startup/xsize")/2 - 400/2); - int y = (fgGetInt("/sim/startup/ysize")/2 - 100/2); - - YNdialogBox = new puDialogBox (x, y); // 150, 50 - { - YNdialogFrame = new puFrame (0,0,400, 100); - - YNdialogBoxMessage = new puText (len, 70); - YNdialogBoxMessage -> setDefaultValue (msg); - YNdialogBoxMessage -> getDefaultValue (&s); - YNdialogBoxMessage -> setLabel (s); - - YNdialogBoxOkButton = new puOneShot (100, 10, 160, 50); - YNdialogBoxOkButton -> setLegend (gui_msg_OK); - YNdialogBoxOkButton -> makeReturnDefault (TRUE ); - YNdialogBoxOkButton -> setCallback (goodBye); - - YNdialogBoxNoButton = new puOneShot (240, 10, 300, 50); - YNdialogBoxNoButton -> setLegend (gui_msg_NO); - YNdialogBoxNoButton -> setCallback (goAwayYesNoCb); - } - FG_FINALIZE_PUI_DIALOG( YNdialogBox ); -} - -void notCb (puObject *) -{ - mkDialog ("This function isn't implemented yet"); -} - -void helpCb (puObject *) -{ - string command; - -#if defined(FX) && !defined(WIN32) -# if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW) - if ( globals->get_fullscreen() ) { - globals->set_fullscreen(false); - XMesaSetFXmode( XMESA_FX_WINDOW ); - } -# endif +#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) +extern void printScreen(puObject *); #endif - - SGPath path( globals->get_fg_root() ); - path.append( "Docs/index.html" ); - -#if !defined(WIN32) - string help_app = fgGetString("/sim/startup/browser-app"); - - if ( system("xwininfo -name Netscape > /dev/null 2>&1") == 0 ) { - command = help_app + " -remote \"openURL(" + path.str() + ")\""; - } else { - command = help_app + " " + path.str(); - } - command += " &"; -#else // WIN32 - command = "start "; - command += path.str(); +extern void MayBeGoodBye(puObject *); +extern void guiTogglePanel(puObject *); +extern void PilotOffsetAdjust(puObject *); +extern void fgHUDalphaAdjust(puObject *); +extern void prop_pickerView(puObject *); +extern void NewAirport(puObject *); +#ifdef FG_NETWORK_OLK +extern void net_display_toggle(puObject *); +extern void NewCallSign(puObject *); +extern void net_fgd_scan(puObject *); +extern void net_register(puObject *); +extern void net_unregister(puObject *); #endif - - system( command.c_str() ); - mkDialog ("Help started in netscape window."); -} - -#define TR_HIRES_SNAP -#if defined( TR_HIRES_SNAP) -#include -extern void trRenderFrame( void ); -extern void fgUpdateHUD( GLfloat x_start, GLfloat y_start, - GLfloat x_end, GLfloat y_end ); - -void fgHiResDump() -{ - FILE *f; - string message; - bool show_pu_cursor = false; - bool show_menu = false; - char *filename = new char [24]; - static int count = 1; - - static const SGPropertyNode *master_freeze - = fgGetNode("/sim/freeze/master"); - - bool freeze = master_freeze->getBoolValue(); - if ( !freeze ) { - fgSetBool("/sim/freeze/master", true); - } - - if(gui_menu_on) { - show_menu = true; - guiToggleMenu(); - } - - if ( !puCursorIsHidden() ) { - show_pu_cursor = true; - puHideCursor(); - } - - fgInitVisuals(); - fgReshape( fgGetInt("/sim/startup/xsize"), - fgGetInt("/sim/startup/ysize") ); - - // we need two render frames here to clear the menu and cursor - // ... not sure why but doing an extra fgRenderFrame() shouldn't - // hurt anything - fgRenderFrame(); - fgRenderFrame(); - - // Make sure we have SSG projection primed for current view - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - ssgSetCamera( (sgVec4 *)globals->get_current_view()->get_VIEW() ); - ssgSetFOV( globals->get_current_view()->get_h_fov(), - globals->get_current_view()->get_v_fov() ); - // ssgSetNearFar( 10.0f, 120000.0f ); - ssgSetNearFar( 0.5f, 1200000.0f ); - - - // This ImageSize stuff is a temporary hack - // should probably use 128x128 tile size and - // support any image size - - // This should be a requester to get multiplier from user - int multiplier = 3; - int width = fgGetInt("/sim/startup/xsize"); - int height = fgGetInt("/sim/startup/ysize"); - - /* allocate buffer large enough to store one tile */ - GLubyte *tile = (GLubyte *)malloc(width * height * 3 * sizeof(GLubyte)); - if (!tile) { - printf("Malloc of tile buffer failed!\n"); - return; - } - - int imageWidth = multiplier*width; - int imageHeight = multiplier*height; - - /* allocate buffer to hold a row of tiles */ - GLubyte *buffer - = (GLubyte *)malloc(imageWidth * height * 3 * sizeof(GLubyte)); - if (!buffer) { - free(tile); - printf("Malloc of tile row buffer failed!\n"); - return; - } - TRcontext *tr = trNew(); - trTileSize(tr, width, height, 0); - trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile); - trImageSize(tr, imageWidth, imageHeight); - trRowOrder(tr, TR_TOP_TO_BOTTOM); - sgFrustum *frustum = ssgGetFrustum(); - trFrustum(tr, - frustum->getLeft(), frustum->getRight(), - frustum->getBot(), frustum->getTop(), - frustum->getNear(), frustum->getFar()); - - /* Prepare ppm output file */ - while (count < 1000) { - snprintf(filename, 24, "fgfs-screen-%03d.ppm", count++); - if ( (f = fopen(filename, "r")) == NULL ) - break; - fclose(f); - } - f = fopen(filename, "wb"); - if (!f) { - printf("Couldn't open image file: %s\n", filename); - free(buffer); - free(tile); - return; - } - fprintf(f,"P6\n"); - fprintf(f,"# ppm-file created by %s\n", "trdemo2"); - fprintf(f,"%i %i\n", imageWidth, imageHeight); - fprintf(f,"255\n"); - - /* just to be safe... */ - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - /* Because the HUD and Panel change the ViewPort we will - * need to handle some lowlevel stuff ourselves */ - int ncols = trGet(tr, TR_COLUMNS); - int nrows = trGet(tr, TR_ROWS); - - bool do_hud = fgGetBool("/sim/hud/visibility"); - GLfloat hud_col_step = 640.0 / ncols; - GLfloat hud_row_step = 480.0 / nrows; - - bool do_panel = fgPanelVisible(); - GLfloat panel_col_step = current_panel->getWidth() / ncols; - GLfloat panel_row_step = current_panel->getHeight() / nrows; - - /* Draw tiles */ - int more = 1; - while (more) { - trBeginTile(tr); - int curColumn = trGet(tr, TR_CURRENT_COLUMN); - int curRow = trGet(tr, TR_CURRENT_ROW); - trRenderFrame(); - if ( do_hud ) - fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step, - (curColumn+1)*hud_col_step, (curRow+1)*hud_row_step ); - if (do_panel) - current_panel->update( curColumn*panel_col_step, panel_col_step, - curRow*panel_row_step, panel_row_step ); - more = trEndTile(tr); - - /* save tile into tile row buffer*/ - int curTileWidth = trGet(tr, TR_CURRENT_TILE_WIDTH); - int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte); - int bytesPerTileRow = (width) * 3*sizeof(GLubyte); - int xOffset = curColumn * bytesPerTileRow; - int bytesPerCurrentTileRow = (curTileWidth) * 3*sizeof(GLubyte); - int i; - for (i=0;iget_fg_root() ); + spath.append( "menu.xml" ); -static GlBitmap *b1 = NULL; -extern FGInterface cur_view_fdm; -GLubyte *hiResScreenCapture( int multiplier ) -{ - float oldfov = fgGetDouble("/sim/current-view/field-of-view"); - float fov = oldfov / multiplier; - FGViewer *v = globals->get_current_view(); - fgSetDouble("/sim/current-view/field-of-view", fov); - fgInitVisuals(); - int cur_width = fgGetInt("/sim/startup/xsize"); - int cur_height = fgGetInt("/sim/startup/ysize"); - if (b1) delete( b1 ); - // New empty (mostly) bitmap - b1 = new GlBitmap( GL_RGB, 1, 1, (unsigned char *)"123" ); - int x,y; - for ( y = 0; y < multiplier; y++ ) { - for ( x = 0; x < multiplier; x++ ) { - fgReshape( cur_width, cur_height ); - // pan to tile - rotateView( 0, (y*fov)-((multiplier-1)*fov/2), (x*fov)-((multiplier-1)*fov/2) ); - fgRenderFrame(); - // restore view - GlBitmap b2; - b1->copyBitmap( &b2, cur_width*x, cur_height*y ); - } - } - fgSetDouble("/sim/current-view/field-of-view", oldfov); - return b1->getBitmap(); -} -#endif + try { + readProperties(spath.c_str(), &main); + } catch (const sg_exception &ex) { + SG_LOG(SG_GENERAL, SG_ALERT, "Error processing the menu file."); + return; + } + SG_LOG(SG_GENERAL, SG_INFO, "Reading menu entries."); -#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) -// win32 print screen function -void printScreen ( puObject *obj ) { - bool show_pu_cursor = false; - TurnCursorOff(); - if ( !puCursorIsHidden() ) { - show_pu_cursor = true; - puHideCursor(); - } - // BusyCursor( 0 ); - mainMenuBar->hide(); + // Make the menu bar + mainMenuBar = new puMenuBar (); - CGlPrinter p( CGlPrinter::PRINT_BITMAP ); - int cur_width = fgGetInt("/sim/startup/xsize"); - int cur_height = fgGetInt("/sim/startup/ysize"); - p.Begin( "FlightGear", cur_width*3, cur_height*3 ); - p.End( hiResScreenCapture(3) ); - - if( gui_menu_on ) { - mainMenuBar->reveal(); - } - // BusyCursor(1); - if ( show_pu_cursor ) { - puShowCursor(); - } - TurnCursorOn(); -} -#endif // #ifdef WIN32 + SGPropertyNode *menu = main.getChild("menu"); + vectorsubmenu = menu->getChildren("submenu"); -void dumpSnapShot ( puObject *obj ) { - fgDumpSnapShot(); -} + Menu_size = 1+submenu.size(); + Menu = (fg_gui_t *)calloc(Menu_size, sizeof(fg_gui_t)); + for (unsigned int h = 0; h < submenu.size(); h++) { -void dumpHiResSnapShot ( puObject *obj ) { - fgHiResDump(); -} + vectoroption = submenu[h]->getChildren("option"); + // + // Make sure all entries will fit into allocated memory + // + Menu[h].submenu = (char **)calloc(1+option.size(), sizeof(char *)); + Menu[h].cb = (puCallback *)calloc(1+option.size(), sizeof(puCallback)); -// do a screen snap shot -void fgDumpSnapShot () { - bool show_pu_cursor = false; - char *filename = new char [24]; - string message; - static int count = 1; + for (unsigned int i = 0; i < option.size(); i++) { - static const SGPropertyNode *master_freeze - = fgGetNode("/sim/freeze/master"); + SGPropertyNode *name = option[i]->getNode("name"); + SGPropertyNode *call = option[i]->getNode("call"); + SGPropertyNode *sep = option[i]->getNode("seperator"); - bool freeze = master_freeze->getBoolValue(); - if ( !freeze ) { - fgSetBool("/sim/freeze/master", true); - } - - mainMenuBar->hide(); - TurnCursorOff(); - if ( !puCursorIsHidden() ) { - show_pu_cursor = true; - puHideCursor(); - } + if (sep) + Menu[h].submenu[i] = strdup("----------"); - fgInitVisuals(); - fgReshape( fgGetInt("/sim/startup/xsize"), - fgGetInt("/sim/startup/ysize") ); - - // we need two render frames here to clear the menu and cursor - // ... not sure why but doing an extra fgRenderFrame() shouldn't - // hurt anything - fgRenderFrame(); - fgRenderFrame(); - - while (count < 1000) { - FILE *fp; - snprintf(filename, 24, "fgfs-screen-%03d.ppm", count++); - if ( (fp = fopen(filename, "r")) == NULL ) - break; - fclose(fp); - } + else if (call && strcmp(call->getStringValue(), "")) + Menu[h].submenu[i] = strdup(name->getStringValue()); - if ( sg_glDumpWindow( filename, - fgGetInt("/sim/startup/xsize"), - fgGetInt("/sim/startup/ysize")) ) { - message = "Snap shot saved to "; - message += filename; - } else { - message = "Failed to save to "; - message += filename; - } + else + Menu[h].submenu[i] = strdup("not specified"); - mkDialog (message.c_str()); + Menu[h].cb[i] = NULL; + for (unsigned int j=0; __fg_gui_fn[j].fn; j++) + if (call && + !strcmp(call->getStringValue(), __fg_gui_fn[j].name) ) + { + Menu[h].cb[i] = __fg_gui_fn[j].fn; + break; + } + } - delete [] filename; + SGPropertyNode *name = submenu[h]->getNode("name"); - if ( show_pu_cursor ) { - puShowCursor(); - } + Menu[h].name = strdup(name->getStringValue()); + mainMenuBar->add_submenu(Menu[h].name, Menu[h].submenu, Menu[h].cb); - TurnCursorOn(); - if( gui_menu_on ) { - mainMenuBar->reveal(); } - if ( !freeze ) { - fgSetBool("/sim/freeze/master", false); - } + mainMenuBar->close(); } -#ifdef FG_NETWORK_OLK -static void net_display_toggle( puObject *cb) -{ - net_hud_display = (net_hud_display) ? 0 : 1; - printf("Toggle net_hud_display : %d\n", net_hud_display); -} - -static void net_register( puObject *cb) -{ - fgd_send_com( "1", FGFS_host ); - net_is_registered = 0; - printf("Registering to deamon\n"); -} - -static void net_unregister( puObject *cb) -{ - fgd_send_com( "8", FGFS_host ); - net_is_registered = -1; - printf("Unregistering from deamon\n"); -} - -extern void net_fgd_scan(puObject *cb); -#endif // #ifdef FG_NETWORK_OLK - -/* ----------------------------------------------------------------------- -The menu stuff ----------------------------------------------------------------------*/ -char *fileSubmenu [] = { - "Exit", /* "Close", "---------", */ -#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) - "Print", -#endif - "Snap Shot", - "Hires Snap Shot", - "---------", - "Reset", - "Load flight", - "Save flight", - NULL -}; -puCallback fileSubmenuCb [] = { - MayBeGoodBye, /* hideMenuCb, NULL, */ -#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) - printScreen, -#endif - /* NULL, notCb, */ - dumpSnapShot, - dumpHiResSnapShot, - NULL, - reInit, - loadFlight, - saveFlight, - NULL -}; - -/* -char *editSubmenu [] = { - "Edit text", NULL -}; -puCallback editSubmenuCb [] = { - notCb, NULL -}; -*/ - -extern void fgHUDalphaAdjust( puObject * ); -char *viewSubmenu [] = { - "Properties", - "HUD Alpha", - "Pilot Offset", - /* "Cockpit View > ", "View >","------------", */ - "Toggle Panel...", NULL -}; -puCallback viewSubmenuCb [] = { - prop_pickerView, - fgHUDalphaAdjust, - PilotOffsetAdjust, - /* notCb, notCb, NULL, */ - guiTogglePanel, NULL -}; - -// "---------", -char *autopilotSubmenu [] = { - "Toggle HUD Format", "Adjust AP Settings", - "---------", - "Clear Route", "Skip Current Waypoint", "Add Waypoint", - "---------", - "Set Altitude", "Set Heading", - NULL -}; +// FIXME: Has to be called from somewhere +// or better yet, turn the menu into a class of its own +void destroyMenu(void) { + for(unsigned int i=0; i < Menu_size; i++) { -puCallback autopilotSubmenuCb [] = { - fgLatLonFormatToggle, fgAPAdjust, - NULL, - ClearRoute, PopWayPoint, AddWayPoint, - NULL, - NewAltitude, NewHeading, - /* notCb, */ NULL -}; + free(Menu[i].name); -char *environmentSubmenu [] = { - "Goto Airport", /* "Terrain", "Weather", */ NULL -}; -puCallback environmentSubmenuCb [] = { - NewAirport, /* notCb, notCb, */ NULL -}; - -/* -char *optionsSubmenu [] = { - "Preferences", "Realism & Reliablity...", NULL -}; -puCallback optionsSubmenuCb [] = { - notCb, notCb, NULL -}; -*/ + // FIXME: don't use strdup/free + for(unsigned int j=0; Menu[i].submenu[j] != NULL; j++) + free(Menu[i].submenu[j]); + } +} -#ifdef FG_NETWORK_OLK -char *networkSubmenu [] = { - "Unregister from FGD ", /* "Send MSG to All", "Send MSG", "Show Pilots", */ - "Register to FGD", - "Scan for Deamons", "Enter Callsign", /* "Display Netinfos", */ - "Toggle Display", NULL -}; -puCallback networkSubmenuCb [] = { - /* notCb, notCb, notCb, notCb, */ - net_unregister, - net_register, - net_fgd_scan, NewCallSign, - net_display_toggle, NULL -}; -#endif -char *helpSubmenu [] = { - /* "About...", */ "Help", NULL -}; -puCallback helpSubmenuCb [] = { - /* notCb, */ helpCb, NULL -}; /* ------------------------------------------------------------------------- @@ -976,12 +304,7 @@ void guiInit() puSetDefaultStyle ( PUSTYLE_SMALL_BEVELLED ); //PUSTYLE_DEFAULT puSetDefaultColourScheme (0.8, 0.8, 0.8, 0.4); - // Initialize our GLOBAL GUI STRINGS - gui_msg_OK = msg_OK; // "OK" - gui_msg_NO = msg_NO; // "NO" - gui_msg_YES = msg_YES; // "YES" - gui_msg_CANCEL = msg_CANCEL; // "CANCEL" - gui_msg_RESET = msg_RESET; // "RESET" + initDialog(); // Next check home directory SGPath fntpath; @@ -994,7 +317,7 @@ void guiInit() } // Install our fast fonts - fntpath.append(fgGetString("/sim/font", "typewriter.txf")); + fntpath.append( "typewriter.txf" ); guiFntHandle = new fntTexFont ; guiFntHandle -> load ( (char *)fntpath.c_str() ) ; puFont GuiFont ( guiFntHandle, 15 ) ; @@ -1036,23 +359,10 @@ void guiInit() NewNetFGDInit(); #endif - mkDialogInit(); + mkDialogInit(); + + initMenu(); - // Make the menu bar - mainMenuBar = new puMenuBar (); - mainMenuBar -> add_submenu ("File", fileSubmenu, fileSubmenuCb); - // mainMenuBar -> add_submenu ("Edit", editSubmenu, editSubmenuCb); - mainMenuBar -> add_submenu ("View", viewSubmenu, viewSubmenuCb); - mainMenuBar -> add_submenu ("Environment", environmentSubmenu, environmentSubmenuCb); - mainMenuBar -> add_submenu ("Autopilot", autopilotSubmenu, autopilotSubmenuCb); - // mainMenuBar -> add_submenu ("Options", optionsSubmenu, optionsSubmenuCb); -#ifdef FG_NETWORK_OLK - if ( fgGetBool("/sim/networking/network-olk") ) { - mainMenuBar -> add_submenu ("Network", networkSubmenu, networkSubmenuCb); - } -#endif - mainMenuBar -> add_submenu ("Help", helpSubmenu, helpSubmenuCb); - mainMenuBar-> close (); // Set up menu bar toggle gui_menu_on = ~0; diff --git a/src/GUI/gui_funcs.cxx b/src/GUI/gui_funcs.cxx new file mode 100644 index 000000000..c3a05ed65 --- /dev/null +++ b/src/GUI/gui_funcs.cxx @@ -0,0 +1,862 @@ +/************************************************************************** + * gui_funcs.cxx + * + * Based on gui.cxx and renamed on 2002/08/13 by Erik Hofman. + * + * Written 1998 by Durk Talsma, started Juni, 1998. For the flight gear + * project. + * + * Additional mouse supported added by David Megginson, 1999. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + **************************************************************************/ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef SG_MATH_EXCEPTION_CLASH +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include + +#if defined(FX) && defined(XMESA) +# include +#endif + +#include STL_FSTREAM +#include STL_STRING + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include
+#include
+#include
+#include
+#include
+ +#ifdef FG_NETWORK_OLK +#include +#endif + +#if defined( WIN32 ) && !defined( __CYGWIN__ ) && !defined(__MINGW32__) +# include +# include +#endif + +#include "gui.h" +#include "gui_local.hxx" +#include "apt_dlg.hxx" +#include "net_dlg.hxx" +#include "sgVec3Slider.hxx" +#include "prop_picker.hxx" + +SG_USING_STD(string); + +#ifndef SG_HAVE_NATIVE_SGI_COMPILERS +SG_USING_STD(cout); +#endif + +// main.cxx hack, should come from an include someplace +extern void fgInitVisuals( void ); +extern void fgReshape( int width, int height ); +extern void fgRenderFrame( void ); + +extern FGInterface cur_view_fdm; +extern void fgHUDalphaAdjust( puObject * ); + +// from cockpit.cxx +extern void fgLatLonFormatToggle( puObject *); + +#ifdef FG_NETWORK_OLK +extern void net_fgd_scan(puObject *cb); +#endif // #ifdef FG_NETWORK_OLK + +#define TR_HIRES_SNAP 1 + +#if defined( TR_HIRES_SNAP) +#include +extern void trRenderFrame( void ); +extern void fgUpdateHUD( GLfloat x_start, GLfloat y_start, + GLfloat x_end, GLfloat y_end ); +#endif + +extern puMenuBar *mainMenuBar; + +puDialogBox *dialogBox = 0; +puFrame *dialogFrame = 0; +puText *dialogBoxMessage = 0; +puOneShot *dialogBoxOkButton = 0; + +puDialogBox *YNdialogBox = 0; +puFrame *YNdialogFrame = 0; +puText *YNdialogBoxMessage = 0; +puOneShot *YNdialogBoxOkButton = 0; +puOneShot *YNdialogBoxNoButton = 0; + +char *gui_msg_OK; // "OK" +char *gui_msg_NO; // "NO" +char *gui_msg_YES; // "YES" +char *gui_msg_CANCEL; // "CANCEL" +char *gui_msg_RESET; // "RESET" + +char msg_OK[] = "OK"; +char msg_NO[] = "NO"; +char msg_YES[] = "YES"; +char msg_CANCEL[] = "Cancel"; +char msg_RESET[] = "Reset"; + +char global_dialog_string[256]; + + +/* ================ General Purpose Functions ================ */ + +void initDialog(void) { + // Initialize our GLOBAL GUI STRINGS + gui_msg_OK = msg_OK; // "OK" + gui_msg_NO = msg_NO; // "NO" + gui_msg_YES = msg_YES; // "YES" + gui_msg_CANCEL = msg_CANCEL; // "CANCEL" + gui_msg_RESET = msg_RESET; // "RESET" +} + +// General Purpose Message Box +void mkDialog (const char *txt) +{ + strncpy(global_dialog_string, txt, 256); + dialogBoxMessage->setLabel(global_dialog_string); + FG_PUSH_PUI_DIALOG( dialogBox ); +} + +// Message Box to report an error. +void guiErrorMessage (const char *txt) +{ + SG_LOG(SG_GENERAL, SG_ALERT, txt); + if (dialogBox != 0) + mkDialog(txt); +} + +// Message Box to report a throwable (usually an exception). +void guiErrorMessage (const char *txt, const sg_throwable &throwable) +{ + string msg = txt; + msg += '\n'; + msg += throwable.getFormattedMessage(); + if (!throwable.getOrigin().empty()) { + msg += "\n (reported by "; + msg += throwable.getOrigin(); + msg += ')'; + } + SG_LOG(SG_GENERAL, SG_ALERT, msg); + if (dialogBox != 0) + mkDialog(msg.c_str()); +} + +// Toggle the Menu and Mouse display state +void guiToggleMenu(void) +{ + if( gui_menu_on ) { + // printf("Hiding Menu\n"); + mainMenuBar->hide (); +#if defined(WIN32_CURSOR_TWEAKS_OFF) + if( mouse_mode == MOUSE_POINTER ) + TurnCursorOff(); +#endif // WIN32_CURSOR_TWEAKS_OFF + } else { + // printf("Showing Menu\n"); + mainMenuBar->reveal(); +#ifdef WIN32 + TurnCursorOn(); +#endif // WIN32 + } + gui_menu_on = ~gui_menu_on; +} + +// Intercept the Escape Key +void ConfirmExitDialog(void) +{ + FG_PUSH_PUI_DIALOG( YNdialogBox ); +} + + + +/* ----------------------------------------------------------------------- +the Gui callback functions +____________________________________________________________________*/ + + +// Hier Neu :-) This is my newly added code +// Added by David Findlay +// on Sunday 3rd of December + +// Start new Save Dialog Box +puDialogBox *SaveDialog = 0; +puFrame *SaveDialogFrame = 0; +puText *SaveDialogMessage = 0; +puInput *SaveDialogInput = 0; + +puOneShot *SaveDialogOkButton = 0; +puOneShot *SaveDialogCancelButton = 0; +// static puOneShot *SaveDialogResetButton = 0; + +// Default save filename +char saveFile[256] = "fgfs.sav"; + +// Cancel Button +void SaveDialogCancel(puObject *) { + FG_POP_PUI_DIALOG( SaveDialog ); +} + +// If press OK do this +void SaveDialogOk(puObject*) { + + FG_POP_PUI_DIALOG( SaveDialog ); + + char *s; + SaveDialogInput->getValue(&s); + + ofstream output(s); + cout << saveFile << endl; + if (output.good() && fgSaveFlight(output)) { + output.close(); + mkDialog("Saved flight"); + SG_LOG(SG_INPUT, SG_INFO, "Saved flight"); + } else { + mkDialog("Cannot save flight"); + SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight"); + } +} + +// Create Dialog +void saveFlight(puObject *cv) { + SaveDialog = new puDialogBox (150, 50); + { + SaveDialogFrame = new puFrame (0,0,350, 150); + SaveDialogMessage + = new puText( (150 - puGetDefaultLabelFont().getStringWidth( "File Name:" ) / 2), 110 ); + SaveDialogMessage -> setLabel ("File Name:"); + + SaveDialogInput = new puInput (50, 70, 300, 100); + SaveDialogInput -> setValue (saveFile); + SaveDialogInput -> acceptInput(); + + SaveDialogOkButton = new puOneShot (50, 10, 110, 50); + SaveDialogOkButton -> setLegend (gui_msg_OK); + SaveDialogOkButton -> setCallback ( SaveDialogOk ); + SaveDialogOkButton -> makeReturnDefault(TRUE); + + SaveDialogCancelButton = new puOneShot (140, 10, 210, 50); + SaveDialogCancelButton -> setLegend (gui_msg_CANCEL); + SaveDialogCancelButton -> setCallback ( SaveDialogCancel ); + } + FG_FINALIZE_PUI_DIALOG( SaveDialog ); + + SaveDialog -> reveal(); +} + +// Load Dialog Start +puDialogBox *LoadDialog = 0; +puFrame *LoadDialogFrame = 0; +puText *LoadDialogMessage = 0; +puInput *LoadDialogInput = 0; + +puOneShot *LoadDialogOkButton = 0; +puOneShot *LoadDialogCancelButton = 0; +// static puOneShot *LoadDialogResetButton = 0; + +// Default load filename +char loadFile[256] = "fgfs.sav"; + +// Do this if the person click okay +void LoadDialogOk(puObject *) { + + FG_POP_PUI_DIALOG( LoadDialog ); + + char *l; + LoadDialogInput->getValue(&l); + + ifstream input(l); + if (input.good() && fgLoadFlight(input)) { + input.close(); + mkDialog("Loaded flight"); + SG_LOG(SG_INPUT, SG_INFO, "Restored flight"); + } else { + mkDialog("Failed to load flight"); + SG_LOG(SG_INPUT, SG_ALERT, "Cannot load flight"); + } +} + +// Do this if the person presses cancel +void LoadDialogCancel(puObject *) { + FG_POP_PUI_DIALOG( LoadDialog ); +} + +// Create Load Dialog +void loadFlight(puObject *cb) +{ + LoadDialog = new puDialogBox (150, 50); + { + LoadDialogFrame = new puFrame (0,0,350, 150); + LoadDialogMessage + = new puText( (150 - puGetDefaultLabelFont().getStringWidth( "File Name:" ) / 2), 110 ); + LoadDialogMessage -> setLabel ("File Name:"); + + LoadDialogInput = new puInput (50, 70, 300, 100); + LoadDialogInput -> setValue (loadFile); + LoadDialogInput -> acceptInput(); + + LoadDialogOkButton = new puOneShot (50, 10, 110, 50); + LoadDialogOkButton -> setLegend (gui_msg_OK); + LoadDialogOkButton -> setCallback ( LoadDialogOk ); + LoadDialogOkButton -> makeReturnDefault(TRUE); + + LoadDialogCancelButton = new puOneShot (140, 10, 210, 50); + LoadDialogCancelButton -> setLegend (gui_msg_CANCEL); + LoadDialogCancelButton -> setCallback ( LoadDialogCancel ); + } + FG_FINALIZE_PUI_DIALOG( LoadDialog ); + + LoadDialog -> reveal(); +} + +// This is the accessor function +void guiTogglePanel(puObject *cb) +{ + if (fgGetBool("/sim/panel/visibility")) + fgSetBool("/sim/panel/visibility", false); + else + fgSetBool("/sim/panel/visibility", true); + + fgReshape(fgGetInt("/sim/startup/xsize"), + fgGetInt("/sim/startup/ysize")); +} + +//void MenuHideMenuCb(puObject *cb) +void hideMenuCb (puObject *cb) +{ + guiToggleMenu(); +} + +void goodBye(puObject *) +{ + // SG_LOG( SG_INPUT, SG_ALERT, + // "Program exiting normally at user request." ); + cout << "Program exiting normally at user request." << endl; + +#ifdef FG_NETWORK_OLK + if ( fgGetBool("/sim/networking/network-olk") ) { + if ( net_is_registered == 0 ) fgd_send_com( "8", FGFS_host); + } +#endif + + // close all external I/O connections + fgIOShutdownAll(); + + exit(0); +} + + +void goAwayCb (puObject *me) +{ + FG_POP_PUI_DIALOG( dialogBox ); +} + +void mkDialogInit (void) +{ + // printf("mkDialogInit\n"); + int x = (fgGetInt("/sim/startup/xsize")/2 - 400/2); + int y = (fgGetInt("/sim/startup/ysize")/2 - 100/2); + dialogBox = new puDialogBox (x, y); // 150, 50 + { + dialogFrame = new puFrame (0,0,400,100); + dialogBoxMessage = new puText (10, 70); + dialogBoxMessage -> setLabel (""); + dialogBoxOkButton = new puOneShot (180, 10, 240, 50); + dialogBoxOkButton -> setLegend (gui_msg_OK); + dialogBoxOkButton -> makeReturnDefault (TRUE ); + dialogBoxOkButton -> setCallback (goAwayCb); + } + FG_FINALIZE_PUI_DIALOG( dialogBox ); +} + +void MayBeGoodBye(puObject *) +{ + ConfirmExitDialog(); +} + +void goAwayYesNoCb(puObject *me) +{ + FG_POP_PUI_DIALOG( YNdialogBox); +} + +void ConfirmExitDialogInit(void) +{ + char msg[] = "Really Quit"; + char *s; + + // printf("ConfirmExitDialogInit\n"); + int len = 200 - puGetDefaultLabelFont().getStringWidth ( msg ) / 2; + + int x = (fgGetInt("/sim/startup/xsize")/2 - 400/2); + int y = (fgGetInt("/sim/startup/ysize")/2 - 100/2); + + YNdialogBox = new puDialogBox (x, y); // 150, 50 + { + YNdialogFrame = new puFrame (0,0,400, 100); + + YNdialogBoxMessage = new puText (len, 70); + YNdialogBoxMessage -> setDefaultValue (msg); + YNdialogBoxMessage -> getDefaultValue (&s); + YNdialogBoxMessage -> setLabel (s); + + YNdialogBoxOkButton = new puOneShot (100, 10, 160, 50); + YNdialogBoxOkButton -> setLegend (gui_msg_OK); + YNdialogBoxOkButton -> makeReturnDefault (TRUE ); + YNdialogBoxOkButton -> setCallback (goodBye); + + YNdialogBoxNoButton = new puOneShot (240, 10, 300, 50); + YNdialogBoxNoButton -> setLegend (gui_msg_NO); + YNdialogBoxNoButton -> setCallback (goAwayYesNoCb); + } + FG_FINALIZE_PUI_DIALOG( YNdialogBox ); +} + +void notCb (puObject *) +{ + mkDialog ("This function isn't implemented yet"); +} + +void helpCb (puObject *) +{ + string command; + +#if defined(FX) && !defined(WIN32) +# if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW) + if ( globals->get_fullscreen() ) { + globals->set_fullscreen(false); + XMesaSetFXmode( XMESA_FX_WINDOW ); + } +# endif +#endif + + SGPath path( globals->get_fg_root() ); + path.append( "Docs/index.html" ); + +#if !defined(WIN32) + string help_app = fgGetString("/sim/startup/browser-app"); + + if ( system("xwininfo -name Netscape > /dev/null 2>&1") == 0 ) { + command = help_app + " -remote \"openURL(" + path.str() + ")\""; + } else { + command = help_app + " " + path.str(); + } + command += " &"; +#else // WIN32 + command = "start "; + command += path.str(); +#endif + + system( command.c_str() ); + mkDialog ("Help started in netscape window."); +} + +#if defined( TR_HIRES_SNAP) +void fgHiResDump() +{ + FILE *f; + string message; + bool show_pu_cursor = false; + bool show_menu = false; + char *filename = new char [24]; + static int count = 1; + + static const SGPropertyNode *master_freeze + = fgGetNode("/sim/freeze/master"); + + bool freeze = master_freeze->getBoolValue(); + if ( !freeze ) { + fgSetBool("/sim/freeze/master", true); + } + + if(gui_menu_on) { + show_menu = true; + guiToggleMenu(); + } + + if ( !puCursorIsHidden() ) { + show_pu_cursor = true; + puHideCursor(); + } + + fgInitVisuals(); + fgReshape( fgGetInt("/sim/startup/xsize"), + fgGetInt("/sim/startup/ysize") ); + + // we need two render frames here to clear the menu and cursor + // ... not sure why but doing an extra fgRenderFrame() shouldn't + // hurt anything + fgRenderFrame(); + fgRenderFrame(); + + // Make sure we have SSG projection primed for current view + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + ssgSetCamera( (sgVec4 *)globals->get_current_view()->get_VIEW() ); + ssgSetFOV( globals->get_current_view()->get_h_fov(), + globals->get_current_view()->get_v_fov() ); + // ssgSetNearFar( 10.0f, 120000.0f ); + ssgSetNearFar( 0.5f, 1200000.0f ); + + + // This ImageSize stuff is a temporary hack + // should probably use 128x128 tile size and + // support any image size + + // This should be a requester to get multiplier from user + int multiplier = 3; + int width = fgGetInt("/sim/startup/xsize"); + int height = fgGetInt("/sim/startup/ysize"); + + /* allocate buffer large enough to store one tile */ + GLubyte *tile = (GLubyte *)malloc(width * height * 3 * sizeof(GLubyte)); + if (!tile) { + printf("Malloc of tile buffer failed!\n"); + return; + } + + int imageWidth = multiplier*width; + int imageHeight = multiplier*height; + + /* allocate buffer to hold a row of tiles */ + GLubyte *buffer + = (GLubyte *)malloc(imageWidth * height * 3 * sizeof(GLubyte)); + if (!buffer) { + free(tile); + printf("Malloc of tile row buffer failed!\n"); + return; + } + TRcontext *tr = trNew(); + trTileSize(tr, width, height, 0); + trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile); + trImageSize(tr, imageWidth, imageHeight); + trRowOrder(tr, TR_TOP_TO_BOTTOM); + sgFrustum *frustum = ssgGetFrustum(); + trFrustum(tr, + frustum->getLeft(), frustum->getRight(), + frustum->getBot(), frustum->getTop(), + frustum->getNear(), frustum->getFar()); + + /* Prepare ppm output file */ + while (count < 1000) { + snprintf(filename, 24, "fgfs-screen-%03d.ppm", count++); + if ( (f = fopen(filename, "r")) == NULL ) + break; + fclose(f); + } + f = fopen(filename, "wb"); + if (!f) { + printf("Couldn't open image file: %s\n", filename); + free(buffer); + free(tile); + return; + } + fprintf(f,"P6\n"); + fprintf(f,"# ppm-file created by %s\n", "trdemo2"); + fprintf(f,"%i %i\n", imageWidth, imageHeight); + fprintf(f,"255\n"); + + /* just to be safe... */ + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + /* Because the HUD and Panel change the ViewPort we will + * need to handle some lowlevel stuff ourselves */ + int ncols = trGet(tr, TR_COLUMNS); + int nrows = trGet(tr, TR_ROWS); + + bool do_hud = fgGetBool("/sim/hud/visibility"); + GLfloat hud_col_step = 640.0 / ncols; + GLfloat hud_row_step = 480.0 / nrows; + + bool do_panel = fgPanelVisible(); + GLfloat panel_col_step = current_panel->getWidth() / ncols; + GLfloat panel_row_step = current_panel->getHeight() / nrows; + + /* Draw tiles */ + int more = 1; + while (more) { + trBeginTile(tr); + int curColumn = trGet(tr, TR_CURRENT_COLUMN); + int curRow = trGet(tr, TR_CURRENT_ROW); + trRenderFrame(); + if ( do_hud ) + fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step, + (curColumn+1)*hud_col_step, (curRow+1)*hud_row_step ); + if (do_panel) + current_panel->update( curColumn*panel_col_step, panel_col_step, + curRow*panel_row_step, panel_row_step ); + more = trEndTile(tr); + + /* save tile into tile row buffer*/ + int curTileWidth = trGet(tr, TR_CURRENT_TILE_WIDTH); + int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte); + int bytesPerTileRow = (width) * 3*sizeof(GLubyte); + int xOffset = curColumn * bytesPerTileRow; + int bytesPerCurrentTileRow = (curTileWidth) * 3*sizeof(GLubyte); + int i; + for (i=0;iget_current_view(); + fgSetDouble("/sim/current-view/field-of-view", fov); + fgInitVisuals(); + int cur_width = fgGetInt("/sim/startup/xsize"); + int cur_height = fgGetInt("/sim/startup/ysize"); + if (b1) delete( b1 ); + // New empty (mostly) bitmap + b1 = new GlBitmap( GL_RGB, 1, 1, (unsigned char *)"123" ); + int x,y; + for ( y = 0; y < multiplier; y++ ) { + for ( x = 0; x < multiplier; x++ ) { + fgReshape( cur_width, cur_height ); + // pan to tile + rotateView( 0, (y*fov)-((multiplier-1)*fov/2), (x*fov)-((multiplier-1)*fov/2) ); + fgRenderFrame(); + // restore view + GlBitmap b2; + b1->copyBitmap( &b2, cur_width*x, cur_height*y ); + } + } + fgSetDouble("/sim/current-view/field-of-view", oldfov); + return b1->getBitmap(); +} +#endif + +#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) +// win32 print screen function +void printScreen ( puObject *obj ) { + bool show_pu_cursor = false; + TurnCursorOff(); + if ( !puCursorIsHidden() ) { + show_pu_cursor = true; + puHideCursor(); + } + // BusyCursor( 0 ); + mainMenuBar->hide(); + + CGlPrinter p( CGlPrinter::PRINT_BITMAP ); + int cur_width = fgGetInt("/sim/startup/xsize"); + int cur_height = fgGetInt("/sim/startup/ysize"); + p.Begin( "FlightGear", cur_width*3, cur_height*3 ); + p.End( hiResScreenCapture(3) ); + + if( gui_menu_on ) { + mainMenuBar->reveal(); + } + // BusyCursor(1); + if ( show_pu_cursor ) { + puShowCursor(); + } + TurnCursorOn(); +} +#endif // #ifdef WIN32 + + +void dumpSnapShot ( puObject *obj ) { + fgDumpSnapShot(); +} + + +void dumpHiResSnapShot ( puObject *obj ) { + fgHiResDump(); +} + + +// do a screen snap shot +void fgDumpSnapShot () { + bool show_pu_cursor = false; + char *filename = new char [24]; + string message; + static int count = 1; + + static const SGPropertyNode *master_freeze + = fgGetNode("/sim/freeze/master"); + + bool freeze = master_freeze->getBoolValue(); + if ( !freeze ) { + fgSetBool("/sim/freeze/master", true); + } + + mainMenuBar->hide(); + TurnCursorOff(); + if ( !puCursorIsHidden() ) { + show_pu_cursor = true; + puHideCursor(); + } + + fgInitVisuals(); + fgReshape( fgGetInt("/sim/startup/xsize"), + fgGetInt("/sim/startup/ysize") ); + + // we need two render frames here to clear the menu and cursor + // ... not sure why but doing an extra fgRenderFrame() shouldn't + // hurt anything + fgRenderFrame(); + fgRenderFrame(); + + while (count < 1000) { + FILE *fp; + snprintf(filename, 24, "fgfs-screen-%03d.ppm", count++); + if ( (fp = fopen(filename, "r")) == NULL ) + break; + fclose(fp); + } + + if ( sg_glDumpWindow( filename, + fgGetInt("/sim/startup/xsize"), + fgGetInt("/sim/startup/ysize")) ) { + message = "Snap shot saved to "; + message += filename; + } else { + message = "Failed to save to "; + message += filename; + } + + mkDialog (message.c_str()); + + delete [] filename; + + if ( show_pu_cursor ) { + puShowCursor(); + } + + TurnCursorOn(); + if( gui_menu_on ) { + mainMenuBar->reveal(); + } + + if ( !freeze ) { + fgSetBool("/sim/freeze/master", false); + } +} + +#ifdef FG_NETWORK_OLK +void net_display_toggle( puObject *cb) +{ + net_hud_display = (net_hud_display) ? 0 : 1; + printf("Toggle net_hud_display : %d\n", net_hud_display); +} + +void net_register( puObject *cb) +{ + fgd_send_com( "1", FGFS_host ); + net_is_registered = 0; + printf("Registering to deamon\n"); +} + +void net_unregister( puObject *cb) +{ + fgd_send_com( "8", FGFS_host ); + net_is_registered = -1; + printf("Unregistering from deamon\n"); +} + +#endif // #ifdef FG_NETWORK_OLK