-By
Date |
Author(s) |
Section Edited |
10-04-01 |
|
|
This document is a technical overview of the XML I/O structs and functions in xmlio.ms.
I/O facilities currently provided in Max are proprietary and limiting. Max' file format is a hierarchical chunk based binary format, each plugin saving and loading it's data from a designated chunk, with parameter blocks and global data saved automatically. This system works well if the entire file is saved and loaded from Max, but fails when
The above were crucial when developing the new Merge Animation tool (see mergeAnim.ms) where Animators and TD's can export animation from one object, modify it and merge it onto a different object
Once it was decided that an ASCII based format was needed, XML was the first choice. XML is an open extensible tag based format and is widely supported with free editors and parsers. Since object and animation I/O can also be useful in other areas of Max (like character nodes), the XML I/O routines were written in a separate module located in xmlio.ms, which should reside in any of the Maxscript startup directories.
This module (scripts) provides functions to persist XML data to and from Max entities, like objects and controllers. It declares a struct "sXmlIO" with a set or routines to load and save XML, and to dynamically creates objects with the given XML data. Instances of the struct can be created to handle multiple I/O operations, the module also created a global instance "gXmlIO" for convenience.
For parsing XML, the module uses "Microsoft XML parser, version 2.0" installed on systems with IE 5. The script can also be modified to use the latest MSXML4.0 parser by changing the following two lines
activeXControl axXMLCreate "MSXML.DOMDocument"
activeXControl axXMLRead "MSXML.DOMDocument"
to
activeXControl axXMLCreate "MSXML2.DOMDocument"
activeXControl axXMLRead "MSXML2.DOMDocument"
The struct constructor takes a string argument, which is the path to "controllers.xml", supplied with xmlio.ms, and has property information for various keyframe controllers in max. You can also add new ones to it.
These set of functions create max side entities with the given XML descriptors, normally used during loading.
init [force:false]
this method has to be called prior to any other operation on the struct. It creates an instance of the parser the first time, and initializes it and other data structures. If true is passed for the optional [force:], a new instance of the parser is always created.
load xmlDocName
loads the specified XML file into memory
save xmlDocName
save the in-memory xml document to file
xml2obj nodeElem [hide:true]
creates a max node give an xml element nodeElem, hide:true will hide the object in the viewport.
Example: The following xml data can be used to create a Sphere with the given parameters.
<object name="Sphere01" classOf="Sphere" isAnimated="true" id="1>
<baseObject classOf="Sphere">
<radius classOf="Float"> </radius>
<segments classOf="Integer"> </segments>
<smooth classOf="BooleanClass">true</smooth>
<hemisphere classOf="Float"> </hemisphere>
<Slice_From classOf="Float"> </Slice_From>
<Slice_To classOf="Float"> </Slice_To>
</baseObject>
<modifiers />
</object>
xml2subAnims animElem anim
reads the data from animElem xml element into sub-anims of a given animatable anim. If the sub-anims have controller than the controller node is passed to the following function
xml2ctrl animElem ctrl
persists the animation data including key frame data from given xml element animElem to the supplied controller ctrl. The given xml element should have a controller sub-node with the animation data.
Example: The above 2 functions can be used to create a transformation controller with the following xml data
<transform classOf="prs">
<position classOf="Point3">
<controller classOf="bezier_position">
<keys>
<key time="0f" selected="false" value="[6,39,0]" inTangent="[0,0,0]" outTangent="[0,0,0]" x_locked="true" y_locked="true" z_locked="true" constantVelocity="false" />
<key time="100f" selected="false" value="[56.4851,234.783,0]" inTangent="[0,0,0]" outTangent="[0,0,0]" x_locked="true" y_locked="true" z_locked="true" constantVelocity="false" />
</keys>
</controller>
</position>
<rotation classOf="Quat">
<controller classOf="tcb_rotation" />
</rotation>
<scale classOf="Point3">
<controller classOf="bezier_scale" />
</scale>
</transform>
max 2 xml functions
These set of functions create XML descriptors with the given max side entities, normally used during saving.
obj2xml obj parentElem [postCallback:undefined] [recurse:true]
creates an xml element for the given max object. parentElem is the parent xml element under which the new element should be created. Optionally you can pass in a postCallback function which gets called when the new element is created, can be used to display progress bars while saving. [recurse:] will recursively create xml nodes for all the child objects in the Max's hierarchy.
subAnims2xml anim animElem
scans through all the sub-anims of a give animatable anim and writes to the given xml element animElem, ctrl2xml() if a controller is assigned
ctrl2xml anim animElem
writes animation data from the given animatable to the given xml element animElem
utility functions
Any miscellaneous functions
create xmlElem [hide:true] [tempObjs:(#())]
creates a max side object from the given xmlElem, this functions sometime creates temporary objects which are put into the array passed as tempObjs:, which have be deleted by the caller of this function.
string2value str
converts a string into a maxscript value
isAnimated subAnim
given an animatable this function returns if any of the sub-anims under it are animatable
getAttribute xmlNode attr
returns the attribute value of a given xml node
The script module was helpful in loading and saving xml animation data from the merge animation tool. It is also planned to us this in the upcoming character nodes feature in saving and loading characters. This script was taking a post processing which worked well on small scenes with key framed controllers but was sluggish and unpredictable on large scenes. Sluggish - because it is a Maxscript and was interpreted and also because of the poor string handling in Maxscript. Unpredictable - Since some of the procedural controllers don't expose their handling of animation data like IK Controllers, Expression Controller.
These obstacles can be overcome if the XML I/O is integrated into Max's I/O mechanism as described in the following
Having plugins implement Animatable::Load and Animatable::Save methods passing ILoad/ISave. We have two classes that implement ILoad interface
O---ILoad
/\
/ \
/ \
XMLReader MaxReader
XMLReader loads from an XML stream whereas MaxReader writes to binary.
|