
Internals
---------

The core of FlightGear is the property system. This is a tree like internal
representation of global variables. The property system is explained more
in detail later on.

FlightGear' way of doing things is breaking it up into small pieces. There is
(for example) animation code that reacts on property changes. There is also a
Flight Dynamics model (FDM) that (amongst other things) updates properties.
There is a menu system that can display and alter properties. Then we have
sound code that plays sound based on ... properties.

Maybe you see a pattern evolve by now.

All subsystems are almost self containing. Most of the time they only read the
values of some properties, and sometimes they alter other properties. This is
the basic way of communicating between subsystems.


Property System
---------------

The property system is best described as an in-memory LDAP database which holds
the state of global variables. The system has a tree like hierarchy (like a
file system) and has a root node, sub nodes (like subdirectories) and end-nodes
(variables).

All variables are kept internally as raw values and can be converted to any
other supported type (boolean, int, float double and string).

Like a file system, every node can be accessed relative to the current node, or
absolute to the root node.

The property system also allows aliasing nodes to other nodes (like symbolic
linking files or directories to other files or directories) and may be assigned
read-only or read-write.

If necessary it would be possible for parts of the program to hold it's own
property tree, which is inaccessible from the global property tree, by keeping
track of it's own root-node.

Property I/O code allows one to easily read the tree from, or write the tree to
an XML file.


Subsystems
----------

To add a new subsystem you would have to create a derived class from
SGSubsystem and define at least a small set of functions:

    class FGSubsystemExample : public SGSubsystem
    {
    public:
        FGSubsystemExample();
        virtual ~FGSubsystemExample();

        // Subsystem API.
        void bind() override;
        void init() override;
        void reinit() override;
        void unbind() override;
        void update(double dt) override;

        // Subsystem identification.
        static const char* staticSubsystemClassId() { return "subsystem-example"; }
    };

To register the subsystem with the subsystem manager, for non-instanced
subsystems add:

    // Register the subsystem.
    SGSubsystemMgr::Registrant<FGSubsystemExample> registrantFGSubsystemExample

Or to define a specific subsystem manager group, e.g. DISPLAY, and add any
dependencies:

    // Register the subsystem.
    SGSubsystemMgr::Registrant<FGSubsystemExample> registrantFGSubsystemExample(
        SGSubsystemMgr::DISPLAY,
        {{"viewer", SGSubsystemMgr::Dependency::HARD},
         {"FGRenderer", SGSubsystemMgr::Dependency::NONSUBSYSTEM_HARD}});

The init() functions should make sure everything is set and ready so the
update() function can be run by the main loop. The reinit() function handles
everything in case of a reset by the user.

The bind() and unbind() functions can be used to tie and untie properties.

Finally to create and have the subsystem managed:

    globals->add_subsystem("example", new FGSubsystemExample);

Now the subsystem manager calls the update() function of this class every
frame. dt is the time (in seconds) elapsed since the last call.


Scripting
---------

The scripting langage Nasal can also read and modify properties but it can also
be incorporated into the menu system. The documentation for Nasal can be found
here:  http://www.plausible.org/nasal/flightgear.html

