<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile='Immersive' version='3.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.0.xsd'>
  <head>
    <meta content='ViewpointGroupPrototype.x3d' name='title'/>
    <meta content='ViewpointGroup contains Viewpoint and ViewpointGroup nodes, allowing nested lists and viewpoint scoping in viewpoint lists. This is a developmental example for potential specification improvement. It is needed because (a) currently specified rules for X3D/VRML node binding state that behavior of child Viewpoints beneath Switch/LOD/etc. is undefined, and (b) browser viewpoint list display behavior is undefined.' name='description'/>
    <meta content='Don Brutzman' name='creator'/>
    <meta content='29 October 2003' name='created'/>
    <meta content='20 October 2019' name='modified'/>
    <meta content='this prototype is for development purposes only, do not override native player support for ViewpointGroup' name='warning'/>
    <meta content='ViewpointListViewpointGroupProse.html' name='reference'/>
    <meta content='ViewpointGroupExample.x3d' name='reference'/>
    <meta content='https://www.web3d.org/specifications/X3Dv4/ISO-IEC19775-1v4-IS/Part01/components/navigation.html#Viewpoint' name='reference'/>
    <meta content='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#Viewpoint' name='reference'/>
    <meta content='ViewpointGroup Viewpoint' name='subject'/>
    <meta content='https://www.web3d.org/x3d/content/examples/Basic/development/ViewpointGroupPrototype.x3d' name='identifier'/>
    <meta content='X3D-Edit 3.3, https://www.web3d.org/x3d/tools/X3D-Edit' name='generator'/>
    <meta content='../license.html' name='license'/>
  </head>
  <Scene>
    <WorldInfo title='ViewpointGroupPrototype.x3d'/>
    <ProtoDeclare appinfo='warning: developmental prototype for X3D v3.2 node do not override native support!' name='ViewpointGroup'>
      <ProtoInterface>
        <field accessType='inputOutput' appinfo='[Viewpoint | ViewpointGroup] only' name='children' type='MFNode'>
          <!-- initialized at runtime, default is empty array of Viewpoint/ViewpointGroup nodes. -->
        </field>
        <field accessType='inputOutput' appinfo='Text description or navigation hint to be displayed for this ViewpointGroup.' name='description' type='SFString'/>
        <field accessType='inputOutput' appinfo='Whether this ViewpointGroup description is displayed in current viewpoint list.' name='displayed' type='SFBool' value='true'/>
        <field accessType='inputOutput' appinfo='Position offset from origin of local coordinate system.' name='center' type='SFVec3f' value='0 0 0'/>
        <field accessType='initializeOnly' appinfo='[0..infinity) Radius in meters of Proximity box within which the ViewpointGroup is usable and displayed on the viewpoint list.' name='radius' type='SFFloat' value='10'/>
        <field accessType='inputOnly' appinfo='[0..infinity) Radius in meters of Proximity box within which the ViewpointGroup is usable and displayed on the viewpoint list.' name='set_radius' type='SFFloat'/>
        <field accessType='inputOutput' appinfo='Whether viewpoint needs to retain (true) or rezero (false) any prior user navigation offsets from defined viewpoint position orientation.' name='retainUserOffsets' type='SFBool' value='true'/>
      </ProtoInterface>
      <ProtoBody>
        <Group>
          <ProximitySensor DEF='ProximityZone' size='20 20 20'>
            <IS>
              <connect nodeField='center' protoField='center'/>
            </IS>
          </ProximitySensor>
          <Switch DEF='ViewpointsSwitch' whichChoice='0'>
            <Group>
              <IS>
                <connect nodeField='children' protoField='children'/>
              </IS>
            </Group>
          </Switch>
          <Switch DEF='HoldExposedFields' whichChoice='-1'>
            <!-- WorldInfo not used because title field is accessType initializeOnly -->
            <Anchor DEF='DescriptionHolder'>
              <IS>
                <connect nodeField='description' protoField='description'/>
              </IS>
            </Anchor>
            <ProximitySensor DEF='DisplayedHolder'>
              <IS>
                <connect nodeField='enabled' protoField='displayed'/>
              </IS>
            </ProximitySensor>
          </Switch>
          <Script DEF='UnbindingControlScript' directOutput='true'>
            <field accessType='inputOnly' name='isActive' type='SFBool'/>
            <field accessType='initializeOnly' name='ProximityZone' type='SFNode'>
              <ProximitySensor USE='ProximityZone'/>
            </field>
            <field accessType='initializeOnly' appinfo='[0..infinity) Radius in meters of Proximity box within which the ViewpointGroup is usable and displayed on the viewpoint list.' name='radius' type='SFFloat'/>
            <field accessType='inputOnly' appinfo='[0..infinity) Radius in meters of Proximity box within which the ViewpointGroup is usable and displayed on the viewpoint list.' name='set_radius' type='SFFloat'/>
            <field accessType='initializeOnly' name='viewpointsSwitch' type='SFNode'>
              <Switch USE='ViewpointsSwitch' whichChoice='-1'/>
            </field>
            <!-- use node holders to work around VRML 97 Script exposedField restriction -->
            <field accessType='initializeOnly' name='descriptionHolder' type='SFNode'>
              <Anchor USE='DescriptionHolder'/>
            </field>
            <field accessType='initializeOnly' name='displayedHolder' type='SFNode'>
              <ProximitySensor USE='DisplayedHolder'/>
            </field>
            <field accessType='initializeOnly' name='description' type='SFString'/>
            <field accessType='initializeOnly' name='displayed' type='SFBool' value='true'/>
            <field accessType='initializeOnly' name='traceEnabled' type='SFBool' value='false'/>
            <IS>
              <connect nodeField='radius' protoField='radius'/>
              <connect nodeField='set_radius' protoField='set_radius'/>
            </IS>
            <![CDATA[
ecmascript:

function initialize ()
{
	// since Viewpoints remain on binding stack as before,
	// no initialization action is necessary when implemented natively.
	description = descriptionHolder.description;
	displayed = displayedHolder.enabled;
	tracePrint ('displayed=' + displayed);
	if (!displayed) viewpointsSwitch.whichChoice = -1;
	set_radius (radius);

	// typecheck valid children nodes:
	tracePrint ('viewpointsSwitch.choice.length=' + viewpointsSwitch.choice.length);
	if (viewpointsSwitch.choice.length >= 1)
		for (i=0; i >= viewpointsSwitch.choice.length; i)
		{
			// how to check type?
			// if (viewpointsSwitch.choice[i].____ etc.)
			// once type checked, warn if Viewpoint position outside proximity box size
		}
	tracePrint ('... initialize() complete');
}
function isActive (activeValue)
{
	// Most likely, viewpoint list actions will be controlled by browser.

	// If viewpoint list is exposed via SAI, could do things here
	// such as setting ViewpointGroup.description as browser label.

	// Current action:  switch child Viewpoints in/out of scope.
	tracePrint ('activeValue=' + activeValue);

	tracePrint ('displayed=' + displayed);
	if (!displayed) return;

	if (activeValue) viewpointsSwitch.whichChoice =  0;
	else             viewpointsSwitch.whichChoice = -1;

	tracePrint ('viewpointsSwitch.whichChoice=' + viewpointsSwitch.whichChoice);
}
function set_radius (value, timestamp)
{
	radius = value;
	ProximityZone.size.x = 2 * radius;
	ProximityZone.size.y = 2 * radius;
	ProximityZone.size.z = 2 * radius;
	tracePrint ('set_radius (' + value + '), radius=' + radius + ', ProximityZone.size=' + ProximityZone.size);
}

function tracePrint(outputString)
{
	if (traceEnabled) Browser.println ('[ViewpointGroup' + description + ']' + outputString);
}
function alwaysPrint(outputString)
{
	Browser.println ('[ViewpointGroup' + description + ']' + outputString);
}
]]>
          </Script>
          <ROUTE fromField='isActive' fromNode='ProximityZone' toField='isActive' toNode='UnbindingControlScript'/>
        </Group>
      </ProtoBody>
    </ProtoDeclare>
    <!-- ===============Example============== -->
    <NavigationInfo type='"FLY" "ANY"'/>
    <Anchor description='ViewpointGroupExample' parameter='"target=_blank"' url='"ViewpointGroupExample.x3d" "https://www.web3d.org/x3d/content/examples/Basic/development/ViewpointGroupExample.x3d" "ViewpointGroupExample.wrl" "https://www.web3d.org/x3d/content/examples/Basic/development/ViewpointGroupExample.wrl"'>
      <Shape>
        <Text string='"ViewpointGroupPrototype" "defines a prototype" "" "Click on this text to see" "ViewpointGroupExample scene"'>
          <FontStyle justify='"MIDDLE" "MIDDLE"' size='0.5'/>
        </Text>
        <Appearance>
          <Material diffuseColor='1 1 0.2'/>
        </Appearance>
      </Shape>
    </Anchor>
    <Viewpoint description='inside scope: ViewpointGroup' position='0 0 5'/>
    <Viewpoint description='outside scope: ViewpointGroup' position='0 0 12'/>
  </Scene>
</X3D>