1
0
Fork 0
flightgear/src/GUI/gui_funcs.cxx
curt 3ad6d87576 FGIO::shutdown_all() is called from the FGIO destructor so we don't want
a seperate explicite call or the io channels will be forced to try to shutdown
twice which could cause problems for some IO modules (i.e. attempting to
close an invalid file descriptor the second time ...)
2004-12-29 20:38:17 +00:00

830 lines
23 KiB
C++

/**************************************************************************
* 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 <config.h>
#endif
#include <simgear/compiler.h>
#ifdef SG_MATH_EXCEPTION_CLASH
# include <math.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#include SG_GL_H
#if defined(FX) && defined(XMESA)
# include <GL/xmesa.h>
#endif
#include STL_FSTREAM
#include STL_STRING
#include <stdlib.h>
#include <string.h>
// for help call back
#ifdef WIN32
# include <shellapi.h>
# ifdef __CYGWIN__
# include <sys/cygwin.h>
# endif
#endif
#include <plib/ssg.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/screen/screen-dump.hxx>
#include <Include/general.hxx>
#include <Aircraft/aircraft.hxx>
#include <Airports/simple.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Cockpit/panel.hxx>
#include <Controls/controls.hxx>
#include <FDM/flight.hxx>
#include <Main/main.hxx>
#include <Main/fg_init.hxx>
#include <Main/fg_io.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Main/viewmgr.hxx>
#if defined( WIN32 ) && !defined( __CYGWIN__ ) && !defined(__MINGW32__)
# include <simgear/screen/win32-printer.h>
# include <simgear/screen/GlBitmaps.h>
#endif
#include "gui.h"
#include "gui_local.hxx"
#include "preset_dlg.hxx"
#include "prop_picker.hxx"
#include "sgVec3Slider.hxx"
SG_USING_STD(string);
SG_USING_STD(cout);
extern void fgHUDalphaAdjust( puObject * );
// from cockpit.cxx
extern void fgLatLonFormatToggle( puObject *);
#if defined( TR_HIRES_SNAP)
#include <simgear/screen/tr.h>
extern void fgUpdateHUD( GLfloat x_start, GLfloat y_start,
GLfloat x_end, GLfloat y_end );
#endif
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];
const __fg_gui_fn_t __fg_gui_fn[] = {
// File
{"saveFlight", saveFlight},
{"loadFlight", loadFlight},
{"reInit", reInit},
#ifdef TR_HIRES_SNAP
{"dumpHiResSnapShot", fgHiResDumpWrapper},
#endif
{"dumpSnapShot", fgDumpSnapShotWrapper},
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__)
{"printScreen", printScreen},
#endif
{"MayBeGoodBye", MayBeGoodBye},
//View
{"guiTogglePanel", guiTogglePanel},
{"PilotOffsetAdjust", PilotOffsetAdjust},
{"fgHUDalphaAdjust", fgHUDalphaAdjust},
{"prop_pickerView", prop_pickerView},
// Environment
{"fgPresetAirport", fgPresetAirport},
{"fgPresetRunway", fgPresetRunway},
{"fgPresetOffsetDistance", fgPresetOffsetDistance},
{"fgPresetAltitude", fgPresetAltitude},
{"fgPresetGlideslope", fgPresetGlideslope},
{"fgPresetAirspeed", fgPresetAirspeed},
{"fgPresetCommit", fgPresetCommit},
// Autopilot
{"NewAltitude", NewAltitude},
{"NewHeading", NewHeading},
{"AddWayPoint", AddWayPoint},
{"PopWayPoint", PopWayPoint},
{"ClearRoute", ClearRoute},
{"fgLatLonFormatToggle", fgLatLonFormatToggle},
// Help
{"helpCb", helpCb},
// Structure termination
{"", NULL}
};
/* ================ 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());
}
// 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 <nedz@bigpond.com>
// 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);
globals->get_renderer()->resize(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
}
void goodBye(puObject *)
{
// SG_LOG( SG_INPUT, SG_ALERT,
// "Program exiting normally at user request." );
cout << "Program exiting normally at user request." << endl;
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 += " &";
system( command.c_str() );
#else // WIN32
// Look for favorite browser
char Dummy[1024], ExecName[1024], browserParameter[1024];
char win32_name[1024];
# ifdef __CYGWIN__
cygwin32_conv_to_full_win32_path(path.c_str(),win32_name);
# else
strcpy(win32_name,path.c_str());
# endif
Dummy[0] = 0;
FindExecutable(win32_name, Dummy, ExecName);
sprintf(browserParameter, "file:///%s", win32_name);
ShellExecute ( NULL, "open", ExecName, browserParameter, Dummy,
SW_SHOWNORMAL ) ;
#endif
mkDialog ("Help started in your web browser window.");
}
#if defined( TR_HIRES_SNAP)
void fgHiResDump()
{
FILE *f;
string message;
bool show_pu_cursor = 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);
}
TurnCursorOff();
if ( !puCursorIsHidden() ) {
show_pu_cursor = true;
puHideCursor();
}
FGRenderer *renderer = globals->get_renderer();
renderer->init();
renderer->resize( 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
renderer->update( true );
renderer->update( true );
// 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 = fgGetInt("/sim/startup/hires-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 = globals->get_current_panel()->getWidth() / ncols;
GLfloat panel_row_step = globals->get_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);
renderer->update( false );
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)
globals->get_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;i<height;i++) {
memcpy(buffer + i*bytesPerImageRow + xOffset, /* Dest */
tile + i*bytesPerTileRow, /* Src */
bytesPerCurrentTileRow); /* Byte count*/
}
if (curColumn == trGet(tr, TR_COLUMNS)-1) {
/* write this buffered row of tiles to the file */
int curTileHeight = trGet(tr, TR_CURRENT_TILE_HEIGHT);
int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte);
int i;
for (i=0;i<curTileHeight;i++) {
/* Remember, OpenGL images are bottom to top. Have to reverse. */
GLubyte *rowPtr = buffer + (curTileHeight-1-i) * bytesPerImageRow;
fwrite(rowPtr, 1, imageWidth*3, f);
}
}
}
renderer->resize( width, height );
trDelete(tr);
fclose(f);
message = "Snap shot saved to ";
message += filename;
mkDialog (message.c_str());
free(tile);
free(buffer);
// message = "Snap shot saved to ";
// message += filename;
// mkDialog (message.c_str());
delete [] filename;
if ( show_pu_cursor ) {
puShowCursor();
}
TurnCursorOn();
if ( !freeze ) {
fgSetBool("/sim/freeze/master", false);
}
}
#endif // #if defined( TR_HIRES_SNAP)
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__)
void rotateView( double roll, double pitch, double yaw )
{
// rotate view
}
GlBitmap *b1 = NULL;
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);
globals->get_renderer()->init();
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++ ) {
globals->get_renderer()->resize( cur_width, cur_height );
// pan to tile
rotateView( 0, (y*fov)-((multiplier-1)*fov/2), (x*fov)-((multiplier-1)*fov/2) );
globals->get_renderer()->update( false );
// 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 );
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) );
// BusyCursor(1);
if ( show_pu_cursor ) {
puShowCursor();
}
TurnCursorOn();
}
#endif // #ifdef WIN32
void fgDumpSnapShotWrapper ( puObject *obj ) {
fgDumpSnapShot();
}
void fgHiResDumpWrapper ( 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);
}
TurnCursorOff();
if ( !puCursorIsHidden() ) {
show_pu_cursor = true;
puHideCursor();
}
FGRenderer *renderer = globals->get_renderer();
renderer->init();
renderer->resize( 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
renderer->update( true );
renderer->update( true );
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 ( !freeze ) {
fgSetBool("/sim/freeze/master", false);
}
}