<?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 name='titlecontent='ViewpointSequencerPrototype.x3d'/>
<meta name='descriptioncontent='Animate through a set of Viewpoint or GeoViewpoint nodes and repeat'/>
<meta name='creatorcontent='Don Brutzman'/>
<meta name='createdcontent='10 December 2002'/>
<meta name='modifiedcontent='20 October 2019'/>
<meta name='subjectcontent='Viewpoint Tour'/>
<meta name='referencecontent='CubeWithLabeledSidesViewpointSequencerIndex.html'/>
<meta name='referencecontent=' https://www.web3d.org/x3d/content/examples//Basic/Geospatial/CaliforniaCampusesIndex.html '/>
<meta name='infocontent='Two versions of this scene are maintained in order to avoid Cross-Origin Resource Sharing (CORS) restrictions when referenced from X3D models embedded inside HTML.'/>
<meta name='referencecontent=' https://savage.nps.edu/Savage/Tools/Animation/ViewpointSequencerPrototype.x3d '/>
<meta name='referencecontent=' https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#ScalarInterpolator '/>
<meta name=' TODO content=' eliminate intermediate TraceHolder '/>
<meta name='identifiercontent=' https://x3dgraphics.com/examples/X3dForAdvancedModeling/Animation/ViewpointSequencerPrototype.x3d '/>
<meta name='generatorcontent='X3D-Edit 3.2, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../../license.html'/>
</head>
<!--

Index for ProtoDeclare definition : ViewpointSequencer

Index for DEF nodes : ProtoBodyGroup, SequencerScript, TouchTextGroup, TouchTextSensor, TouchToggle, TraceHolder, Trigger
-->
<Scene>
<WorldInfo title='ViewpointSequencerPrototype.x3d'/>
<ProtoDeclare name='ViewpointSequencerappinfo='Sequentially binds each Viewpoint in a set of Viewpoint USE nodes, creating an automatic tour for a scene'>
<ProtoInterface>
<field name='viewpointstype='MFNodeaccessType='initializeOnly'
 appinfo='Viewpoint USE nodes that are sequentially bound'>
<!-- initialization nodes (if any) go here -->
</field>
<field name='intervaltype='SFTimevalue='5accessType='inputOutput'
 appinfo='number of seconds between viewpoint shifts'/>

<field name='enabledtype='SFBoolvalue='trueaccessType='inputOutput'
 appinfo='whether ViewpointSequencer is enabled or not'/>

<field name='set_enabledtype='SFBoolaccessType='inputOnly'
 appinfo='whether ViewpointSequencer is enabled or not'/>

<field name='previoustype='SFBoolaccessType='inputOnly'
 appinfo='bind previous Viewpoint in list'/>

<field name='nexttype='SFBoolaccessType='inputOnly'
 appinfo='bind next Viewpoint in list'/>

<field name='toggleMessagetype='MFStringvalue='"Click text to toggle" "ViewpointSequencer"accessType='inputOutput'
 appinfo='Select message to toggle ViewpointSequencer'/>

<field name='toggleMessageFontSizetype='SFFloatvalue='1accessType='initializeOnly'
 appinfo='Font size for toggleMessage text'/>

<field name='toggleMessageColortype='SFColorvalue='0.6 0.4 0.13accessType='inputOutput'
 appinfo='Color for toggleMessage text'/>

<field name='traceEnabledtype='SFBoolvalue='falseaccessType='inputOutput'
 appinfo='enable console output'/>
</ProtoInterface>
<ProtoBody>
<Group DEF='ProtoBodyGroup'>
<!-- ROUTE information for Trigger node:  [from TouchToggle.toggle to enabled ] [from cycleTime to SequencerScript.triggerNext ] -->
<TimeSensor DEF='Triggerloop='true'>
<IS>
<connect nodeField='enabledprotoField='enabled'/>
<connect nodeField='cycleIntervalprotoField='interval'/>
</IS>
</TimeSensor>
<TimeSensor DEF='TraceHolder'>
<IS>
<connect nodeField='enabledprotoField='traceEnabled'/>
</IS>
</TimeSensor>
<!-- ROUTE information for SequencerScript node:  [from Trigger.cycleTime to triggerNext ] [from TouchToggle.toggle to set_enabled ] -->
<Script DEF='SequencerScriptdirectOutput='true'>
<field name='viewpointstype='MFNodeaccessType='initializeOnly'/>
<field name='set_enabledtype='SFBoolaccessType='inputOnly'
 appinfo='whether ViewpointSequencer is enabled or not'/>

