5 Simulation Control

5.2 Custom properties

Because of the usefulness of properties in creating control panels and probes (Sections 5.1) and Section 5.4), model developers may wish to add their own properties, either to the root model, or to a custom component.

This section provides only a brief summary of how to define properties. Full details are available in the “Properties” section of the Maspack Reference Manual.

5.2.1 Adding properties to a component

As mentioned in Section 1.4, properties are class-specific, and are exported by a class through code contained in the class’s definition. Often, it is convenient to add properties to the RootModel subclass that defines the application model. In more advanced applications, developers may want to add properties to a custom component.

The property definition steps are:

Declare the property list:

The class exporting the properties creates its own static instance of a PropertyList, using a declaration like

   static PropertyList myProps = new PropertyList (MyClass.class, MyParent.class);
   @Override
   public PropertyList getAllPropertyInfo() {
      return myProps;
   }

where MyClass and MyParent specify the class types of the exporting class and its parent class. The PropertyList declaration creates a new property list, with a copy of all the properties contained in the parent class. If one does not want the parent class properties, or if the parent class does not have properties, then one would use the constructor PropertyList(MyClass.class) instead. If the parent class is an ArtiSynth model component (including the RootModel), then it will always have its own properties. The declaration of the method getAllPropertyInfo() exposes the property list to other classes.

Add properties to the list:

Properties can then be added to the property list, by calling the PropertyList’s add() method:

   PropertyDesc add (String name, String description, Object defaultValue);

where name contains the name of the property, description is a comment describing the property, and defaultValue is an object containing the property’s default value. This is done inside a static code block:

   static {
      myProps.add ("stiffness", "spring stiffness", /*defaultValue=*/1);
      myProps.add ("damping", "spring damping", /*defaultValue=*/0);
   }

Variations on the add() method exist for adding read-only or inheritable properties, or for setting various property options. Other methods allow the property list to be edited.

Declare property accessor functions:

For each property propXXX added to the property list, accessor methods of the form

   void setPropXXX (TypeX value) {
      ...
   }
   TypeX getPropXXX() {
      TypeX value = ...
      return value;
   }

must be declared, where TypeX is the value associated with the property.

It is possible to specify different names for the accessor functions in the string argument name supplied to the add() method. Read-only properties only require a get accessor.

5.2.2 Example: a visibility property

An model illustrating the exporting of properties is defined in

  artisynth.demos.tutorial.SimpleMuscleWithProperties

This model extends SimpleMuscleWithPanel (Section 4.4.2) to provide a custom property boxVisible that is added to the control panel. The class definition, excluding include statements, is shown below:

1 public class SimpleMuscleWithProperties extends SimpleMuscleWithPanel {
2
3    // internal property list; inherits properties from SimpleMuscleWithPanel
4    static PropertyList myProps =
5       new PropertyList (
6          SimpleMuscleWithProperties.class, SimpleMuscleWithPanel.class);
7
8    // override getAllPropertyInfo() to return property list for this class
9    public PropertyList getAllPropertyInfo() {
10       return myProps;
11    }
12
13    // add new properties to the list
14    static {
15       myProps.add ("boxVisible", "box is visible", false);
16    }
17
18    // declare property accessors
19    public boolean getBoxVisible() {
20       return box.getRenderProps().isVisible();
21    }
22
23    public void setBoxVisible (boolean visible) {
24       RenderProps.setVisible (box, visible);
25    }
26
27    public void build (String[] args) throws IOException {
28
29       super.build (args);
30
31       panel.addWidget (this, "boxVisible");
32       panel.pack();
33    }
34 }

First, a property list is created for the application class SimpleMuscleWithProperties.class which contains a copy of all the properties from the parent class SimpleMuscleWithPanel.class (lines 4-6). This property list is made visible by overriding getAllPropertyInfo() (lines 9-11). The boxVisible property itself is then added to the property list (line 15), and accessor functions for it are declared (lines 19-25).

Figure 5.2: Control panel created by the model SimpleMuscleWithProperties, showing the newly defined property boxVisible.

The build() method calls super.build() to perform all the model creation required by the super class, and then adds an additional widget for the boxVisible property to the control panel.

To run this example in ArtiSynth, select All demos > tutorial > SimpleMuscleWithProperties from the Models menu. The control panel will now contain an additional widget for the property boxVisible as shown in Figure 5.2. Toggling this property will make the box visible or invisible in the viewer.