1
0
Fork 0

Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/flightgear into next

This commit is contained in:
Erik Hofman 2017-03-23 12:52:23 +01:00
commit d13a7b2ddb
9 changed files with 634 additions and 548 deletions

View file

@ -6,6 +6,7 @@ endif (MSVC)
set(SOURCES set(SOURCES
bootstrap.cxx bootstrap.cxx
fg_commands.cxx fg_commands.cxx
fg_scene_commands.cxx
fg_init.cxx fg_init.cxx
fg_io.cxx fg_io.cxx
fg_os_common.cxx fg_os_common.cxx

View file

@ -15,31 +15,24 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_random.h> #include <simgear/math/sg_random.h>
#include <simgear/io/iostreams/sgstream.hxx> #include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/structure/commands.hxx> #include <simgear/structure/commands.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/structure/event_mgr.hxx> #include <simgear/structure/event_mgr.hxx>
#include <simgear/sound/soundmgr.hxx>
#include <simgear/timing/sg_time.hxx> #include <simgear/timing/sg_time.hxx>
#include <Network/RemoteXMLRequest.hxx> #include <Network/RemoteXMLRequest.hxx>
#include <FDM/flight.hxx> #include <FDM/flight.hxx>
#include <GUI/gui.h>
#include <GUI/new_gui.hxx>
#include <GUI/dialog.hxx>
#include <Aircraft/replay.hxx> #include <Aircraft/replay.hxx>
#include <Scenery/scenery.hxx>
#include <Scripting/NasalSys.hxx> #include <Scripting/NasalSys.hxx>
#include <Sound/sample_queue.hxx>
#include <Airports/xmlloader.hxx> #include <Airports/xmlloader.hxx>
#include <Network/HTTPClient.hxx> #include <Network/HTTPClient.hxx>
#include <Viewer/viewmgr.hxx> #include <Viewer/viewmgr.hxx>
#include <Viewer/view.hxx> #include <Viewer/view.hxx>
#include <Environment/presets.hxx> #include <Environment/presets.hxx>
#include <Navaids/NavDataCache.hxx> #include <Navaids/NavDataCache.hxx>
#include <GUI/gui.h>
#include "fg_init.hxx" #include "fg_init.hxx"
#include "fg_io.hxx" #include "fg_io.hxx"
@ -58,10 +51,6 @@
# include <google/profiler.h> # include <google/profiler.h>
#endif #endif
#if defined(HAVE_QT)
#include <GUI/QtLauncher.hxx>
#endif
using std::string; using std::string;
using std::ifstream; using std::ifstream;
using std::ofstream; using std::ofstream;
@ -188,54 +177,6 @@ do_nasal (const SGPropertyNode * arg)
return ((FGNasalSys*)globals->get_subsystem("nasal"))->handleCommand(arg); return ((FGNasalSys*)globals->get_subsystem("nasal"))->handleCommand(arg);
} }
/**
* Built-in command: exit FlightGear.
*
* status: the exit status to return to the operating system (defaults to 0)
*/
static bool
do_exit (const SGPropertyNode * arg)
{
SG_LOG(SG_INPUT, SG_INFO, "Program exit requested.");
fgSetBool("/sim/signals/exit", true);
globals->saveUserSettings();
fgOSExit(arg->getIntValue("status", 0));
return true;
}
/**
* Reset FlightGear (Shift-Escape or Menu->File->Reset)
*/
static bool
do_reset (const SGPropertyNode * arg)
{
fgResetIdleState();
return true;
}
/**
* Change aircraft
*/
static bool
do_switch_aircraft (const SGPropertyNode * arg)
{
fgSetString("/sim/aircraft", arg->getStringValue("aircraft"));
// start a reset
fgResetIdleState();
return true;
}
/**
*/
static bool
do_reposition (const SGPropertyNode * arg)
{
fgStartReposition();
return true;
}
/** /**
* Built-in command: replay the FDR buffer * Built-in command: replay the FDR buffer
*/ */
@ -366,42 +307,6 @@ do_load_tape (const SGPropertyNode * arg)
return true; return true;
} }
/**
* Built-in command: (re)load the panel.
*
* path (optional): the file name to load the panel from
* (relative to FG_ROOT). Defaults to the value of /sim/panel/path,
* and if that's unspecified, to "Panels/Default/default.xml".
*/
static bool
do_panel_load (const SGPropertyNode * arg)
{
string panel_path = arg->getStringValue("path");
if (!panel_path.empty()) {
// write to the standard property, which will force a load
fgSetString("/sim/panel/path", panel_path.c_str());
}
return true;
}
/**
* Built-in command: (re)load preferences.
*
* path (optional): the file name to load the panel from (relative
* to FG_ROOT). Defaults to "preferences.xml".
*/
static bool
do_preferences_load (const SGPropertyNode * arg)
{
// disabling this command which was formerly used to reload 'preferences.xml'
// reloading the defaults doesn't make sense (better to reset the simulator),
// and loading arbitrary XML docs into the property-tree can be done via
// the standard load-xml command.
SG_LOG(SG_GENERAL, SG_ALERT, "preferences-load command is deprecated and non-functional");
return false;
}
static void static void
do_view_next(bool do_it) do_view_next(bool do_it)
{ {
@ -424,17 +329,6 @@ do_view_prev(bool do_it)
} }
} }
/**
* An fgcommand to toggle fullscreen mode.
* No parameters.
*/
static bool
do_toggle_fullscreen(const SGPropertyNode *arg)
{
fgOSFullScreen();
return true;
}
/** /**
* Built-in command: cycle view. * Built-in command: cycle view.
*/ */
@ -446,112 +340,6 @@ do_view_cycle (const SGPropertyNode * arg)
return true; return true;
} }
/**
* Built-in command: capture screen.
*/
static bool
do_screen_capture (const SGPropertyNode * arg)
{
return fgDumpSnapShot();
}
static bool
do_reload_shaders (const SGPropertyNode*)
{
simgear::reload_shaders();
return true;
}
static bool
do_dump_scene_graph (const SGPropertyNode*)
{
fgDumpSceneGraph();
return true;
}
static bool
do_dump_terrain_branch (const SGPropertyNode*)
{
fgDumpTerrainBranch();
double lon_deg = fgGetDouble("/position/longitude-deg");
double lat_deg = fgGetDouble("/position/latitude-deg");
SGGeod geodPos = SGGeod::fromDegFt(lon_deg, lat_deg, 0.0);
SGVec3d zero = SGVec3d::fromGeod(geodPos);
SG_LOG(SG_INPUT, SG_INFO, "Model parameters:");
SG_LOG(SG_INPUT, SG_INFO, "Center: " << zero.x() << ", " << zero.y() << ", " << zero.z() );
SG_LOG(SG_INPUT, SG_INFO, "Rotation: " << lat_deg << ", " << lon_deg );
return true;
}
static bool
do_print_visible_scene_info(const SGPropertyNode*)
{
fgPrintVisibleSceneInfoCommand();
return true;
}
/**
* Built-in command: hires capture screen.
*/
static bool
do_hires_screen_capture (const SGPropertyNode * arg)
{
fgHiResDump();
return true;
}
/**
* Reload the tile cache.
*/
static bool
do_tile_cache_reload (const SGPropertyNode * arg)
{
SGPropertyNode *master_freeze = fgGetNode("/sim/freeze/master");
bool freeze = master_freeze->getBoolValue();
SG_LOG(SG_INPUT, SG_INFO, "ReIniting TileCache");
if ( !freeze ) {
master_freeze->setBoolValue(true);
}
globals->get_subsystem("tile-manager")->reinit();
if ( !freeze ) {
master_freeze->setBoolValue(false);
}
return true;
}
/**
* Reload the materials definition
*/
static bool
do_materials_reload (const SGPropertyNode * arg)
{
SG_LOG(SG_INPUT, SG_INFO, "Reloading Materials");
SGMaterialLib* new_matlib = new SGMaterialLib;
SGPath mpath( globals->get_fg_root() );
mpath.append( fgGetString("/sim/rendering/materials-file") );
bool loaded = new_matlib->load(globals->get_fg_root().local8BitStr(),
mpath.local8BitStr(),
globals->get_props());
if ( ! loaded ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Error loading materials file " << mpath );
return false;
}
globals->set_matlib(new_matlib);
FGScenery* scenery = static_cast<FGScenery*>(globals->get_scenery());
scenery->materialLibChanged();
return true;
}
/** /**
* Built-in command: toggle a bool property value. * Built-in command: toggle a bool property value.
* *
@ -894,188 +682,6 @@ do_data_logging_commit (const SGPropertyNode * arg)
return true; return true;
} }
/**
* Built-in command: Add a dialog to the GUI system. Does *not*
* display the dialog. The property node should have the same format
* as a dialog XML configuration. It must include:
*
* name: the name of the GUI dialog for future reference.
*/
static bool
do_dialog_new (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
if (!gui) {
return false;
}
// Note the casting away of const: this is *real*. Doing a
// "dialog-apply" command later on will mutate this property node.
// I'm not convinced that this isn't the Right Thing though; it
// allows client to create a node, pass it to dialog-new, and get
// the values back from the dialog by reading the same node.
// Perhaps command arguments are not as "const" as they would
// seem?
gui->newDialog((SGPropertyNode*)arg);
return true;
}
/**
* Built-in command: Show an XML-configured dialog.
*
* dialog-name: the name of the GUI dialog to display.
*/
static bool
do_dialog_show (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
gui->showDialog(arg->getStringValue("dialog-name"));
return true;
}
/**
* Built-in Command: Hide the active XML-configured dialog.
*/
static bool
do_dialog_close (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
if(arg->hasValue("dialog-name"))
return gui->closeDialog(arg->getStringValue("dialog-name"));
return gui->closeActiveDialog();
}
/**
* Update a value in the active XML-configured dialog.
*
* object-name: The name of the GUI object(s) (all GUI objects if omitted).
*/
static bool
do_dialog_update (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
FGDialog * dialog;
if (arg->hasValue("dialog-name"))
dialog = gui->getDialog(arg->getStringValue("dialog-name"));
else
dialog = gui->getActiveDialog();
if (dialog != 0) {
dialog->updateValues(arg->getStringValue("object-name"));
return true;
} else {
return false;
}
}
static bool
do_open_browser (const SGPropertyNode * arg)
{
string path;
if (arg->hasValue("path"))
path = arg->getStringValue("path");
else
if (arg->hasValue("url"))
path = arg->getStringValue("url");
else
return false;
return openBrowser(path);
}
static bool
do_open_launcher(const SGPropertyNode *)
{
#if defined(HAVE_QT)
bool ok = flightgear::runInAppLauncherDialog();
if (ok) {
// start a full reset
fgResetIdleState();
}
return true; // don't report failure
#else
return false;
#endif
}
/**
* Apply a value in the active XML-configured dialog.
*
* object-name: The name of the GUI object(s) (all GUI objects if omitted).
*/
static bool
do_dialog_apply (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
FGDialog * dialog;
if (arg->hasValue("dialog-name"))
dialog = gui->getDialog(arg->getStringValue("dialog-name"));
else
dialog = gui->getActiveDialog();
if (dialog != 0) {
dialog->applyValues(arg->getStringValue("object-name"));
return true;
} else {
return false;
}
}
/**
* Redraw GUI (applying new widget colors). Doesn't reload the dialogs,
* unlike reinit().
*/
static bool
do_gui_redraw (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
gui->redraw();
return true;
}
/**
* Adds model to the scenery. The path to the added branch (/models/model[*])
* is returned in property "property".
*/
static bool
do_add_model (const SGPropertyNode * arg)
{
SGPropertyNode * model = fgGetNode("models", true);
int i;
for (i = 0; model->hasChild("model",i); i++);
model = model->getChild("model", i, true);
copyProperties(arg, model);
if (model->hasValue("elevation-m"))
model->setDoubleValue("elevation-ft", model->getDoubleValue("elevation-m")
* SG_METER_TO_FEET);
model->getNode("load", true);
model->removeChildren("load");
const_cast<SGPropertyNode *>(arg)->setStringValue("property", model->getPath());
return true;
}
/**
* Built-in command: commit presets (read from in /sim/presets/)
*/
static bool
do_presets_commit (const SGPropertyNode * arg)
{
if (fgGetBool("/sim/initialized", false)) {
fgResetIdleState();
} else {
// Nasal can trigger this during initial init, which confuses
// the logic in ReInitSubsystems, since initial state has not been
// saved at that time. Short-circuit everything here.
flightgear::initPosition();
}
return true;
}
/** /**
* Built-in command: set log level (0 ... 7) * Built-in command: set log level (0 ... 7)
*/ */
@ -1087,21 +693,6 @@ do_log_level (const SGPropertyNode * arg)
return true; return true;
} }
/*
static bool
do_decrease_visibility (const SGPropertyNode * arg)
{
Environment::Presets::VisibilitySingleton::instance()->adjust( 0.9 );
return true;
}
static bool
do_increase_visibility (const SGPropertyNode * arg)
{
Environment::Presets::VisibilitySingleton::instance()->adjust( 1.1 );
return true;
}
*/
/** /**
* An fgcommand to allow loading of xml files via nasal, * An fgcommand to allow loading of xml files via nasal,
* the xml file's structure will be made available within * the xml file's structure will be made available within
@ -1253,49 +844,6 @@ do_save_xml_from_proptree(const SGPropertyNode * arg)
return true; return true;
} }
static bool
do_press_cockpit_button (const SGPropertyNode *arg)
{
const char *prefix = arg->getStringValue("prefix");
if (arg->getBoolValue("guarded") && fgGetDouble((string(prefix) + "-guard").c_str()) < 1)
return true;
string prop = string(prefix) + "-button";
double value;
if (arg->getBoolValue("latching"))
value = fgGetDouble(prop.c_str()) > 0 ? 0 : 1;
else
value = 1;
fgSetDouble(prop.c_str(), value);
fgSetBool(arg->getStringValue("discrete"), value > 0);
return true;
}
static bool
do_release_cockpit_button (const SGPropertyNode *arg)
{
const char *prefix = arg->getStringValue("prefix");
if (arg->getBoolValue("guarded")) {
string prop = string(prefix) + "-guard";
if (fgGetDouble(prop.c_str()) < 1) {
fgSetDouble(prop.c_str(), 1);
return true;
}
}
if (! arg->getBoolValue("latching")) {
fgSetDouble((string(prefix) + "-button").c_str(), 0);
fgSetBool(arg->getStringValue("discrete"), false);
}
return true;
}
// Optional profiling commands using gperftools: // Optional profiling commands using gperftools:
// http://code.google.com/p/gperftools/ // http://code.google.com/p/gperftools/
@ -1355,22 +903,12 @@ static struct {
} built_ins [] = { } built_ins [] = {
{ "null", do_null }, { "null", do_null },
{ "nasal", do_nasal }, { "nasal", do_nasal },
{ "exit", do_exit },
{ "reset", do_reset },
{ "reposition", do_reposition },
{ "switch-aircraft", do_switch_aircraft },
{ "pause", do_pause }, { "pause", do_pause },
{ "load", do_load }, { "load", do_load },
{ "save", do_save }, { "save", do_save },
{ "save-tape", do_save_tape }, { "save-tape", do_save_tape },
{ "load-tape", do_load_tape }, { "load-tape", do_load_tape },
{ "panel-load", do_panel_load },
{ "preferences-load", do_preferences_load },
{ "toggle-fullscreen", do_toggle_fullscreen },
{ "view-cycle", do_view_cycle }, { "view-cycle", do_view_cycle },
{ "screen-capture", do_screen_capture },
{ "hires-screen-capture", do_hires_screen_capture },
{ "tile-cache-reload", do_tile_cache_reload },
/* /*
{ "set-sea-level-air-temp-degc", do_set_sea_level_degc }, { "set-sea-level-air-temp-degc", do_set_sea_level_degc },
{ "set-outside-air-temp-degc", do_set_oat_degc }, { "set-outside-air-temp-degc", do_set_oat_degc },
@ -1387,18 +925,8 @@ static struct {
{ "property-randomize", do_property_randomize }, { "property-randomize", do_property_randomize },
{ "property-interpolate", do_property_interpolate }, { "property-interpolate", do_property_interpolate },
{ "data-logging-commit", do_data_logging_commit }, { "data-logging-commit", do_data_logging_commit },
{ "dialog-new", do_dialog_new },
{ "dialog-show", do_dialog_show },
{ "dialog-close", do_dialog_close },
{ "dialog-update", do_dialog_update },
{ "dialog-apply", do_dialog_apply },
{ "open-browser", do_open_browser },
{ "gui-redraw", do_gui_redraw },
{ "add-model", do_add_model },
{ "presets-commit", do_presets_commit },
{ "log-level", do_log_level }, { "log-level", do_log_level },
{ "replay", do_replay }, { "replay", do_replay },
{ "open-launcher", do_open_launcher },
/* /*
{ "decrease-visibility", do_decrease_visibility }, { "decrease-visibility", do_decrease_visibility },
{ "increase-visibility", do_increase_visibility }, { "increase-visibility", do_increase_visibility },
@ -1406,13 +934,6 @@ static struct {
{ "loadxml", do_load_xml_to_proptree}, { "loadxml", do_load_xml_to_proptree},
{ "savexml", do_save_xml_from_proptree }, { "savexml", do_save_xml_from_proptree },
{ "xmlhttprequest", do_load_xml_from_url }, { "xmlhttprequest", do_load_xml_from_url },
{ "press-cockpit-button", do_press_cockpit_button },
{ "release-cockpit-button", do_release_cockpit_button },
{ "dump-scenegraph", do_dump_scene_graph },
{ "dump-terrainbranch", do_dump_terrain_branch },
{ "print-visible-scene", do_print_visible_scene_info },
{ "reload-shaders", do_reload_shaders },
{ "reload-materials", do_materials_reload },
{ "profiler-start", do_profiler_start }, { "profiler-start", do_profiler_start },
{ "profiler-stop", do_profiler_stop }, { "profiler-stop", do_profiler_stop },

View file

@ -8,6 +8,8 @@
*/ */
void fgInitCommands (); void fgInitCommands ();
void fgInitSceneCommands();
// end of fg_commands.hxx // end of fg_commands.hxx
#endif #endif

