Contributors

Proposal for a VRML 2.0 Informative Annex

External Authoring Interface Reference

Chris Marrin

August 2, 1996

For communication between a VRML world and its external environment some means of communication between the two is needed. This interface is call an external API and it defines the set of functions on the VRML browser that the external environment can perform to affect the VRML world. Two examples of this interface are language bindings for Java or some other language, and some sort of network aware socket interface.

Note: Current work with a prototype external API is ongoing. This interface uses LiveConnect and Netscape Navigator 3.0. The interface described is largely influenced by that work. It is intended that the final API will consist of a set of generic rules for interfacing to a VRML scene with binding between that abstraction and several popular environments. But for now both are contained in this single document for clarity in understanding how to apply the abstract rules in a practical system.

VRML 2.0 API

Nodes in VRML can be named using the "DEF" construct. This naming gives a convenient mechanism for accessing nodes from an external interface. Any node named with the DEF construct can be accessed from outside the VRML world. A node so named is referred to as an accessible node. Access to the node's internal data structures from the external API is limited to the eventIns and eventOuts of that node. This implies that the eventIn and eventOut components of an exposedField can also be accessed, using the set_ and _changed modifiers. Interfaces are provided to send an eventIn to a accessible node. That node will receive that event just as if it had come through a ROUTE, or had been set by the script of a Script node. When an eventOut is sent from an accessible node that event is sent through the external API for handling, using a previously defined callback. The current value of an eventOut can also be gotten from the node.

Language Access

Access to the VRML world can be done through a language interface. Using Netscape Navigator 3.0 and above, this interface is called LiveConnect. Microsoft Internet Explorer uses a different set of interfaces but it is expected that similar access to a VRML world will be possible there.

With LiveConnect all interface to a VRML world is done through a set of Java native API classes. Every frame on a Netscape page appears to Java as a subclass of the Plugin class. The Java class for a VRML plugin is called Browser. A pointer to a Browser instance can be obtained in a Java applet using the netscape package. Here is the definition of that class:

::::::::::::::::::
:: browser.java ::
::::::::::::::::::

package vrml.browser;

// Java file specifying the External API for VRML Browser.
import java.lang.*; // Needed for String class

import netscape.plugin.Plugin;
import vrml.node.Node;
import vrml.exception.InvalidNodeException;
import vrml.exception.InvalidVrmlException;

//
// Browser API //
//

public class Browser extends Plugin {
    // Get a DEFed node by name
    native public Node getNode(String name)
        throws InvalidNodeException;

    // Get the name and version of the VRML browser
    native public String getName();
    native public String getVersion();

    // get info about the scene
    native public float getCurrentSpeed();
    native public float getCurrentFrameRate();
    native public String getWorldURL();

    // replace the current world with the passed nodes
    native public void replaceWorld(Node[] nodes);

    // Parse STRING into a VRML scene and return the list of root
    // nodes for the resulting scene.
    native public Node[] createVrmlFromString(String vrmlSyntax)
        throws InvalidVRMLException;

    // Parse data at the passed URL into a VRML scene.  When complete
    // send the nodes as an MFNode event to the passed eventIn in 
    // the passed node.
    native public void createVrmlFromURL(String[] url, Node node, String event)
        throws InvalidVRMLException;

    // Add or delete the given route
    native public void addRoute(Node fromNode, String fromEventOut,
                         Node toNode, String toEventIn);
    native public void deleteRoute(Node fromNode, String fromEventOut,
                         Node toNode, String toEventIn);

    // Load the passed URL using the passed parameter strings.
    native public void loadURL(String[] url, String[] parameter)
        throws InvalidVRMLException;

    // Set the description in a browser dependent way
    native public void setDescription(String description);
}

The above interface is the Browser API as defined in the VRML 2.0 spec with the addition of a single method, getNode, to get an instance of an accessible node.

Accessing EventIns and EventOuts

Once a Node instance is obtained from the getNode method of the Browser class, it's EventIns and EventOuts can be accessed by first obtaining an instance of the EventIn or EventOut class for the desired value. Here is the definition of the Node class:

::::::::::::::
node.java
::::::::::::::

package vrml.node;

import vrml.field.EventIn;
import vrml.field.EventOut;
import vrml.exception.InvalidEventInException;
import vrml.exception.InvalidEventOutException;

// Java wrapper class for a VRML node.
public class Node {
    // Means of getting a handle to an EventIn of this node
    native public EventIn getEventIn(String name)
        throws InvalidEventInException;

    // Means of getting a handle to an EventOut of this node
    native public EventOut getEventOut(String name)
        throws InvalidEventOutException;
}

