Switch {
exposedField MFNode choice []
exposedField SFInt32 whichChoice -1 # [-1,
)
}
The Switch grouping node traverses zero or one of the nodes specified
in the choice field.
"2.6.5 Grouping and children nodes"
describes details on the types of nodes that are legal values for choice.
The whichChoice field specifies the index of the child to
traverse, with the first child having index 0. If whichChoice is
less than zero or greater than the number of nodes in the choice
field, nothing is chosen.
All nodes under a Switch continue to receive and send events regardless
of the value of whichChoice. For example, if an active
TimeSensor is contained within an inactive choice of an Switch, the
TimeSensor sends events regardless of the Switch's state.
design note
Note that the Switch node is a grouping node, so it can't be used in
place of an Appearance or Material node to switch between different
appearances or textures. Allowing a node to act like several different
node types causes implementation difficulties, especially for
object-oriented implementations that create a hierarchy of node
classes. If Switch could appear anywhere in the scene, implementations
would have to be prepared to treat it as a group or a geometry or a
material or any other node class.
tip
A Switch node can be used to hide or "comment-out" parts of
the scene, which can be useful when you are creating a world and want
to turn parts of it off quickly. Just replace any Group or Transform
with
Switch { choice Group/Transform ... }
The default value for the whichChoice field is 1, so the
Group/Transform will not be displayed.
If you need to switch between different textures or materials for a
Shape, there are a couple of ways of doing it. The obvious way
# THIS EXAMPLE IS ILLEGAL!
Shape {
appearance Appearance {
material DEF ILLEGAL Switch { # Switch is NOT a material!
choice [
# Materials are NOT legal children!
DEF M1 Material { ... }
DEF M2 Material { ... }
]
}
}
geometry IndexedFaceSet ...
}
does not work, because Switch nodes are not materials, and Material
nodes are not legal children nodes. Instead, you can switch between two
different shapes that share parts that aren't changing with DEF/USE,
like this:
Switch {
choice [
Shape {
appearance Appearance {
material DEF M1 Material { ... }
}
geometry DEF IFS IndexedFaceSet ...
}
Shape {
appearance Appearance {
material DEF M2 Material { ... }
}
geometry USE IFS # Same geometry, different material
}
]
}
Or, alternatively, you can write a Script that changes the Material
node directly. For example, here is a prototype that encapsulates a
Script that just toggles a Material between two different colors based
on an SFBool eventIn:
PROTO ToggleMaterial [
field SFColor color1 1 1 1 # White and
field SFColor color2 0 0 0 # black by default
eventIn SFBool which ]
{
DEF M Material { }
DEF S Script {
field SFColor color1 IS color1
field SFColor color2 IS color2
eventIn SFBool which IS which
eventOut SFColor color_changed
url "javascript:
function initialize() {
color_changed = color1;
}
function which(value) {
if (value) color_changed = color2;
else color_changed = color1;
}"
}
ROUTE S.color_changed TO M.set_diffuseColor
}
# Use like this:
Group {
children [
Shape {
appearance Appearance {
material DEF TM ToggleMaterial {
color1 1 0 0 color2 0 1 0
}
}
geometry Cube { }
}
DEF TS TouchSensor { }
]
ROUTE TS.isOver TO TM.which
}
tip
Bindable nodes (Background, Fog, NavigationInfo, and Viewpoint) are not
bound by setting their parent Switch's whichChoice field and
have no effect on whether a bindable node is active or not. For
example, the following file excerpt has a Switch node that has
activated the second choice (whichChoice 1). However, the
first choice is the first encountered Background node in the file and
is bound at load time (i.e., whichChoice has no effect on
binding):
...
Switch {
whichChoice 1 # sets second choice, B2, as active
choice [
DEF B1 Background { ... } # choice 0 bound at load time
DEF B2 Background { ... } # choice 1 not bound at load time
DEF B3 Background { ... } # choice 2
...
]
}
...
The following example illustrates a simple use of the Switch node (see
Figure 3-55). A TouchSensor is routed to a Script, which cycles
through the whichChoice field of the Switch node:
#VRML V2.0 utf8
Group { children [
DEF SW Switch {
whichChoice 0 # set by Script
choice [
Shape { # choice 0
geometry Box {}
appearance DEF A1 Appearance {
material Material { diffuseColor 1 0 0 }
}
}
Shape { # choice 1
geometry Sphere {}
appearance DEF A1 Appearance {
material Material { diffuseColor 0 1 0 }
}
}
Shape { # choice 2
geometry Cone {}
appearance DEF A1 Appearance {
material Material { diffuseColor 0 0 1 }
}
}
]
}
DEF TS TouchSensor {}
DEF SCR Script { # Switches the choice
eventIn SFTime touchTime
eventOut SFInt32 whichChoice
url "javascript:
function initialize() {
whichChoice = 0;
}
function touchTime( value, time) {
if ( whichChoice == 2 ) whichChoice = 0;
else ++whichChoice;
}"
}
NavigationInfo { type "EXAMINE" }
]}
ROUTE TS.touchTime TO SCR.touchTime
ROUTE SCR.whichChoice TO SW.whichChoice

Figure 3-55: Switch Node Example