View file

@ -0,0 +1,555 @@
// fg_scene_commands.cxx - internal FGFS commands.
#include "config.h"
#include <string.h> // strcmp()
#include <simgear/compiler.h>
#include <string>
#include <fstream>
#include <simgear/sg_inlines.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/structure/commands.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/event_mgr.hxx>
#include <simgear/sound/soundmgr.hxx>
#include <simgear/timing/sg_time.hxx>
#include <Network/RemoteXMLRequest.hxx>
#include <FDM/flight.hxx>
#include <GUI/gui.h>
#include <GUI/new_gui.hxx>
#include <GUI/dialog.hxx>
#include <Aircraft/replay.hxx>
#include <Scenery/scenery.hxx>
#include <Scripting/NasalSys.hxx>
#include <Sound/sample_queue.hxx>
#include <Airports/xmlloader.hxx>
#include <Network/HTTPClient.hxx>
#include <Viewer/viewmgr.hxx>
#include <Viewer/view.hxx>
#include <Environment/presets.hxx>
#include <Navaids/NavDataCache.hxx>
#include "fg_init.hxx"
#include "fg_io.hxx"
#include "fg_os.hxx"
#include "fg_commands.hxx"
#include "fg_props.hxx"
#include "globals.hxx"
#include "logger.hxx"
#include "util.hxx"
#include "main.hxx"
#include "positioninit.hxx"
#include <boost/scoped_array.hpp>
#if FG_HAVE_GPERFTOOLS
# include <google/profiler.h>
#endif
#if defined(HAVE_QT)
#include <GUI/QtLauncher.hxx>
#endif
////////////////////////////////////////////////////////////////////////
// Command implementations.
////////////////////////////////////////////////////////////////////////
/**
* Built-in command: exit FlightGear.
*
* status: the exit status to return to the operating system (defaults to 0)
*/
static bool
do_exit (const SGPropertyNode * arg)
{
SG_LOG(SG_INPUT, SG_INFO, "Program exit requested.");
fgSetBool("/sim/signals/exit", true);
globals->saveUserSettings();
fgOSExit(arg->getIntValue("status", 0));
return true;
}
/**
* Reset FlightGear (Shift-Escape or Menu->File->Reset)
*/
static bool
do_reset (const SGPropertyNode * arg)
{
fgResetIdleState();
return true;
}
/**
* Change aircraft
*/
static bool
do_switch_aircraft (const SGPropertyNode * arg)
{
fgSetString("/sim/aircraft", arg->getStringValue("aircraft"));
// start a reset
fgResetIdleState();
return true;
}
/**
*/
static bool
do_reposition (const SGPropertyNode * arg)
{
fgStartReposition();
return true;
}
/**
* Built-in command: (re)load the panel.
*
* path (optional): the file name to load the panel from
* (relative to FG_ROOT). Defaults to the value of /sim/panel/path,
* and if that's unspecified, to "Panels/Default/default.xml".
*/
static bool
do_panel_load (const SGPropertyNode * arg)
{
string panel_path = arg->getStringValue("path");
if (!panel_path.empty()) {
// write to the standard property, which will force a load
fgSetString("/sim/panel/path", panel_path.c_str());
}
return true;
}
/**
* Built-in command: (re)load preferences.
*
* path (optional): the file name to load the panel from (relative
* to FG_ROOT). Defaults to "preferences.xml".
*/
static bool
do_preferences_load (const SGPropertyNode * arg)
{
// disabling this command which was formerly used to reload 'preferences.xml'
// reloading the defaults doesn't make sense (better to reset the simulator),
// and loading arbitrary XML docs into the property-tree can be done via
// the standard load-xml command.
SG_LOG(SG_GENERAL, SG_ALERT, "preferences-load command is deprecated and non-functional");
return false;
}
/**
* An fgcommand to toggle fullscreen mode.
* No parameters.
*/
static bool
do_toggle_fullscreen(const SGPropertyNode *arg)
{
fgOSFullScreen();
return true;
}
/**
* Built-in command: capture screen.
*/
static bool
do_screen_capture (const SGPropertyNode * arg)
{
return fgDumpSnapShot();
}
static bool
do_reload_shaders (const SGPropertyNode*)
{
simgear::reload_shaders();
return true;
}
static bool
do_dump_scene_graph (const SGPropertyNode*)
{
fgDumpSceneGraph();
return true;
}
static bool
do_dump_terrain_branch (const SGPropertyNode*)
{
fgDumpTerrainBranch();
double lon_deg = fgGetDouble("/position/longitude-deg");
double lat_deg = fgGetDouble("/position/latitude-deg");
SGGeod geodPos = SGGeod::fromDegFt(lon_deg, lat_deg, 0.0);
SGVec3d zero = SGVec3d::fromGeod(geodPos);
SG_LOG(SG_INPUT, SG_INFO, "Model parameters:");
SG_LOG(SG_INPUT, SG_INFO, "Center: " << zero.x() << ", " << zero.y() << ", " << zero.z() );
SG_LOG(SG_INPUT, SG_INFO, "Rotation: " << lat_deg << ", " << lon_deg );
return true;
}
static bool
do_print_visible_scene_info(const SGPropertyNode*)
{
fgPrintVisibleSceneInfoCommand();
return true;
}
/**
* Built-in command: hires capture screen.
*/
static bool
do_hires_screen_capture (const SGPropertyNode * arg)
{
fgHiResDump();
return true;
}
/**
* Reload the tile cache.
*/
static bool
do_tile_cache_reload (const SGPropertyNode * arg)
{
SGPropertyNode *master_freeze = fgGetNode("/sim/freeze/master");
bool freeze = master_freeze->getBoolValue();
SG_LOG(SG_INPUT, SG_INFO, "ReIniting TileCache");
if ( !freeze ) {
master_freeze->setBoolValue(true);
}
globals->get_subsystem("tile-manager")->reinit();
if ( !freeze ) {
master_freeze->setBoolValue(false);
}
return true;
}
/**
* Reload the materials definition
*/
static bool
do_materials_reload (const SGPropertyNode * arg)
{
SG_LOG(SG_INPUT, SG_INFO, "Reloading Materials");
SGMaterialLib* new_matlib = new SGMaterialLib;
SGPath mpath( globals->get_fg_root() );
mpath.append( fgGetString("/sim/rendering/materials-file") );
bool loaded = new_matlib->load(globals->get_fg_root().local8BitStr(),
mpath.local8BitStr(),
globals->get_props());
if ( ! loaded ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Error loading materials file " << mpath );
return false;
}
globals->set_matlib(new_matlib);
FGScenery* scenery = static_cast<FGScenery*>(globals->get_scenery());
scenery->materialLibChanged();
return true;
}
/**
* Built-in command: Add a dialog to the GUI system. Does *not*
* display the dialog. The property node should have the same format
* as a dialog XML configuration. It must include:
*
* name: the name of the GUI dialog for future reference.
*/
static bool
do_dialog_new (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
if (!gui) {
return false;
}
// Note the casting away of const: this is *real*. Doing a
// "dialog-apply" command later on will mutate this property node.
// I'm not convinced that this isn't the Right Thing though; it
// allows client to create a node, pass it to dialog-new, and get
// the values back from the dialog by reading the same node.
// Perhaps command arguments are not as "const" as they would
// seem?
gui->newDialog((SGPropertyNode*)arg);
return true;
}
/**
* Built-in command: Show an XML-configured dialog.
*
* dialog-name: the name of the GUI dialog to display.
*/
static bool
do_dialog_show (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
gui->showDialog(arg->getStringValue("dialog-name"));
return true;
}
/**
* Built-in Command: Hide the active XML-configured dialog.
*/
static bool
do_dialog_close (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
if(arg->hasValue("dialog-name"))
return gui->closeDialog(arg->getStringValue("dialog-name"));
return gui->closeActiveDialog();
}
/**
* Update a value in the active XML-configured dialog.
*
* object-name: The name of the GUI object(s) (all GUI objects if omitted).
*/
static bool
do_dialog_update (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
FGDialog * dialog;
if (arg->hasValue("dialog-name"))
dialog = gui->getDialog(arg->getStringValue("dialog-name"));
else
dialog = gui->getActiveDialog();
if (dialog != 0) {
dialog->updateValues(arg->getStringValue("object-name"));
return true;
} else {
return false;
}
}
static bool
do_open_browser (const SGPropertyNode * arg)
{
string path;
if (arg->hasValue("path"))
path = arg->getStringValue("path");
else
if (arg->hasValue("url"))
path = arg->getStringValue("url");
else
return false;
return openBrowser(path);
}
static bool
do_open_launcher(const SGPropertyNode *)
{
#if defined(HAVE_QT)
bool ok = flightgear::runInAppLauncherDialog();
if (ok) {
// start a full reset
fgResetIdleState();
}
return true; // don't report failure
#else
return false;
#endif
}
/**
* Apply a value in the active XML-configured dialog.
*
* object-name: The name of the GUI object(s) (all GUI objects if omitted).
*/
static bool
do_dialog_apply (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
FGDialog * dialog;
if (arg->hasValue("dialog-name"))
dialog = gui->getDialog(arg->getStringValue("dialog-name"));
else
dialog = gui->getActiveDialog();
if (dialog != 0) {
dialog->applyValues(arg->getStringValue("object-name"));
return true;
} else {
return false;
}
}
/**
* Redraw GUI (applying new widget colors). Doesn't reload the dialogs,
* unlike reinit().
*/
static bool
do_gui_redraw (const SGPropertyNode * arg)
{
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
gui->redraw();
return true;
}
/**
* Adds model to the scenery. The path to the added branch (/models/model[*])
* is returned in property "property".
*/
static bool
do_add_model (const SGPropertyNode * arg)
{
SGPropertyNode * model = fgGetNode("models", true);
int i;
for (i = 0; model->hasChild("model",i); i++);
model = model->getChild("model", i, true);
copyProperties(arg, model);
if (model->hasValue("elevation-m"))
model->setDoubleValue("elevation-ft", model->getDoubleValue("elevation-m")
* SG_METER_TO_FEET);
model->getNode("load", true);
model->removeChildren("load");
const_cast<SGPropertyNode *>(arg)->setStringValue("property", model->getPath());
return true;
}
/**
* Built-in command: commit presets (read from in /sim/presets/)
*/
static bool
do_presets_commit (const SGPropertyNode * arg)
{
if (fgGetBool("/sim/initialized", false)) {
fgResetIdleState();
} else {
// Nasal can trigger this during initial init, which confuses
// the logic in ReInitSubsystems, since initial state has not been
// saved at that time. Short-circuit everything here.
flightgear::initPosition();
}
return true;
}
static bool
do_press_cockpit_button (const SGPropertyNode *arg)
{
const char *prefix = arg->getStringValue("prefix");
if (arg->getBoolValue("guarded") && fgGetDouble((string(prefix) + "-guard").c_str()) < 1)
return true;
string prop = string(prefix) + "-button";
double value;
if (arg->getBoolValue("latching"))
value = fgGetDouble(prop.c_str()) > 0 ? 0 : 1;
else
value = 1;
fgSetDouble(prop.c_str(), value);
fgSetBool(arg->getStringValue("discrete"), value > 0);
return true;
}
static bool
do_release_cockpit_button (const SGPropertyNode *arg)
{
const char *prefix = arg->getStringValue("prefix");
if (arg->getBoolValue("guarded")) {
string prop = string(prefix) + "-guard";
if (fgGetDouble(prop.c_str()) < 1) {
fgSetDouble(prop.c_str(), 1);
return true;
}
}
if (! arg->getBoolValue("latching")) {
fgSetDouble((string(prefix) + "-button").c_str(), 0);
fgSetBool(arg->getStringValue("discrete"), false);
}
return true;
}
////////////////////////////////////////////////////////////////////////
// Command setup.
////////////////////////////////////////////////////////////////////////
/**
* Table of built-in commands.
*
* New commands do not have to be added here; any module in the application
* can add a new command using globals->get_commands()->addCommand(...).
*/
static struct {
const char * name;
SGCommandMgr::command_t command;
} built_ins [] = {
{ "exit", do_exit },
{ "reset", do_reset },
{ "reposition", do_reposition },
{ "switch-aircraft", do_switch_aircraft },
{ "panel-load", do_panel_load },
{ "preferences-load", do_preferences_load },
{ "toggle-fullscreen", do_toggle_fullscreen },
{ "screen-capture", do_screen_capture },
{ "hires-screen-capture", do_hires_screen_capture },
{ "tile-cache-reload", do_tile_cache_reload },
{ "dialog-new", do_dialog_new },
{ "dialog-show", do_dialog_show },
{ "dialog-close", do_dialog_close },
{ "dialog-update", do_dialog_update },
{ "dialog-apply", do_dialog_apply },
{ "open-browser", do_open_browser },
{ "gui-redraw", do_gui_redraw },
{ "add-model", do_add_model },
{ "presets-commit", do_presets_commit },
{ "press-cockpit-button", do_press_cockpit_button },
{ "release-cockpit-button", do_release_cockpit_button },
{ "dump-scenegraph", do_dump_scene_graph },
{ "dump-terrainbranch", do_dump_terrain_branch },
{ "print-visible-scene", do_print_visible_scene_info },
{ "reload-shaders", do_reload_shaders },
{ "reload-materials", do_materials_reload },
{ "open-launcher", do_open_launcher },
{ 0, 0 } // zero-terminated
};
/**
* Initialize the default built-in commands.
*
* Other commands may be added by other parts of the application.
*/
void
fgInitSceneCommands ()
{
SG_LOG(SG_GENERAL, SG_BULK, "Initializing scene built-in commands:");
for (int i = 0; built_ins[i].name != 0; i++) {
SG_LOG(SG_GENERAL, SG_BULK, " " << built_ins[i].name);
globals->get_commands()->addCommand(built_ins[i].name,
built_ins[i].command);
}
}

