Touch me

tested with ++


Today I talk about the TouchSensor and how to ROUTE events from it. The TouchSensor is one of five pointing device sensors (speak: mouse). It is used as a child of the triggering parent node.
Let's say you modeled a light switch and you want it to do something when clicked on. You would place a TouchSensor node into the lightSwitch group. The lightSwitch is the parent and the TouchSensor is one of it's children.

DEF lightSwitch Group {

  children [

    lots of children ...

    DEF touchSwitch TouchSensor { }

  ]

}
Most of the time you will need to name your TouchSensor in order to ROUTE from it. The TouchSensor has several eventOuts and one of them is isActive. When clicked on the TouchSensor's parent node the TouchSensor will emit the event TRUE since it is active now. OK, now I have that 'TRUE' floating around, so what? The solution is 'ROUTEing'. A ROUTE simply takes the eventOut value and ROUTEs it to an eventIn. Wou wou wou, not that fast, what eventIn are you tallking about? Without a Script node there are not many interesting eventIns to ROUTE to. Viewpoint for example has an eventIn of type boolean.
Viewpoints let the user view your world from different locations. It is sometimes easy to get lost in VR space so it is a good idea to provide your visitors with central orientation points. Let's add two of them to our Hello World file and rename it to 'touchme.wrl':


DEF view1 Viewpoint {

  position 0 0 20

  description "view1"

}

DEF view2 Viewpoint {

  position 5 0 20

  description "view2"

}

The Viewpoints are named and the names appear as a string in the field description. This has the benefit that a visitor can directly change viewpoints from the browser's menu (hopefully). The position field locates view1 at x=0 y=0 z=20. This is 20 units (meters) in front of the sphere. View2 is 5 units to the right, thus in front of the red cube.
Back to our main topic: place a TouchSensor as a child into the box Transform.


DEF box Transform {

  children [

    Shape { ... Box ... }

    DEF touchBox TouchSensor { }

  ]

}

....

Check the Touch me source and look at Touch me.wrl. Clicking on the TouchSensor will do not much (nothing visible, only sending 'isActive'-eventOuts out).
That is what we need the ROUTE for. It will take the 'touchBox' eventOut (TRUE) and ROUTE it to the eventIn of 'view2'. The eventIn we need is set_bind which deactivates the current Viewpoint and activates the one we ROUTEd to.


ROUTE touchBox.isActive TO view2.set_bind

After loading the scene (Touch me.wrl) click on the box and keep the mouse button down. This will ROUTE the 'touchBox' eventOut to the 'view2' eventIn. The technical term is 'a viewpoint is bound to the current view'.
Hmm, interesting, but I want to jump to the new viewpoint and stay there. How can I accomplish this?
We need a Script for this. A Script node has like any other nodes eventIn, eventOut, and field values. For our purpose we need to feed an eventIn from the TouchSensor node to the Script node. I call it 'touchBoxIsActive'. We also need an eventOut from the Script node which we feed to the Viewpoint node. I call it 'bindView2'.


DEF touchScript Script {

  eventIn SFBool touchBoxIsActive

  eventOut SFBool bindView2

  ....

}

Think of a Script as a black box. You send it an eventIn (touchBoxIsActive) and you will receive an eventOut (bindView2). Let's go back to the ROUTE for a minute. We used the following ROUTE in the previous example:

ROUTE touchBox.isActive TO view2.set_bind


Now we take a detour through the Script node instead:


ROUTE touchBox.isActive TO touchScript.touchBoxIsActive

ROUTE touchScript.bindView2 TO view2.set_bind


Still, our scene won't do much. The Script node isn't written yet. All what we need for that is a statement which sets on receiving an eventIn the eventOut to TRUE.


  function touchBoxIsActive(active) {

    bindView2 = TRUE;

  }

When node 'touchScript' receives an eventIn (touchBoxIsActive), it calls the function 'touchBoxIsActive' and executes it. Here it simply sets 'bindView2' to TRUE. Now there is an eventOut available and can be ROUTEd to the Viewpoint node.
The function itself is written in 'javascript'.

url "javascript:

  function touchBoxIsActive(active) {

    bindView2 = TRUE;

  }"
Please note that the name of the eventIn is identical to the name of the function. Every eventIn to a Script has a corresponding function. As a result, the Touch me.wrl scene will change it's viewpoint permanently. You can change the viewpiont back via the browser menu. Touch me source shows today's work as a whole.

I hope that I could bring some light to this topic. ROUTEing and Scripting are important features in VRML2.0 and once you understand the concept of eventIns and eventOuts you will have a solid base for further experiments.





Copyright © 1996-98 Markus Roskothen. All rights reserved.