Howto:Create animation XML files from Nasal: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
mNo edit summary
Line 3: Line 3:
Objective: Use [[Nasal]] scripting to dynamically create an XML file by using the setprop() API call to set up your XML file's PropertyList-encoded structure and then writing the result to the file system using the write_properties() wrapper found in $FG_ROOT/Nasal/io.nas.
Objective: Use [[Nasal]] scripting to dynamically create an XML file by using the setprop() API call to set up your XML file's PropertyList-encoded structure and then writing the result to the file system using the write_properties() wrapper found in $FG_ROOT/Nasal/io.nas.


There are two wrappers provided: read_properties() and write_properties. These are wrappers for the corresponding fgcommands "load-xml" and "save-xml".
There are two wrappers provided: read_properties() and write_properties. These are wrappers for the corresponding fgcommands "[http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands#line133 loadxml]" and "[http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands#line139 save-xml]".


So, you don't need to look into the low level XML processing routines, you can directly use these PropertyList-wrappers - these allow you to directly dump a property tree sub branch to an XML file. So you can create your structure dynamically using setprop() and at the end use the write_properties() wrapper to write the resulting XML file to disk. That should save you some time.
So, you don't need to look into the low level XML processing routines, you can directly use these PropertyList-wrappers - these allow you to directly dump a property tree sub branch to an XML file. So you can create your structure dynamically using setprop() and at the end use the write_properties() wrapper to write the resulting XML file to disk. That should save you some time.

Revision as of 17:56, 5 February 2012

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

Objective: Use Nasal scripting to dynamically create an XML file by using the setprop() API call to set up your XML file's PropertyList-encoded structure and then writing the result to the file system using the write_properties() wrapper found in $FG_ROOT/Nasal/io.nas.

There are two wrappers provided: read_properties() and write_properties. These are wrappers for the corresponding fgcommands "loadxml" and "save-xml".

So, you don't need to look into the low level XML processing routines, you can directly use these PropertyList-wrappers - these allow you to directly dump a property tree sub branch to an XML file. So you can create your structure dynamically using setprop() and at the end use the write_properties() wrapper to write the resulting XML file to disk. That should save you some time.


Background

In general, this shouldn't really be necessary - because XML files are meant to be created and edited manually. On the other hand, due to the lack of a simple 2D drawing API accessible from Nasal, more and more complex "glass cockpit"-style instruments are getting implemented using the XML-based approach. These files (often more than 100-200 kbytes in size) contain fairly repetitive markup that could (and should) be created procedurally in an automated fashion. So, the approach suggested here is to use a separate Nasal script to create the required XML markup dynamically, rather than having to copy/paste and customize hundreds of XML animations manually using a text editor.

Getting started

The following piece of Nasal creates a new XML file, in the standard FlightGear PropertyList encoded form:

 var location= "/temp/test/foo"; # location in the global FG property tree
 var filename="test.xml"; # location in the local file system (will be OVERWRITTEN/DELETED!)
 setprop(location, "hello world");
 io.write_properties(filename, location);


The created output is:

 <?xml version="1.0"?>
 <PropertyList>
  <temp>
   <test>
    <foo>hello world</foo>
   </test>
  </temp>

Once you understand how this works, you can dynamically create PropertyList-encoded XML files for your instruments. Consider the following XML file containing a single animation:

       <path>vsd.ac</path>
       <animation>
          <type>select</type>
          <object-name>vsd</object-name>
          <condition>
             <greater-than-equals>
                <property>systems/electrical/outputs/efis</property>
                <value>9</value>
             </greater-than-equals>
          </condition>
       </animation>

Now, to create this snippet of XML procedurally, you can use this piece of Nasal:

    var location = "/temp/test/";
    var filename="xmltest.xml";
    setprop(location~"path", "vsd.ac");
    setprop(location~"animation[0]/type", "select");
    setprop(location~"animation[0]/object-name", "vsd");
    setprop(location~"animation[0]/condition/greather-than-equals/property", "systems/electrical/outputs/efis");
    setprop(location~"animation[0]/condition/greather-than-equals/value", "9");
    io.write_properties(filename, location);


Note that multiple setprop() calls like this would obviously overwrite the previous animation, so you would need to use explicit indices here:

  • animation[0]
  • animation[1]
  • animation[2]

This also holds true for any child nodes (once you have several identically named nodes):

  • object-name[0]
  • object-name[1]
  • object-name[2]
  • object-name[3]

So, it is always a good idea to explicitly add the index, too.

This is identical to how the property tree internally works already: /sim/foo is equivalent to /sim/foo[0] If you don't understand how this works, please take a look at $FG_ROOT/Docs: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.xmlpanel#line162

If you want this to be even easier, you could use the props.nas module, because its methods have support for adding indices automatically.

Next, you could add a handful of helpers (or even a class wrapping animations) to make things a bit easier. Anybody interested in coming up with an OOP wrapper for this, should look into using the props.nas module available in $FG_ROOT/Nasal.

If you already have some prefabricated XML file that you'd like to continue using, then you could also just automate the creation of certain animations and save them in a separate file. This is supported by including a PropertyList file in another file using the "include" attribute:

 <PropertyList>
  <animation include="vsd.xml"/>
 </PropertyList>


 <?xml version="1.0"?>
  <PropertyList>
   <foo include="someotherfile.xml"/>
  </PropertyList>
<?xml version="1.0"?>
<PropertyList>
    <bla>data</bla>
</PropertyList>

This would result in /foo/bla=data

Some additional info is available in $FG_ROOT/Docs:


There is also support for customizing included files (overriding certain properties with custom defaults): http://gitorious.org/fg/fgdata/blobs/master/Docs/README.xmlpanel#line245

Related