2.4. Event Routing and Scripting

Communications in VC are implemented through message routing. Messages can be sent to or received from external applications through UDP protocol, they can be routed from one scene node to one or more other nodes, or they can be received from user interactions. Responses to events are described into scripts attached to nodes in the scene graph.

2.4.1. Events

The received events are processed on a First In First Out basis whatever their source. They are stored in an output event queue that is flushed at each frame rate by dispatching the events to the target scene nodes or external applications. Emitted events are processed on the same basis and stored in an input event queue. To reduce the overhead due to event routing, received and emitted events are controlled as follows:

Figure 2-6 shows the data flow for event processing. Events received in the input queue are processed by an interpreter. For each event and for each target node, the script of the corresponding node is retrieved. If the script contains a command triggered by the message carried by the event, the command is executed by the interpreter. If the command triggers output events, they are stored in the output queue. If the triggering event is controlled by a node state and an operator, the corresponding action(s) are only performed if the comparison between the node state and the expected state is true.

Output events are issued by the interpreter if the action triggers events, or by the browser in the case of automatic updates of objects that are not rendered by the browser (for instance sonic objects). The router is in charge of dispatching these events to their targets. Events for internal scene nodes are added to the input queue, events for external applications are sent to the UDP ports of the corresponding applications.

Input events that are received from the router (see above), from user interactions, or from external applications through UDP communications are causal events. In addition to these events, scripts can also contain scheduled events that are triggered at predefined times. Scheduled events can be used to modify the appearance of a scene in an animation film.

Figure 2-6. Event Routing and Processing

2.4.2. Scripting

Any node in a scene graph can contain a script: a list of commands made of the following three components:

Nodes have states that can be dynamically modified. States are used by VC to control the triggering of actions upon the reception of messages.

Scripts can also be associated with schedules: completion scripts that are executed once when the schedule terminates, and update scripts that are executed at each frame in which the schedule is active. In both scripts, commands do not have triggers because their activation does not rely on the reception of external events.

The following script is made of three commands. The first one is triggered if the node receives a message volumeh. In this case, the action performed is set_node_attribute_value, a modification the x, y, and z values of the scale transformation expected to be found on the node named hvscale cylinder #1. The second command is triggered by a key stroke. Since key events are not directed towards a specific node, all the commands triggered by key events are relocated at the root node during a preprocessing of the scene graph. The associated action sends a message start rotate to the node named moving cylinder #0. The third command is scheduled at time 7 and sends a UDP message. A target udp_host is specified for this command: a UDP server defined in the configuration file (see environment node). For instance, interactive control modules such as PureData or MaxMSP can be target hosts if a UDP server is defined in these applications. The fourth and fifth commands are both triggered by the message click. These actions are only executed if the node is in the state A_ongoing. The fourth action modifies the sonic properties of the target node, and the fifth command modifies the internal state of the target node.

<script id="script_metro">
  <command>
    <trigger type="message_event" value="volumeh" /> 
    <action>
      <set_node_attribute_value operator="="> 
        <transformation x="2.0" y="2.0" z="2.0" />
      </set_node_attribute_value> 
      <target type="single_node" value="#hvscale cylinder #1" /> 
    </action>
  </command>
  <command>
    <trigger type="keystroke" value="C" /> 
    <action>
      <send_message value="start rotate" />
      <target type="single_node" value="#moving cylinder #0" />
    </action>
  </command>
  <command>
    <trigger type="time_limit" value="7" /> 
    <action>
      <send_message_udp value="source 0 level 100" />
      <target type="single_host" value="spatializer" />
    </action>
  </command>
  <command>
    <trigger type="message_event" value="click" 
             state="A" bool_operator="==" /> 
    <action>
      <set_sound_attribute_value operator="=">
        <sound begin="now" end="100000" />
      </set_sound_attribute_value>
      <set_internal_state value="A_ongoing" />
      <target type="single_node" value="#sphere 1" />
    </action>
  </command>
</script>