107 lines
3.6 KiB
Plaintext
107 lines
3.6 KiB
Plaintext
|
|
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
|
|
|