<?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='3 February 2024'/>
<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='identifiercontent=' https://www.web3d.org/x3d/content/examples/X3dForAdvancedModeling/Animation/ViewpointSequencerPrototype.x3d '/>
<meta name='generatorcontent='X3D-Edit 4.0, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../../license.html'/>
</head>
<!--

to top <!-- Event Graph ROUTE Table shows event connections -->
 
<!-- Index for DEF nodes: ProtoBodyGroup, SequencerScript, TouchTextGroup, TouchTextSensor, TouchToggle, TraceHolder, Trigger

Index for ProtoDeclare definition: ViewpointSequencer
-->
<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>
<!-- this node and field is used to hold value of ProtoInterface field -->
<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.println ('[ViewpointSequencer] ' + outputString);
}

function alwaysPrint(outputString)
{
	Browser.println ('[ViewpointSequencer] ' + outputString);
}

          
]]>
</Script>
< ROUTE  fromNode=' Trigger' fromField='cycleTime' toNode=' SequencerScript' toField='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=' TouchTextSensor' fromField='isActive' toNode=' TouchToggle' toField='set_boolean'/>
<!-- TouchToggle toggle_changed should likely revert to TouchToggle toggle when inputOutput fields supported in Script, or native implementation provided. -->
< ROUTE  fromNode=' TouchToggle' fromField='toggle' toNode=' SequencerScript' toField='set_enabled'/>
< ROUTE  fromNode=' TouchToggle' fromField='toggle' toNode=' Trigger' toField='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>
<!--

to top <!-- Event Graph ROUTE Table shows event connections -->
 
<!-- Index for DEF nodes: ProtoBodyGroup, SequencerScript, TouchTextGroup, TouchTextSensor, TouchToggle, TraceHolder, Trigger

Index for ProtoDeclare definition: ViewpointSequencer
-->

Event Graph ROUTE Table entries with 4 ROUTE connections total, showing X3D event-model relationships for this scene.

Each row shows an event cascade that may occur during a single timestamp interval between frame renderings, as part of the X3D execution model.

TouchTextSensor
TouchSensor
isActive
SFBool

ROUTE
event to
(1)
TouchToggle
BooleanToggle
set_boolean
SFBool

 
 
then
TouchToggle
BooleanToggle
toggle
SFBool

ROUTE
event to
(2)
SequencerScript
Script
set_enabled
SFBool
 
 
 
then
TouchToggle
BooleanToggle
toggle
SFBool

ROUTE
event to
(2)
Trigger
TimeSensor
enabled
SFBool

 
 
then
Trigger
TimeSensor
cycleTime
SFTime

ROUTE
event to
(3)
SequencerScript
Script
triggerNext
SFTime


Trigger
TimeSensor
cycleTime
SFTime

ROUTE
event to
(1)
SequencerScript
Script
triggerNext
SFTime


      SequencerScript
Script
No ROUTE connection found for output from this node.
Contains SFNode field with indirect access to another node. 


-->

<!-- Online at
https://www.web3d.org/x3d/content/examples/X3dForAdvancedModeling/Animation/ViewpointSequencerPrototypeIndex.html -->
<!-- Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/X3dForAdvancedModeling/Animation/ViewpointSequencerPrototype.x3d -->

<!-- Color legend: X3D terminology <X3dNode DEF='idName' field='value'/> matches XML terminology <XmlElement DEF='idName' attribute='value'/>
(Light-blue background: event-based behavior node or statement) (Grey background inside box: inserted documentation) (Magenta background: X3D Extensibility)
    <ProtoDeclare name='ProtoName'> <field name='fieldName'/> </ProtoDeclare> -->

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