Howto:Work with the Property Tree API: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
Line 77: Line 77:


==== Tied Properties ====
==== Tied Properties ====
void fgUntie (const char * name);
Please try to refrain from using tied properties. Tied properties have been known to cause issues and break other features of FlightGear. For additional information please see: [[Howto:Use Property Tree Objects]].


[[Category:Property Tree]]
[[Category:Property Tree]]
[[Category:Core developer documentation]]
[[Category:Core developer documentation]]

Revision as of 14:18, 30 May 2012

This article is a stub. You can help the wiki by expanding it.

Most FlightGear systems communicate internally using the so called Property Tree (see Property Tree Intro for an introduction).

This article is meant to introduce you to the C++ API that is used by FlightGear to work with the Property Tree.

Most of the high level API can be found in the $FG SRC/Main folder, specifically the files fg_props.cxx and the corresponding fg_props.hxx header are relevant (this is the one, that you'll want to include when working with the property tree).

The property tree implementation itself is to be found in the SimGear sources ([1] see specifically SGPropertyNode).

Note: Accessing property manager values via static propertynode pointers is more efficient because you only have to do the expensive string name hash lookup once the first time the routine runs.

Modeling an API on top of the property tree

The property tree's purpose is to provide access to internal variables, i.e. by allowing people to inspect internal variables in a read-only fashion, but also in a writable fashion in many cases.

The property tree's support for "publishing" internal variables, that can be read from and written to using an intuitive symbolic name within a tree hierarchy, also makes it possible to register so called "listeners" which invoke internal code routines ("callbacks) whenever certain properties are accessed (read or modified).

This, in turn, makes it also possible to emulate a signal/slots mechanism (think Qt) on top of the property tree, i.e. by using "output properties" as signals, and "input properties" as "slots".

Routines that can be invoked this way include core C++ code, but also Nasal scripts.

More and more subsystems in FlightGear make use of this method to implement a subsystem-specific high level interface on top of the property tree.

There are certain advantages by using the property tree like this, because all FlightGear subsystems can easily access those "APIs" - i.e. once a certain feature is implemented and provided using the property tree, the corresponding features becomes accessible everywhere, it would no longer matter if you wanted to access the feature internally, e.g. using the property tree browser, using an XML configuration file, a Nasal script, a networking protocol or even the telnet/props interface - simply because all of these methods have access to the property tree. In other words, once a feature is implemented like this, RPC also becomes possible automatically. The AI traffic system is working like this for example: It registers a listener callback that gets invoked whenever updates take place for the corresponding branch in the property tree (such as /ai/models).

So, as soon as some part of FG makes modifications to this branch, the AI system is there to validate and process these modifications - i.e. in order to parse and see what it has to do.

At that point, it doesn't matter any longer if you are instantiating AI traffic manually (by using the property tree browser), using a Nasal script or a telnet connection into the property tree - simply because the AI system provides an API an top of the property tree that is accessible to all FG systems.

Another advantage is that there wouldn't be any changes required to Nasal or other existing code, this would be just about adding a new subsystem, making it listen to a dedicated branch in the property tree (such as /usb-hid) and processing events. This is where you'd need to map the core C++ API to property tree events, where you'd handle argument processing.

The same approach could be used to add other features to FG, without touching the Nasal code at all - such as socket support, or 2D rendering.

Checking for Property Existence

bool fgHasNode (const char * path);

Getters

SGPropertyNode * fgGetNode (const char * path, bool create);
SGPropertyNode * fgGetNode (const char * path, int index, bool create);

Boolean Values

bool fgSetBool (const char * name, bool val);
bool fgGetBool (const char * name, bool defaultValue);

Integers

bool fgSetInt (const char * name, int val);
int fgGetInt (const char * name, int defaultValue);

Floats

bool fgSetFloat (const char * name, float val);
float fgGetFloat (const char * name, float defaultValue);

Doubles

bool fgSetDouble (const char * name, double val);
double fgGetDouble (const char * name, double defaultValue);

Longs

long fgGetLong (const char * name, long defaultValue);
fgSetLong (const char * name, long val);

Strings

bool fgSetString (const char * name, const char * val);
const char * fgGetString (const char * name, const char * defaultValue);

Using Listeners

void fgAddChangeListener (SGPropertyChangeListener * listener, const char * path);
void fgAddChangeListener (SGPropertyChangeListener * listener, const char * path, int index);

Attributes

Persistance
void fgSetArchivable (const char * name, bool state);
Access
void fgSetReadable (const char * name, bool state);
void fgSetWritable (const char * name, bool state);

Tied Properties

Please try to refrain from using tied properties. Tied properties have been known to cause issues and break other features of FlightGear. For additional information please see: Howto:Use Property Tree Objects.