View file

@ -286,6 +286,7 @@ static void fgIdleFunction ( void ) {
// Initialize the property-based built-in commands // Initialize the property-based built-in commands
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
fgInitCommands(); fgInitCommands();
fgInitSceneCommands();
flightgear::registerSubsystemCommands(globals->get_commands()); flightgear::registerSubsystemCommands(globals->get_commands());

View file

@ -33,7 +33,7 @@ using std::string;
#include "VoiceSynthesizer.hxx" #include "VoiceSynthesizer.hxx"
FGFLITEVoice::FGFLITEVoice(FGVoiceMgr * mgr, const SGPropertyNode_ptr node, const char * sampleGroupRefName) FGFLITEVoice::FGFLITEVoice(FGVoiceMgr * mgr, const SGPropertyNode_ptr node, const char * sampleGroupRefName)
: FGVoice(mgr), _synthesizer( NULL) : FGVoice(mgr), _synthesizer( NULL), _seconds_to_run(0.0)
{ {
_sampleName = node->getStringValue("desc", node->getPath().c_str()); _sampleName = node->getStringValue("desc", node->getPath().c_str());
@ -68,14 +68,21 @@ void FGFLITEVoice::speak(const string & msg)
} }
} }
void FGFLITEVoice::update() void FGFLITEVoice::update(double dt)
{ {
_seconds_to_run -= dt;
if (_seconds_to_run < 0.0) {
SGSharedPtr<SGSoundSample> sample = _sampleQueue.pop(); SGSharedPtr<SGSoundSample> sample = _sampleQueue.pop();
if (sample.valid()) { if (sample.valid()) {
_sgr->remove(_sampleName); _sgr->remove(_sampleName);
_sgr->add(sample, _sampleName); _sgr->add(sample, _sampleName);
_sgr->resume(); _sgr->resume();
_sgr->play(_sampleName, false); _sgr->play(_sampleName, false);
// Don't play any further TTS until we've finished playing this sample,
// allowing 500ms for a gap between transmissions. Good radio comms!
_seconds_to_run = 0.5 + ((float) sample->get_no_samples()) / ((float) sample->get_frequency());
}
} }
} }

