FlightGear Commands Mini-HOWTO

David Megginson
Started: 2002-10-25
Last revised: 2007-12-01


In FlightGear, a *command* represents an action, while a *property*
represents a state.  The trigger for a command can be any kind of user
input, including the keyboard, mouse, joystick, GUI, instrument panel,
or a remote network client.


XML Command Binding Markup
--------------------------

Most of the command-binding in FlightGear is handled through static
XML configuration files such as $FG_ROOT/keyboard.xml for the
keyboard, $FG_ROOT/mice.xml for the mouse, and
$FG_ROOT/gui/menubar.xml for the menubar.  In all of these files, you
reference a command through a binding.  This binding advances the
first throttle by 1%, up to a maximum value of 1.0:

  <binding>
   <command>property-adjust</command>
   <property>/controls/throttle[0]</property>
   <step type="double">0.01</step>
   <max>1.0</max>
  </binding>

A command binding always consists of the XML 'binding' element, with
one subelement named 'command' containing the command name (such as
'property-adjust').  All other subelements are named parameters to the
command: in this case, the parameters are 'property', 'step', and
'max'.  Here is a simpler binding, with no parameters:

  <binding>
   <command>exit</command>
  </binding>

Bindings always appear inside some other kind of markup, depending on
the input type.  For example, here is the binding from keyboard.xml
that links the ESC key to the 'exit' command:

 <key n="27">
  <name>ESC</name>
  <desc>Prompt and quit FlightGear.</desc>
  <binding>
    <command>exit</command>
  </binding>
 </key>

Usually, more than one binding is allowed for a single input trigger,
and bindings are executed in order from first to last. Bindings support
conditions (see README.conditions):

 <key n="113">
  <name>q</name>
  <desc>Test</desc>

  <binding>
   <condition>
    <property>/devices/status/mice/mouse/button[0]</property>
   </condition>
   <command>nasal</command>
   <script>print("mouse button 0 pressed")</script>
  </binding>
 </key>

Keyboard definitions can embed bindings in tags <mod-up> (key released),
<mod-shift>, <mod-ctrl>, <mod-alt>, <mod-meta>, <mod-super>, and <mod-hyper>.
Nesting is supported. Meta, Super, and Hyper modifier tags are for local
use only, and must be supported by the operating system to work.

 <key n="113">
  <name>q</name>
  <desc>Test</desc>
  <binding>
   <command>nasal</command>
   <script>print("q pressed")</script>
  </binding>

  <mod-alt>
   <binding>
    <command>nasal</command>
    <script>print("Alt-q pressed")</script>
   </binding>

   <mod-super>
    <binding>
     <command>nasal</command>
     <script>print("Alt-Super-q pressed")</script>
    </binding>

    <mod-meta>
     <binding>
      <command>nasal</command>
      <script>print("Alt-Super-Meta-q pressed")</script>
     </binding>

    </mod-meta>
   </mod-super>
  </mod-alt>
 </key>



Built-in Commands
-----------------