<field name='TriggerNodetype='SFNodeaccessType='initializeOnly'>
<TimeSensor USE='Trigger'/>
</field>
<field name='TraceHolderNodetype='SFNodeaccessType='initializeOnly'>
<TimeSensor USE='TraceHolder'/>
</field>
<field name='triggerNexttype='SFTimeaccessType='inputOnly'/>
<field name='previoustype='SFBoolaccessType='inputOnly'/>
<field name='nexttype='SFBoolaccessType='inputOnly'/>
<!-- local Script variables needing persistent values -->
<field name='indextype='SFInt32value='0accessType='initializeOnly'/>
<field name='viewpointCounttype='SFInt32value='0accessType='initializeOnly'/>
<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'/>
<IS>
<connect nodeField='viewpointsprotoField='viewpoints'/>
<connect nodeField='previousprotoField='previous'/>
<connect nodeField='nextprotoField='next'/>
<connect nodeField='set_enabledprotoField='set_enabled'/>
</IS>
<![CDATA[
            
ecmascript:

function initialize ()
{
	index = 0;
	viewpointCount = viewpoints.length;
	traceEnabled = TraceHolderNode.loop;

	tracePrint ('initialize: viewpoints.length=' + viewpointCount);
	tracePrint ('initialize: Viewpoint [' + index + '] ' + viewpoints[index].description);

	if (TriggerNode.enabled=='false') return;
	if (viewpointCount > 0) viewpoints[index].set_bind = true;
}

function set_enabled (newValue, timeStamp)
{
	enabled = newValue;
	tracePrint ('enabled=' + newValue);
        if ((newValue == true) && (viewpoints.length >= 1))
            viewpoints[0].bind = true;
}

function triggerNext(triggerTime, timeStamp)
{
	if ((TriggerNode.enabled=='false') || (viewpointCount==0)) return;
	if (index < viewpointCount - 1)
		index++;
	else	index = 0;
	if (viewpointCount > 1) viewpoints[index].set_bind = true;
	tracePrint ('triggerNext: Viewpoint [' + index + '] ' + viewpoints[index].description);
}

function previous (value, timeStamp)
{
  if ((TriggerNode.enabled=='false') || (viewpointCount==0)) return;
  if (value==true) // trigger on true events only
  {
	if (index > 0)
		index--;
	else	index = viewpointCount - 1;
	if (viewpointCount > 1) viewpoints[index].set_bind = true;
	tracePrint ('previous: Viewpoint [' + index + '] ' + viewpoints[index].description);
  }
}
function next (value, timeStamp)
{
  if ((TriggerNode.enabled=='false') || (viewpointCount==0)) return;
  if (value==true) // trigger on true events only
  {
	if (index < viewpointCount - 1)
		index++;
	else	index = 0;
	if (viewpointCount > 1) viewpoints[index].set_bind = true;
	tracePrint ('next: Viewpoint [' + index + '] ' + viewpoints[index].description);
  }
}

function tracePrint(outputString)
{
	if (traceEnabled) Browser.print ('[ViewpointSequencer] ' + outputString + '\n');
}

function alwaysPrint(outputString)
{
	Browser.print ('[ViewpointSequencer] ' + outputString + '\n');
}

          
]]>
</Script>
<ROUTE fromNode='TriggerfromField='cycleTimetoNode='SequencerScripttoField='triggerNext'/>
<Group DEF='TouchTextGroup'>
<!-- ROUTE information for TouchTextSensor node:  [from isActive to TouchToggle.set_boolean ] -->
<TouchSensor DEF='TouchTextSensordescription='Click text to toggle ViewpointSequencer'/>
<Billboard axisOfRotation='0 0 0'>
<Shape>
<Text>
<IS>
<connect nodeField='stringprotoField='toggleMessage'/>
</IS>
<FontStyle justify='"MIDDLE" "MIDDLE"'>
<IS>
<connect nodeField='sizeprotoField='toggleMessageFontSize'/>
</IS>
</FontStyle>
</Text>
<Appearance>
<Material>
<IS>
<connect nodeField='diffuseColorprotoField='toggleMessageColor'/>
</IS>
</Material>
</Appearance>
</Shape>
<!-- An invisible box behind the string helps to toggle the ViewpointSequencer -->
<Shape>
<Box size='7.8 2 0.1'/>
<Appearance>
<Material diffuseColor='1 1 1transparency='1'/>
</Appearance>
</Shape>
</Billboard>
<!-- ROUTE information for TouchToggle node:  [from TouchTextSensor.isActive to set_boolean ] [from toggle to SequencerScript.set_enabled ] [from toggle to Trigger.enabled ] -->
<BooleanToggle DEF='TouchTogglecontainerField='children'/>
<ROUTE fromNode='TouchTextSensorfromField='isActivetoNode='TouchToggletoField='set_boolean'/>
<!-- TouchToggle toggle_changed should likely revert to TouchToggle toggle when inputOutput fields supported in Script, or native implementation provided. -->
<ROUTE fromNode='TouchTogglefromField='toggletoNode='SequencerScripttoField='set_enabled'/>
<ROUTE fromNode='TouchTogglefromField='toggletoNode='TriggertoField='enabled'/>
</Group>
</Group>
</ProtoBody>
</ProtoDeclare>
<!-- ===============Example============== -->
<Anchor description='select to view ViewpointSequencer exampleparameter='"target=_blank"'
  url=' "ViewpointSequencerExample.x3d" "https://savage.nps.edu/Savage/Tools/Animation/ViewpointSequencerExample.x3d" "ViewpointSequencerExample.wrl" "https://savage.nps.edu/Savage/Tools/Animation/ViewpointSequencerExample.wrl" '>
<Shape>
<Text string='"ViewpointSequencerPrototype" "defines a prototype" "" "Click text to see example scene" "ViewpointTourExample"'>
<FontStyle justify='"MIDDLE" "MIDDLE"size='0.9'/>
</Text>
<Appearance>
<Material diffuseColor='1 1 0.2'/>
</Appearance>
</Shape>
<Shape>
<!-- transparent Box to make text more selectable -->
<Box size='11 5 0.1'/>
<Appearance>
<Material diffuseColor='1 1 1transparency='1'/>
</Appearance>
</Shape>
</Anchor>
</Scene>
</X3D>
<!--

Index for ProtoDeclare definition : ViewpointSequencer

Index for DEF nodes : ProtoBodyGroup, SequencerScript, TouchTextGroup, TouchTextSensor, TouchToggle, TraceHolder, Trigger
-->

<!-- Color key: <X3dNode DEF='idName' field='value'/> matches <XmlElement DEF='idName' attribute='value'/>
(Light blue background: behavior node) (Grey background: inserted documentation) (Magenta background: X3D Extensibility)
    <Prototype name='ProtoName'> <field name='fieldName'/> </Prototype> -->

<!-- For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources and X3D Scene Authoring Hints. -->