View file

@ -35,7 +35,7 @@ public:
FGFLITEVoice(FGVoiceMgr *, const SGPropertyNode_ptr, const char * sampleGroupRefName = "flite-voice"); FGFLITEVoice(FGVoiceMgr *, const SGPropertyNode_ptr, const char * sampleGroupRefName = "flite-voice");
virtual ~FGFLITEVoice(); virtual ~FGFLITEVoice();
virtual void speak(const std::string & msg); virtual void speak(const std::string & msg);
virtual void update(); virtual void update(double dt);
private: private:
FGFLITEVoice(const FGFLITEVoice & other); FGFLITEVoice(const FGFLITEVoice & other);
@ -45,6 +45,7 @@ private:
VoiceSynthesizer * _synthesizer; VoiceSynthesizer * _synthesizer;
SGLockedQueue<SGSharedPtr<SGSoundSample> > _sampleQueue; SGLockedQueue<SGSharedPtr<SGSoundSample> > _sampleQueue;
std::string _sampleName; std::string _sampleName;
double _seconds_to_run;
}; };
#endif // _FLITEVOICE_HXX #endif // _FLITEVOICE_HXX

View file

@ -43,7 +43,7 @@ public:
FGFestivalVoice(FGVoiceMgr *, const SGPropertyNode_ptr); FGFestivalVoice(FGVoiceMgr *, const SGPropertyNode_ptr);
virtual ~FGFestivalVoice(); virtual ~FGFestivalVoice();
virtual void speak( const string & msg ); virtual void speak( const string & msg );
virtual void update(); virtual void update(double);
void setVolume(double); void setVolume(double);
void setPitch(double); void setPitch(double);
void setSpeed(double); void setSpeed(double);
@ -129,14 +129,14 @@ void FGVoiceMgr::shutdown()
} }
void FGVoiceMgr::update(double) void FGVoiceMgr::update(double dt)
{ {
if (!_enabled) if (!_enabled)
return; return;
_paused = !_pausedNode->getBoolValue(); _paused = !_pausedNode->getBoolValue();
for (unsigned int i = 0; i < _voices.size(); i++) { for (unsigned int i = 0; i < _voices.size(); i++) {
_voices[i]->update(); _voices[i]->update(dt);
#if !defined(ENABLE_THREADS) #if !defined(ENABLE_THREADS)
_voices[i]->speak(); _voices[i]->speak();
#endif #endif
@ -235,7 +235,7 @@ void FGFestivalVoice::speak( const string & msg )
} }
void FGFestivalVoice::update(void) void FGFestivalVoice::update(double dt)
{ {
double d; double d;
d = _volumeNode->getDoubleValue(); d = _volumeNode->getDoubleValue();
@ -333,5 +333,3 @@ void FGVoiceMgr::FGVoice::valueChanged(SGPropertyNode *node)
pushMessage(m); pushMessage(m);
} }

View file

@ -99,7 +99,7 @@ public:
FGVoice(FGVoiceMgr * mgr ) : _mgr(mgr) {} FGVoice(FGVoiceMgr * mgr ) : _mgr(mgr) {}
virtual ~FGVoice() {} virtual ~FGVoice() {}
virtual void speak( const std::string & msg ) = 0; virtual void speak( const std::string & msg ) = 0;
virtual void update() = 0; virtual void update(double dt) = 0;
void pushMessage( const std::string & m); void pushMessage( const std::string & m);
bool speak(); bool speak();