As of the last revision date, the following commands were available
from inside FlightGear; the most commonly-used ones are the commands
that operate on property values (FlightGear's internal state):


null - do nothing

script - execute a PSL script
  script: the PSL script to execute

exit - prompt and quit FlightGear

pause - pause/resume the simulation

load - load properties from an XML file
  file: the name of the file to load, relative to the current
    directory (defaults to "fgfs.sav")

save - save properties to an XML file
  file: the name of the file to save, relative to the current
    directory (defaults to "fgfs.sav").

loadxml - load XML file into property tree
  filename: the path & filename of the file to load
  targetnode: the target node within the property tree where to store the XML
  file's structure. If targetnode isn't defined, then the data will be stored
  in a node "data" under the argument branch.

savexml - save property tree node to XML file
  filename: the path & filename for the file to be saved
  sourcenode: the source node within the property tree where the XML file's
  structure is assembled from. If sourcenode isn't defined, then savexml will
  try to save data stored in a node "data" in the argument branch.

panel-load - (re)load the 2D instrument panel
  path: the path of the XML panel file, relative to $FG_ROOT (defaults
    to the value of /sim/panel/path if specified, or
    "Panels/Default/default.xml" as a last resort.

panel-mouse-click - pass a mouse click to the instrument panel
  button: the number of the mouse button (0-based)
  is-down: true if the button is down, false if it is up
  x-pos: the x position of the mouse click
  y-pos: the y position of the mouse click

preferences-load - (re)load preferences
  path: the file name to load preferences from, relative to $FG_ROOT.
    Defaults to "preferences.xml".

view-cycle - cycle to the next viewpoint

screen-capture - capture the screen to a file

tile-cache-reload - reload the scenery tile cache

lighting-update - update FlightGear's lighting

property-toggle - swap a property value between true and false
  property: the name of the property to toggle

property-assign - assign a value to a property
  property[0]: the name of the property that will get the new value.
  value: the new value for the property; or
  property[1]: the name of the property holding the new value.

property-interpolate - assign a value to a property, interpolated 
                       over time
  property[0]: the name of the property that will get the new value
               and defines the starting point of the interpolation
  value:       the new value for the property; or
  property[1]: the name of the property holding the new value.
  time:        the time in seconds it takes for the transition from the
               old value to the new value of property[0]; or
  rate:        the ammount of change per second the value of property[0] changes
               to transition to the new value

property-adjust - adjust the value of a property
  property: the name of the property to increment or decrement
  step: the amount of the increment or decrement (defaults to 0)
  offset: input offset distance (used for the mouse; multiplied by
    factor)
  factor: factor for multiplying offset distance (used for the mouse;
    defaults to 1)
  min: the minimum allowed value (default: no minimum)
  max: the maximum allowed value (default: no maximum)
  mask: 'integer' to apply only to the left of the decimal point;
    'decimal' to apply only to the right of the decimal point; 'all'
    to apply to the full value (defaults to 'all')
  wrap: true if the value should be wrapped when it passes min or max;
    both min and max must be specified (defaults to false)

property-multiply - multiply the value of a property
  property: the name of the property to multiply
  factor: the amount by which to multiply (defaults to 1.0)
  min: the minimum allowed value (default: no minimum)
  max: the maximum allowed value (default: no maximum)
  mask: 'integer' to apply only to the left of the decimal point;
    'decimal' to apply only to the right of the decimal point; 'all'
    to apply to the full value (defaults to 'all')
  wrap: true if the value should be wrapped when it passes min or max;
    both min and max must be specified (defaults to false)

property-swap - swap the values of two properties
  property[0]: the name of the first property
  property[1]: the name of the second property

property-scale - set the value of a property based on an axis
  property: the name of the property to set
  setting: the current input setting (usually a joystick axis from -1
    or 0 to 1)
  offset: the offset to shift by, before applying the factor (defaults
    to 0)
  factor: the factor to multiply by (use negative to reverse; defaults
    to 1.0)
  squared: if true will square the resulting value (same as power=2)
  power: the resulting value will be taken to the power of this integer
    value (overrides squared; default=1)

property-cycle - cycle a property through a set of values
  property: the name of the property to cycle
  value[*]: all of the allowed values

dialog-new - create new dialog from the argument branch

dialog-show - show an XML-configured dialog box
  dialog-name - the name of the dialog to show

dialog-close - close the active dialog box

dialog-update - copy values from FlightGear to the active dialog box
  object-name: the name of the GUI object to update (defaults to all
    objects)

dialog-apply - copy values from the active dialog box to FlightGear
  object-name: the name of the GUI object to apply (defaults to all
    objects)

presets-commit - commit preset values from /sim/presets

open-browser - open the web browser and show given file
   path: name of the local file to be opened.
   url: URL to be opened (http://..., ftp://...).

The following commands are temporary, and will soon disappear or be
renamed; do NOT rely on them:

old-save-dialog - offer to save a flight

old-load-dialog - offer to load a flight

old-reinit-dialog - offer to reinit FlightGear

old-hires-snapshot-dialog - save a hires screen shot

old-snapshot-dialog - save a screenshot

old-print-dialog - print the screen (Windows only)

old-pilot-offset-dialog - set pilot offsets graphically

old-hud-alpha-dialog - set the alpha value for the HUD

old-properties-dialog - display the property browser

old-preset-airport-dialog - set the default airport

old-preset-runway-dialog - set the default runway

old-preset-offset-distance-dialog - set the default offset distance

old-preset-altitude-dialog - set the default altitude

old-preset-glidescope-dialog - set the default glidescope

old-preset-airspeed-dialog - set the default airspeed

old-preset-commit-dialog - commit preset values

old-ap-add-waypoint-dialog - add a waypoint to the current route

old-ap-pop-waypoint-dialog - remove a waypoint from the current route

old-ap-clear-dialog - clear the current route

old-ap-adjust-dialog - adjust the autopilot settings

old-lat-lon-format-dialog - toggle the lat/lon format in the HUD


Adding New Commands in C++
--------------------------


To add a new command to FlightGear, you first need to create a
function that takes a single SGPropertyNode const pointer as an
argument:

  void
  do_something (SGPropertyNode * arg)
  {
    something();
  }

Next, you need to register it with the command manager:

  globals->get_commands()->addCommand("something", do_something);

Now, the command "something" is available to any mouse, joystick,
panel, or keyboard bindings.  If the bindings pass any arguments, they
will be children of the SGPropertyNode passed in:

  void
  do_something (const SGPropertyNode * arg)
  {
    something(arg->getStringValue("foo"), arg->getDoubleValue("bar"));
  }

That's pretty-much it.  Apologies in advance for not making things any
more complicated.