The methods of the Node class return an instance of an EventIn or EventOut contained in that node when given a string corresponding to the eventIn or eventOut name. ExposedFields can also be accessed, either by giving a string for the exposedField itself (such as "translation") or by giving the name of the corresponding eventIn or eventOut ("set_translation" for the eventIn and "translation_changed" for the eventOut).

Sending Events to an EventIn

Once an instance of the desired EventIn is obtained, an event can be sent to it. To do this the EventIn must first be cast to the appropriate field type subclass. Here is the definition of the EventIn abstract class and an example of one of the field types subclassed from it. The remaining classes are found at the end of this document:

::::::::::::::
eventin.java
::::::::::::::

package vrml.field;

// Base class for EventIn types
public abstract class EventIn {
}

::::::::::::::
eventinsfvec3f.java
::::::::::::::

package vrml.field;

public class EventInSFVec3f extends EventIn {
    native public void set(float[] value)
        throws ArrayIndexOutOfBoundsException;
}

Here is an example of sending an eventIn to a VRML scene containing this node:

    DEF Mover Transform { ... }

Here is the Java code to send it an event to change its translation field (assume browser is the instance of a Browser class gotten from a previous call):

    Node mover = browser.getNode("Mover");
    EventInSFVec3f translation = 
                (EventInSFVec3f) mover.getEventIn("set_translation");

    float value[3] = new float[3];
    value[0] = 5; value[1] = 0; value[2] = 1;
    translation.set(value);

In the above example, the translation value (5, 0, 1) is sent to the translation field of the Transform node.

Accessing an EventOut

Once an instance of a desired EventOut is obtained, 2 functions can be performed. The current value of the eventOut can be gotten and a callback can be setup to be invoked when an eventOut is generated. To do either of these operations requires that you first cast the EventOut to the appropriate field type subclass. Here is the definition of the EventOut abstract class and an example of one of the field types subclassed from it. The remaining classes are found at the end of this document:

::::::::::::::
eventout.java
::::::::::::::

package vrml.field;

// Base class for EventOut types
public abstract class EventOut {
    // Mechanism for setting up an observer for this field.
    // The FieldObserver's callback gets called when the
    // EventOut's value changes.
    public void setObserver(EventOutObserver f, int fId) {
        observer = f; id = fId; hasObserver = true;
    }
}

::::::::::::::
eventoutsfvec3f.java
::::::::::::::

package vrml.field;

public class EventOutSFVec3f extends EventOut {
    native public float[] get();
}

Using the eventIn example above, the current value of the translation field can be read like this:

    float current[] = ((EventOutSFVec3f)
                      (mover.getEventOut("translation_changed"))).get();

The EventOut Observer

To receive notification when an eventOut is generated from the scene, the applet must first subclass the EventOutObserver class to define a method to be called. Then an instance of this class is set on the EventOut using the setObserver method. Here is the EventOutObserver class:

::::::::::::::
eventoutobserver.java
::::::::::::::

package vrml.field;

import vrml.field.EventOut;

// Interface which all observer classes must implement.

public interface EventOutObserver {
    void callback(EventOut value, double timeStamp, int id);
}

When the eventOut is generated the callback method of the observer is called with the value of the event, the timestamp and a user specified id. Here is an example, based on the above example, of getting notified when the translation field of the Transform is changed:

    public class MyObserver implements EventOutObserver {
        public void callback(EventOut value, double timeStamp, int id)
        {
            // cast value into an EventOutSFVec3f and use it
        }
    }

    ...

    MyObserver observer = new MyObserver;
    mover.getEventOut("translation_changed").setObserver(observer, 0);

When the eventOut occurs, observer.callback() is called.

Java Interface

As mentioned before the above examples are given as the Java bindings to LiveConnect. He is a complete list of the .java files making up that interface:

::::::::::::::
browser.java
::::::::::::::

package vrml.browser;

// Java file specifying the External API for VRML Browser.
import java.lang.*; // Needed for String class

import netscape.plugin.Plugin;
import vrml.node.Node;
import vrml.exception.InvalidNodeException;
import vrml.exception.InvalidVrmlException;

//
// Browser API //
//

public class Browser extends Plugin {
    // Get a DEFed node by name
    native public Node getNode(String name)
        throws InvalidNodeException;

    // Get the name and version of the VRML browser
    native public String getName();
    native public String getVersion();

    // get info about the scene
    native public float getCurrentSpeed();
    native public float getCurrentFrameRate();
    native public String getWorldURL();

    // replace the current world with the passed nodes
    native public void replaceWorld(Node[] nodes);

    // Parse STRING into a VRML scene and return the list of root
    // nodes for the resulting scene.
    native public Node[] createVrmlFromString(String vrmlSyntax)
        throws InvalidVRMLException;

