<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "http://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile='Immersive' version='3.3 xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation =' http://www.web3d.org/specifications/x3d-3.3.xsd '>
<head>
<meta name='titlecontent='FlyingTextPrototype.x3d'/>
<meta name='descriptioncontent='Prototype definition for a flying text message. Waypoints, time intervals, cycleInterval and text message can be overridden.'/>
<meta name='creatorcontent='Murat Onder and Don Brutzman'/>
<meta name='createdcontent='2 June 2004'/>
<meta name='modifiedcontent='9 July 2018'/>
<meta name='referencecontent='FlyingTextExample.x3d'/>
<meta name='identifiercontent=' https://savage.nps.edu/Savage/Tools/Animation/FlyingTextPrototype.x3d '/>
<meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../../license.html'/>
</head>
<!-- -->
<Scene>
<ProtoDeclare name='FlyingTextappinfo='Visualize message transfer between two points as flying text'>
<ProtoInterface>
<field name='waypointstype='MFVec3fvalue='0 0 0 0 1 0accessType='initializeOnly'/>
<field name='set_waypointstype='MFVec3faccessType='inputOnly'/>
<field name='timeIntervalstype='MFTimevalue='1accessType='initializeOnly'/>
<field name='set_timeIntervalstype='MFTimeaccessType='inputOnly'/>
<field name='textMessagetype='MFStringvalue='"default"accessType='initializeOnly'/>
<field name='set_textMessagetype='MFStringaccessType='inputOnly'/>
<field name='visibletype='SFBoolvalue='trueaccessType='initializeOnly'/>
<field name='set_visibletype='SFBoolaccessType='inputOnly'/>
<field name='looptype='SFBoolvalue='falseaccessType='initializeOnly'/>
<field name='axisOfRotationtype='SFVec3fvalue='0 0 0accessType='initializeOnly'/>
<field name='timeSensorEnabledtype='SFBoolvalue='trueaccessType='initializeOnly'/>
<field name='startTimetype='SFTimevalue='0accessType='inputOutput'/>
<field name='set_startTimetype='SFTimeaccessType='inputOnly'/>
<field name='stopTimetype='SFTimevalue='0accessType='inputOutput'/>
<field name='set_stopTimetype='SFTimeaccessType='inputOnly'/>
<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'/>
<field name='textDiffuseColortype='SFColorvalue='.2 .2 .4accessType='inputOutput'/>
<field name='fontStyletype='SFNodeaccessType='inputOutput'>
<FontStyle justify='"MIDDLE" "MIDDLE"'/>
</field>
</ProtoInterface>
<ProtoBody>
<Group>
<Billboard>
<IS>
<connect nodeField='axisOfRotationprotoField='axisOfRotation'/>
</IS>
<!-- ROUTE information for TextMessageTransform node:  [from TextAnimator.value_changed to set_translation ] -->
<Transform DEF='TextMessageTransform'>
<!-- ROUTE information for TextVisibilitySwitch node:  [from HideTextTrigger.triggerValue to whichChoice ] [from RevealTextTrigger.triggerValue to whichChoice ] -->
<Switch DEF='TextVisibilitySwitchwhichChoice='-1'>
<Shape>
<Text DEF='TextMessage'>
<IS>
<connect nodeField='fontStyleprotoField='fontStyle'/>
</IS>
</Text>
<Appearance>
<Material>
<IS>
<connect nodeField='diffuseColorprotoField='textDiffuseColor'/>
</IS>
</Material>
</Appearance>
</Shape>
<!-- ROUTE information for Toucher node:  [from touchTime to Clock.set_startTime ] -->
<TouchSensor DEF='Toucherdescription='Touch to fly the text'/>
</Switch>
</Transform>
<Group DEF='TextAnimationGroup'>
<!-- ROUTE information for Clock node:  [from Toucher.touchTime to set_startTime ] [from fraction_changed to TextAnimator.set_fraction ] -->
<TimeSensor DEF='Clock'>
<IS>
<connect nodeField='loopprotoField='loop'/>
<connect nodeField='enabledprotoField='timeSensorEnabled'/>
<connect nodeField='startTimeprotoField='startTime'/>
<connect nodeField='set_startTimeprotoField='set_startTime'/>
<connect nodeField='stopTimeprotoField='stopTime'/>
<connect nodeField='set_stopTimeprotoField='set_stopTime'/>
</IS>
</TimeSensor>
<ROUTE fromNode='ToucherfromField='touchTimetoNode='ClocktoField='set_startTime'/>
<!-- ROUTE information for TextAnimator node:  [from Clock.fraction_changed to set_fraction ] [from value_changed to TextMessageTransform.set_translation ] -->
<PositionInterpolator DEF='TextAnimator'/>
<ROUTE fromNode='ClockfromField='fraction_changedtoNode='TextAnimatortoField='set_fraction'/>
<ROUTE fromNode='TextAnimatorfromField='value_changedtoNode='TextMessageTransformtoField='set_translation'/>
</Group>
</Billboard>
<!-- ROUTE information for AnimationScript node:  [from hideText to HideTextTrigger.set_boolean ] [from revealText to RevealTextTrigger.set_boolean ] -->
<Script DEF='AnimationScriptdirectOutput='true'>
<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'/>
<field name='interpolatorNodetype='SFNodeaccessType='initializeOnly'>
<PositionInterpolator USE='TextAnimator'/>
</field>
<field name='textNodetype='SFNodeaccessType='initializeOnly'>
<Text USE='TextMessage'/>
</field>
<field name='timeSensorNodetype='SFNodeaccessType='initializeOnly'>
<TimeSensor USE='Clock'/>
</field>
<field name='waypointstype='MFVec3faccessType='initializeOnly'/>
<field name='set_waypointstype='MFVec3faccessType='inputOnly'/>
<field name='timeIntervalstype='MFTimeaccessType='initializeOnly'/>
<field name='set_timeIntervalstype='MFTimeaccessType='inputOnly'/>
<field name='textMessagetype='MFStringaccessType='initializeOnly'/>
<field name='set_textMessagetype='MFStringaccessType='inputOnly'/>
<field name='visibletype='SFBoolaccessType='initializeOnly'/>
<field name='set_visibletype='SFBoolaccessType='inputOnly'/>
<field name='hideTexttype='SFBoolaccessType='outputOnly'/>
<field name='revealTexttype='SFBoolaccessType='outputOnly'/>
<field name='set_startTimetype='SFTimeaccessType='inputOnly'/>
<field name='totalDurationtype='SFTimevalue='0accessType='initializeOnly'/>
<IS>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
<connect nodeField='waypointsprotoField='waypoints'/>
<connect nodeField='set_waypointsprotoField='set_waypoints'/>
<connect nodeField='timeIntervalsprotoField='timeIntervals'/>
<connect nodeField='set_timeIntervalsprotoField='set_timeIntervals'/>
<connect nodeField='textMessageprotoField='textMessage'/>
<connect nodeField='set_textMessageprotoField='set_textMessage'/>
<connect nodeField='visibleprotoField='visible'/>
<connect nodeField='set_visibleprotoField='set_visible'/>
<connect nodeField='set_startTimeprotoField='set_startTime'/>
</IS>
<![CDATA[
            
ecmascript:

function initialize()
{
   if ((waypoints.length - timeIntervals.length) == 1 )
   {
     set_textMessage(textMessage);
     set_timeIntervals(timeIntervals);
     set_waypoints(waypoints);
   }
   else
   {
     alwaysPrint('timeIntervals.length=' + timeIntervals.length + ' should be one less '
                + 'than waypoints.length=' + waypoints.length);
     alwaysPrint ('timeIntervals=' + timeIntervals);
     alwaysPrint ('waypoints    =' + waypoints);
   }
   if (visible) revealText = true;
   else           hideText = true;
   tracePrint ('visible = ' + visible);
}
function set_textMessage(text)
{
   textNode.string = text;
   tracePrint ('textNode.string = ' + textNode.string);
}
function set_waypoints(waypointsArray)
{
   interpolatorNode.keyValue = waypointsArray;
   tracePrint ('interpolatorNode.keyValue = ' + interpolatorNode.keyValue);
}
function set_timeIntervals(intervals)
{
   tracePrint ('set_timeIntervals(' + timeIntervals + ')');
   totalDuration = 0;
   for(i = 0; i < timeIntervals.length; i++)
   {
      totalDuration = totalDuration + timeIntervals[i];
   }
   tracePrint ('totalDuration = ' + totalDuration);
   timeSensorNode.cycleInterval = totalDuration;

   interpolatorNode.key[0] = 0.0;
   for (j = 0; j < timeIntervals.length; j++)
   {
      interpolatorNode.key[j+1] = interpolatorNode.key[j] + timeIntervals[j]/totalDuration;
      tracePrint ('interpolatorNode.key[j] = ' + interpolatorNode.key[j]);
   }
   tracePrint ('interpolatorNode.key = ' + interpolatorNode.key);
}
function set_visible (value, timestamp)
{
	visible = value;
	if (visible) revealText = true;
	else           hideText = true;
	tracePrint ('visible = ' + visible);
}
function set_startTime (value, timestamp)
{
	tracePrint ('set_startTime = ' + value);
	set_visible (true);  // ensure visible when activated
	initialize ();       // ensure all computations up to date
}
function tracePrint(value)
{
   if (traceEnabled) alwaysPrint(value);
}
function alwaysPrint(value)
{
      if (textMessage.length > 1)
	       Browser.print ('[FlyingText ' + textMessage + '] ' + value + '\n');
      else Browser.print ('[FlyingText] ' + value + '\n');
}

          
]]>
</Script>
<Group DEF='TextVisibilityGroup'>
<!-- ROUTE information for HideTextTrigger node:  [from AnimationScript.hideText to set_boolean ] [from triggerValue to TextVisibilitySwitch.whichChoice ] -->
<IntegerTrigger DEF='HideTextTrigger'/>
<ROUTE fromNode='AnimationScriptfromField='hideTexttoNode='HideTextTriggertoField='set_boolean'/>
<ROUTE fromNode='HideTextTriggerfromField='triggerValuetoNode='TextVisibilitySwitchtoField='whichChoice'/>
<!-- ROUTE information for RevealTextTrigger node:  [from AnimationScript.revealText to set_boolean ] [from triggerValue to TextVisibilitySwitch.whichChoice ] -->
<IntegerTrigger DEF='RevealTextTriggerintegerKey='0'/>
<ROUTE fromNode='AnimationScriptfromField='revealTexttoNode='RevealTextTriggertoField='set_boolean'/>
<ROUTE fromNode='RevealTextTriggerfromField='triggerValuetoNode='TextVisibilitySwitchtoField='whichChoice'/>
</Group>
</Group>
</ProtoBody>
</ProtoDeclare>
<!-- ============================ -->
<Anchor description='FlyingText Exampleparameter='"target=_blank"'
  url=' "../../../Savage/Tools/Animation/FlyingTextExample.x3d" "https://savage.nps.edu/Savage/Tools/Animation/FlyingTextExample.x3d" "../../../Savage/Tools/Animation/FlyingTextExample.wrl" "https://savage.nps.edu/Savage/Tools/Animation/FlyingTextExample.wrl" '>
<Shape>
<Text string='"FlyingTextPrototype" "defines a prototype" "" "Click text to see example scene" "" "(Text has Billboard style)"'>
<FontStyle justify='"MIDDLE" "MIDDLE"size='0.7'/>
</Text>
<Appearance>
<Material diffuseColor='.8 .7 0.2'/>
</Appearance>
</Shape>
</Anchor>
</Scene>
</X3D>
<!--

Index for ProtoDeclare definition : FlyingText

Index for DEF nodes : AnimationScript, Clock, HideTextTrigger, RevealTextTrigger, TextAnimationGroup, TextAnimator, TextMessage, TextMessageTransform, TextVisibilityGroup, TextVisibilitySwitch, Toucher
-->

<!-- 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> -->

<!-- Additional help information about X3D scenes: X3D Resources, X3D Scene Authoring Hints and X3D Tooltips -->