The Moving Worlds VRML 2.0 Specification

Working Draft #2

Appendix A: Java Bindings

April 18, 1996

This appendix describes the Java classes and methods that allow scripts to interact with associated scenes. It contains links to various Java pages as well as to certain sections of the Moving Worlds spec (including the general description of scripting and the API).

Language

Java(TM) is a portable, interpreted, object-oriented programming language developed at Sun Microsystems. It's likely to be the most common language supported by VRML browsers in Script nodes. A full description of Java is far beyond the scope of this appendix; see the Java web site for more information. This appendix describes only the Java bindings of the VRML API (the calls that allow the script in a VRML Script node to interact with the scene in the VRML file).

Exposed Classes and Methods for Nodes and Fields

Java classes for VRML are defined in the package vrml. (Package names are generally all-lowercase, in deference to UNIX file system naming conventions.)

The Field class extends Java's Object class by default (when declared without an explicit superclass, as below); thus, Field has the full functionality of the Object class, including the getClass() method. The rest of the package defines a "Const" read-only class for each VRML field type, with a getValue() method for each class; and another read/write class for each VRML field type, with both getValue() and setValue() methods for each class.

Most of the setValue() methods are listed as "throws exception," meaning that errors are possible -- you may need to write exception handlers (using Java's catch() method) when you use those methods. Any method not listed as "throws exception" is guaranteed to generate no exceptions. Each method that throws an exception is followed by a comment indicating what type of exception will be thrown.

package vrml;

class Field {
}


//
// Read-only (constant) classes, one for each field type:
//

class ConstSFBool extends Field {
  public boolean getValue();
}

class ConstSFColor extends Field {
  public float[] getValue();
}

class ConstMFColor extends Field {
  public float[][] getValue();
}

class ConstSFFloat extends Field {
  public float getValue();
}

class ConstMFFloat extends Field {
  public float[] getValue();
}

class ConstSFImage extends Field {
  public byte[] getValue(int[] dims);
}

class ConstSFInt32 extends Field {
  public int getValue();
}

class ConstMFInt32 extends Field {
  public int[] getValue();
}

class ConstSFNode extends Field {
  public Node getValue();
}

class ConstMFNode extends Field {
  public Node[] getValue();
}

class ConstSFRotation extends Field {
  public float[] getValue();
}

class ConstMFRotation extends Field {
  public float[][] getValue();
}

class ConstSFString extends Field {
  public String getValue();
}

class ConstMFString extends Field {
  public String[] getValue();
}

class ConstSFVec2f extends Field {
  public float[] getValue();
}

class ConstMFVec2f extends Field {
  public float[][] getValue();
}

class ConstSFVec3f extends Field {
  public float[] getValue();
}

class ConstMFVec3f extends Field {
  public float[][] getValue();
}

class ConstSFTime extends Field {
  public double getValue();
}


//
// And now the writeable versions of the above classes:
//

class SFBool extends Field {
  public boolean getValue();
  public void setValue(boolean value);
}

class SFColor extends Field {
  public float[] getValue();
  public void setValue(float[] value)
    throws ArrayIndexOutOfBoundsException;
}

class MFColor extends Field {
  public float[][] getValue();
  public void setValue(float[][] value)
    throws ArrayIndexOutOfBoundsException;
  public void setValue(ConstMFColor value);
  public void set1Value(int index, float[] value);
}

class SFFloat extends Field {
  public float getValue();
  public void setValue(float value);
}

class MFFloat extends Field {
  public float[] getValue();
  public void setValue(float[] value);
  public void setValue(ConstMFFloat value);
  public void set1Value(int index, float value);
}

class SFImage extends Field {
  public byte[] getValue(int[] dims);
  public void setValue(byte[] data, int[] dims)
    throws ArrayIndexOutOfBoundsException;
}

// In Java, the int class is a 32-bit integer
class SFInt32 extends Field {
  public int getValue();
  public void setValue(int value);
}

class MFInt32 extends Field {
  public int[] getValue();
  public void setValue(int[] value);
  public void setValue(ConstMFInt32 value);
  public void set1Value(int index, int value);
}

class SFNode extends Field {
  public Node getValue();
  public void setValue(Node node);
}

class MFNode extends Field {
  public Node[] getValue();
  public void setValue(Node[] node);
  public void setValue(ConstMFNode node);
  public void set1Value(int index, Node node);
}

class SFRotation extends Field {
  public float[] getValue();
  public void setValue(float[] value)
    throws ArrayIndexOutOfBoundsException;
}

class MFRotation extends Field {
  public float[][] getValue();
  public void setValue(float[][] value)
    throws ArrayIndexOutOfBoundsException;
  public void setValue(ConstMFRotation value);
  public void set1Value(int index, float[] value);
}

// In Java, the String class is a Unicode string
class SFString extends Field {
  public String getValue();
  public void setValue(String value);
}

class MFString extends Field {
  public String[] getValue();
  public void setValue(String[] value);
  public void setValue(ConstMFString value);
  public void set1Value(int index, String value);
}

class SFTime extends Field {
  public double getValue();
  public void setValue(double value);
}

class SFVec2f extends Field {
  public float[] getValue();
  public void setValue(float[] value)
    throws ArrayIndexOutOfBoundsException;
}

class MFVec2f extends Field {
  public float[][] getValue();
  public void setValue(float[][] value)
    throws ArrayIndexOutOfBoundsException;
  public void setValue(ConstMFVec2f value);
  public void set1Value(int index, float[] value);
}

class SFVec3f extends Field {
  public float[] getValue();
  public void setValue(float[] value)
    throws ArrayIndexOutOfBoundsException;
}

class MFVec3f extends Field {
  public float[][] getValue();
  public void setValue(float[][] value)
    throws ArrayIndexOutOfBoundsException;
  public void setValue(ConstMFVec3f value);
  public void set1Value(int index, float[] value);
}


//
// Interfaces (abstract classes that your classes can inherit from
// but that you can't instantiate) relating to events and nodes:
//

interface EventIn {
  public String getName();
  public SFTime getTimeStamp();
  public ConstField getValue();
}

interface Node {
  public ConstField getValue(String fieldName)
    throws InvalidFieldException;
  public void postEventIn(String eventName, Field eventValue)
    throws InvalideEventInException;
}


//
// This is the general Script class, to be subclassed by all scripts.
// Note that the provided methods allow the script author to explicitly
// throw tailored exceptions in case something goes wrong in the
// script; thus, the exception codes for those exceptions are to be
// determined by the script author.
//

class Script implements Node {
  public void processEvents(Events [] events)
    throws Exception; // Script:code is up to script author
  public void eventsProcessed()
    throws Exception; // Script:code is up to script author
  protected Field getEventOut(String eventName)
    throws InvalidEventOutException;
  protected Field getField(String fieldName)
    throws InvalidFieldException;
}

Browser Interface

This section lists the public Java interfaces to the Browser class, which allows scripts to get and set browser information. For descriptions of the methods, see the "Browser Interface" section of the "Scripting" section of the spec.

public class Browser {

  public static String getName();
  public static String getVersion();

  public static String getNavigationType();
  public static void setNavigationType(String type)
    throws InvalidNavigationTypeException;

  public static float getNavigationSpeed();
  public static void setNavigationSpeed(float speed);

  public static float getCurrentSpeed();

  public static float getNavigationScale();
  public static void setNavigationScale(float scale);

  public static boolean getHeadlight();
  public static void setHeadlight(boolean onOff);

  public static String getWorldURL();
  public static void loadWorld(String [] url);

  public static float getCurrentFrameRate();

  public static Node createVrmlFromURL(String[] url)
    throws InvalidVRMLException;
  public static Node createVrmlFromString(String vrmlSyntax)
    throws InvalidVRMLException;

  public void addRoute(Node fromNode, String fromEventOut,
    Node toNode, String toEventIn)
    throws InvalidRouteException;
  public void deleteRoute(Node fromNode, String fromEventOut,
    Node toNode, String toEventIn)
    throws InvalidRouteException;

  public void bindBackground(Node background);
  public void unbindBackground();
  public boolean isBackgroundBound(Node background);

  public void bindNavigationInfo(Node navigationInfo);
  public void unbindNavigationInfo();
  public boolean isNavigationInfoBound(Node navigationInfo);

  public void bindViewpoint(Node viewpoint);
  public void unbindViewpoint();
  public boolean isViewpointBound(Node viewpoint);

}

System and Networking Libraries

To perform system or networking calls, use the appropriate standard Java libraries.

Example

Here's an example of a Script node which determines whether a given color contains a lot of red. The Script node exposes a color field, an eventIn, and an eventOut:

Script {
  field SFColor currentColor 0 0 0
  eventIn SFColor colorIn
  eventOut SFBool isRed

  scriptType "javabc"
  behavior "ExampleScript.java"
}

[[should we rename colorIn to setCurrentColor, or would that imply that one was required to use this naming convention?]]

And here's the source code for the "ExampleScript.java" file that gets called every time an eventIn is routed to the above Script node:

import vrml;


class ExampleScript extends Script {

  // Declare field(s)
  private SFColor currentColor = (SFColor) getField("currentColor");

  // Declare eventOut field(s)
  private SFBool isRed = (SFBool) getEventOut("isRed");

  public void colorIn(ConstSFColor newColor, ConstSFTime ts) {
    // This method is called when a colorIn event is received
    currentColor.setValue(newColor.getValue());
}

  public void eventsProcessed() {
    if (currentColor.getValue()[0] >= 0.5) // if red is at or above 50%
      isRed.setValue(TRUE);
  }

}

For details on when the methods defined in ExampleScript are called, see the "Execution Model" section of the "Concepts" document.