    // Parse data at the passed URL into a VRML scene.  When complete
    // send the nodes as an MFNode event to the passed eventIn in 
    // the passed node.
    native public void createVrmlFromURL(String[] url, Node node, String event)
        throws InvalidVRMLException;

    // Add or delete the given route
    native public void addRoute(Node fromNode, String fromEventOut,
                         Node toNode, String toEventIn);
    native public void deleteRoute(Node fromNode, String fromEventOut,
                         Node toNode, String toEventIn);

    // Load the passed URL using the passed parameter strings.
    native public void loadURL(String[] url, String[] parameter)
        throws InvalidVRMLException;

    // Set the description in a browser dependent way
    native public void setDescription(String description);
}


::::::::::::::
node.java
::::::::::::::

package vrml.node;

import vrml.field.EventIn;
import vrml.field.EventOut;
import vrml.exception.InvalidEventInException;
import vrml.exception.InvalidEventOutException;

// Java wrapper class for a VRML node.
public class Node {
    // Means of getting a handle to an EventIn of this node
    native public EventIn getEventIn(String name)
        throws InvalidEventInException;

    // Means of getting a handle to an EventOut of this node
    native public EventOut getEventOut(String name)
        throws InvalidEventOutException;
}


::::::::::::::
eventin.java
::::::::::::::

package vrml.field;

// Base class for EventIn types
public abstract class EventIn {
}


::::::::::::::
eventout.java
::::::::::::::

package vrml.field;

// Base class for EventOut types
public abstract class EventOut {
    // Mechanism for setting up an observer for this field.
    // The FieldObserver's callback gets called when the
    // EventOut's value changes.
    public void setObserver(EventOutObserver f, int fId) {
        observer = f; id = fId; hasObserver = true;
    }
}


::::::::::::::
eventoutobserver.java
::::::::::::::

package vrml.field;

import vrml.field.EventOut;

// Interface which all observer classes must implement.

public interface EventOutObserver {
    void callback(EventOut value, double timeStamp, int id);
}


::::::::::::::
eventinsfbool.java
::::::::::::::
package vrml.field;

public class EventInSFBool extends EventIn {
  native public void set(boolean value); 

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFBool() {}
}


::::::::::::::
eventinsfcolor.java
::::::::::::::
package vrml.field;

public class EventInSFColor extends EventIn {
  native public void set(float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFColor() {}
}


::::::::::::::
eventinsffloat.java
::::::::::::::
package vrml.field;

public class EventInSFFloat extends EventIn {
  native public void set(float value);

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFFloat() {}
}


::::::::::::::
eventinsfint32.java
::::::::::::::
package vrml.field;

public class EventInSFInt32 extends EventIn {
  native public void set(int value);

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFInt32() {}
}


::::::::::::::
eventinsfnode.java
::::::::::::::
package vrml.field;

import vrml.node.Node;

public class EventInSFNode extends EventIn {
  native public void set(Node value);

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFNode() {}
}


::::::::::::::
eventinsfrotation.java
::::::::::::::
package vrml.field;

public class EventInSFRotation extends EventIn {
  native public void set(float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFRotation() {}
}


::::::::::::::
eventinsfstring.java
::::::::::::::
package vrml.field;

public class EventInSFString extends EventIn {
  native public void set(String value);

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFString() {}
}


::::::::::::::
eventinsftime.java
::::::::::::::
package vrml.field;

public class EventInSFTime extends EventIn {
  native public void set(double value);

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFTime() {}
}


::::::::::::::
eventinsfvec2f.java
::::::::::::::
package vrml.field;

public class EventInSFVec2f extends EventIn {
  native public void set(float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFVec2f() {}
}


::::::::::::::
eventinsfvec3f.java
::::::::::::::
package vrml.field;

public class EventInSFVec3f extends EventIn {
  native public void set(float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInSFVec3f() {}
}


::::::::::::::
eventinmfcolor.java
::::::::::::::
package vrml.field;

public class EventInMFColor extends EventIn {
  native public void set(float[][] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFColor() {}
}


::::::::::::::
eventinmffloat.java
::::::::::::::
package vrml.field;

public class EventInMFFloat extends EventIn {
  native public void set(float[] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, float value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFFloat() {}
}


::::::::::::::
eventinmfint32.java
::::::::::::::
package vrml.field;

public class EventInMFInt32 extends EventIn {
  native public void set(int[] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, int value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventOut
  // objects from within Java.
  private EventInMFInt32() {}
}


::::::::::::::
eventinmfnode.java
::::::::::::::
package vrml.field;

import vrml.node.Node;

public class EventInMFNode extends EventIn {
  native public void set(Node[] node)
    throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, Node node)
    throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFNode() {}
}


::::::::::::::
eventinmfrotation.java
::::::::::::::
package vrml.field;

public class EventInMFRotation extends EventIn {
  native public void set(float[][] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFRotation() {}
}


::::::::::::::
eventinmfstring.java
::::::::::::::
package vrml.field;

public class EventInMFString extends EventIn {
  native public void set(String[] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, String value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFString() {}
}


::::::::::::::
eventinmfvec2f.java
::::::::::::::
package vrml.field;

public class EventInMFVec2f extends EventIn {
  native public void set(float[][] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFVec2f() {}
}


::::::::::::::
eventinmfvec3f.java
::::::::::::::
package vrml.field;

public class EventInMFVec3f extends EventIn {
  native public void set(float[][] value)
       throws ArrayIndexOutOfBoundsException;
  native public void set1(int index, float[] value)
       throws ArrayIndexOutOfBoundsException;

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventInMFVec3f() {}
}


::::::::::::::
eventoutsfbool.java
::::::::::::::
package vrml.field;

public class EventOutSFBool extends EventOut {
  native public boolean get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFBool() {}
}


::::::::::::::
eventoutsfcolor.java
::::::::::::::
package vrml.field;

public class EventOutSFColor extends EventOut {
  native public float[] get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFColor() {}
}


::::::::::::::
eventoutsffloat.java
::::::::::::::
package vrml.field;

public class EventOutSFFloat extends EventOut {
  native public float get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFFloat() {}
}


::::::::::::::
eventoutsfint32.java
::::::::::::::
package vrml.field;

public class EventOutSFInt32 extends EventOut {
  native public int get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFInt32() {}
}


::::::::::::::
eventoutsfnode.java
::::::::::::::
package vrml.field;

import vrml.node.Node;

public class EventOutSFNode extends EventOut {
  native public Node get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFNode() {}
}


::::::::::::::
eventoutsfrotation.java
::::::::::::::
package vrml.field;

public class EventOutSFRotation extends EventOut {
  native public float[] get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFRotation() {}
}


::::::::::::::
eventoutsfstring.java
::::::::::::::
package vrml.field;

public class EventOutSFString extends EventOut {
  native public String get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFString() {}
}


::::::::::::::
eventoutsftime.java
::::::::::::::
package vrml.field;

public class EventOutSFTime extends EventOut {
  // Note that this returns a VRML "Time" - the number of seconds since
  // Jan 1, 1970 GMT, rather than a Java time which is a long, the number
  // of milliseconds since Jan 1, 1970 GMT
  native public double get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFTime() {}
}


::::::::::::::
eventoutsfvec2f.java
::::::::::::::
package vrml.field;

public class EventOutSFVec2f extends EventOut {
  native public float[] get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFVec2f() {}
}


::::::::::::::
eventoutsfvec3f.java
::::::::::::::
package vrml.field;

public class EventOutSFVec3f extends EventOut {
  native public float[] get();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutSFVec3f() {}
}


::::::::::::::
eventoutmfcolor.java
::::::::::::::
package vrml.field;

public class EventOutMFColor extends EventOut {
  native public float[][] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFColor() {}
}


::::::::::::::
eventoutmffloat.java
::::::::::::::
package vrml.field;

public class EventOutMFFloat extends EventOut {
  native public float[] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFFloat() {}
}


::::::::::::::
eventoutmfint32.java
::::::::::::::
package vrml.field;

public class EventOutMFInt32 extends EventOut {
  native public int[] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventOut
  // objects from within Java.
  private EventOutMFInt32() {}
}


::::::::::::::
eventoutmfnode.java
::::::::::::::
package vrml.field;

import vrml.node.Node;

public class EventOutMFNode extends EventOut {
  native public Node[] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFNode() {}
}


::::::::::::::
eventoutmfrotation.java
::::::::::::::
package vrml.field;

public class EventOutMFRotation extends EventOut {
  native public float[][] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFRotation() {}
}


::::::::::::::
eventoutmfstring.java
::::::::::::::
package vrml.field;

public class EventOutMFString extends EventOut {
  native public String[] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFString() {}
}


::::::::::::::
eventoutmfvec2f.java
::::::::::::::
package vrml.field;

public class EventOutMFVec2f extends EventOut {
  native public float[][] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFVec2f() {}
}


::::::::::::::
eventoutmfvec3f.java
::::::::::::::
package vrml.field;

public class EventOutMFVec3f extends EventOut {
  native public float[][] get();
  native public int getSize();

  protected void finalize() throws Throwable {
    freeResources();
    super.finalize();
  }

  // Implementation details:
  // Private constructor, so you can't instantiate new EventIn/Out
  // objects from within Java.
  private EventOutMFVec3f() {}
}

 Contact cmarrin@sgi.com with questions or comments.