X3D Model Documentation: BooleanSequencerPrototype.x3d

  1  <?xml version="1.0" encoding="UTF-8"?>
  2 
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
  3  <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'>
  4       <head>
  5            <meta name='titlecontent='BooleanSequencerPrototype.x3d'/>
  6            <meta name='descriptioncontent='BooleanSequencer is modeled after ScalarInterpolator and generates true or false values.'/>
  7            <meta name='creatorcontent='Don Brutzman, Estuko Lippi, Jeff Weekley, Jane Wu'/>
  8            <meta name='createdcontent='7 August 2001'/>
  9            <meta name='modifiedcontent='20 January 2020'/>
 10            <meta name='referencecontent='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#ScalarInterpolator'/>
 11            <meta name='subjectcontent='boolean sequencer'/>
 12            <meta name='identifiercontent='https://www.web3d.org/x3d/content/examples/Basic/development/BooleanSequencerPrototype.x3d'/>
 13            <meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
 14            <meta name='licensecontent='../license.html'/>
 15       </head>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->

<!-- to top Index for DEF nodes: KeyHolder, KeyValueHolder, SequencerScript

Index for ProtoDeclare definition: BooleanSequencer
-->
 16       <Scene>
 17            <WorldInfo title='BooleanSequencerPrototype.x3d'/>
 18            <ProtoDeclare name='BooleanSequencer'>
 19                 <ProtoInterface>
 20                      <field name='set_fractiontype='SFFloataccessType='inputOnly'
                     appinfo='Regular interpolator-style input, typical range [0..1]'/>
 21                      <field name='set_keytype='MFFloataccessType='inputOnly'/>
 22                      <field name='keytype='MFFloataccessType='inputOutput'
                     appinfo='Array sequentially increasing typically [0..1]. Must have the same number of keys as keyValues.'>
 23                           <!-- NULL initialization value -->
 24                      </field>
 25                      <field name='key_changedtype='MFFloataccessType='outputOnly'/>
 26                      <field name='set_keyValuetype='MFBoolaccessType='inputOnly'/>
 27                      <field name='keyValuetype='MFBoolaccessType='inputOutput'
                     appinfo='Array of true|false values. Must have the same number of keys as keyValues.'>
 28                           <!-- NULL initialization value -->
 29                      </field>
 30                      <field name='keyValue_changedtype='MFBoolaccessType='outputOnly'
                     appinfo='Regular interpolator-style input'/>
 31                      <field name='value_changedtype='SFBoolaccessType='outputOnly'
                     appinfo='Regular interpolator-style input'/>
 32                      <field name='previoustype='SFBoolaccessType='inputOnly'
                     appinfo='Utility method'/>
 33                      <field name='nexttype='SFBoolaccessType='inputOnly'
                     appinfo='Utility method'/>
 34                 </ProtoInterface>
 35                 <ProtoBody>
 36                      <Group>
 37 
                         <!-- ScalarInterpolator KeyHolder is a DEF node that has 1 USE node: USE_1 -->
                         <ScalarInterpolator DEF='KeyHolder'>
 38                                <IS>
 39                                     <connect nodeField='keyprotoField='key'/>
 40                                </IS>
 41                           </ScalarInterpolator>
 42 
                         <!-- Anchor KeyValueHolder is a DEF node that has 1 USE node: USE_1 -->
                         <Anchor DEF='KeyValueHolder'>
 43                                <IS>
 44                                     <connect nodeField='descriptionprotoField='keyValue'/>
 45                                </IS>
 46                           </Anchor>
 47                           <Script DEF='SequencerScriptdirectOutput='true'>
 48                                <!-- Regular interpolator-style input -->
 49                                <field name='set_fractiontype='SFFloataccessType='inputOnly'
                               appinfo='typical range [0..1]'/>
 50                                <field name='set_keytype='MFFloataccessType='inputOnly'
                               appinfo='Array sequentially increasing typically [0..1]. Must have the same number of keys as keyValues.'/>
 51                                <field name='keyHolderNodetype='SFNodeaccessType='initializeOnly'>
 52                                     <ScalarInterpolator USE='KeyHolder'/>
 53                                </field>
 54                                <field name='key_changedtype='MFFloataccessType='outputOnly'/>
 55                                <field name='set_keyValuetype='MFBoolaccessType='inputOnly'
                               appinfo='Array of true or false values. Must have the same number of keys as keyValues.'/>
 56                                <field name='keyValueHolderNodetype='SFNodeaccessType='initializeOnly'>
 57                                     <Anchor USE='KeyValueHolder'/>
 58                                </field>
 59                                <field name='keyValue_changedtype='MFBoolaccessType='outputOnly'/>
 60                                <!-- Regular interpolator-style output -->
 61                                <field name='value_changedtype='SFBoolaccessType='outputOnly'/>
 62                                <!-- Utility methods -->
 63                                <field name='previoustype='SFBoolaccessType='inputOnly'/>
 64                                <field name='nexttype='SFBoolaccessType='inputOnly'/>
 65                                <!-- Script-specific interfaces, not needed for node definition -->
 66                                <field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'/>
 67                                <field name='keyValueArraytype='MFInt32accessType='initializeOnly'>
 68                                     <!-- NULL initialization value -->
 69                                </field>
 70                                <field name='previousFractiontype='SFFloatvalue='0.0accessType='initializeOnly'/>
 71                                <field name='nextIndextype='SFInt32value='0accessType='initializeOnly'/>
 72                                <field name='validtype='SFBoolvalue='trueaccessType='outputOnly'/>
 73                                <field name='recheckValiditytype='SFBoolvalue='falseaccessType='initializeOnly'/>
 74                                <field name='forwardtype='SFBoolvalue='trueaccessType='initializeOnly'
                               appinfo='leftToRight'/>
 75                                <field name='keytype='MFFloataccessType='inputOnly'>
 76                                     <!-- NULL initialization value -->
 77                                </field>
 78                                <field name='keyValuetype='MFInt32accessType='inputOutput'>
 79                                     <!-- NULL initialization value -->
 80                                </field>
 81                                <IS>
 82                                     <connect nodeField='set_fractionprotoField='set_fraction'/>
 83                                     <connect nodeField='set_keyprotoField='set_key'/>
 84                                     <connect nodeField='key_changedprotoField='key_changed'/>
 85                                     <connect nodeField='set_keyValueprotoField='set_keyValue'/>
 86                                     <connect nodeField='keyValue_changedprotoField='keyValue_changed'/>
 87                                     <connect nodeField='value_changedprotoField='value_changed'/>
 88                                     <connect nodeField='previousprotoField='previous'/>
 89                                     <connect nodeField='nextprotoField='next'/>
 90                                </IS>
  <![CDATA[
            
ecmascript:

var key, keyValue;

function initialize()
{
	key      = keyHolderNode.key;
	keyValue = keyValueHolderNode.description;
	tracePrint('key =' + key);
	tracePrint('keyValue =' + keyValue);
	keyValueToKeyValueArray ();
	tracePrint('keyValueArray =' + keyValueArray);

	forward = true;
	tracePrint('Initializing a new BooleanSequencer.  key.length=' + key.length + '; keyValueArray.length=' + keyValueArray.length);
	validityCheck();
}

function keyValueToKeyValueArray ()
{
	tracePrint('keyValueToKeyValueArray starting');
	index = 0;
	complete = false;
	nextString = keyValue.toLowerCase();
	tracePrint('initial nextString=' + nextString);
	tokenCount=0;
	while ((complete != true) && (nextString.length > 0))
	{
		tracePrint('nextString=' + nextString);
		while ((nextString.substring(0,1) == ' ') || (nextString.substring(0,1) == ','))
		       nextString = nextString.slice(1);
		tracePrint('deblanked nextString=' + nextString);
		if (nextString.length == 0)
		{
			tracePrint ('nextString.length == 0');
			complete = true;
		}
		if (nextString.length < 4)
		{
			alwaysPrint ('*** illegal keyValue input=' + nextString);
			valid = false;
			complete = true;
		}
		else if (nextString.substring(0,4) =='true')
		{
			keyValueArray[keyValueArray.length] = 1; // append
			newString = nextString.slice(4);
			nextString = newString;
			tokenCount++;
			tracePrint('found true, nextString=' + nextString + ', tokenCount=' + tokenCount);
		}
		else if (nextString.length < 5)
		{
			alwaysPrint ('*** illegal keyValue input=' + nextString);
			valid = false;
			complete = true;
		}
		else if (nextString.substring(0,5) =='false')
		{
			keyValueArray[keyValueArray.length] = 0; // append
			newString = nextString.slice(5);
			nextString = newString;
			tokenCount++;
			tracePrint('found false, nextString=' + nextString + ', tokenCount=' + tokenCount);
		}
		tracePrint('  intermediate keyValueArray=' + keyValueArray);
	}
	tracePrint('keyValueToKeyValueArray complete');
}

function set_fraction(value, timeStamp)
{
	if (recheckValidity) validityCheck();

	if (!valid) return; //BooleanSequencer ignored

	tracePrint('fraction =' + value);
	//Bounds checking
	if (value < 0)
	{
		alwaysPrint('*** warning: fraction is less than 0.  fraction reset to 0 ***');
		value = 0;
	}
	else if (value > 1)
	{
		alwaysPrint('*** warning: fraction is greater than 1.  fraction reset to 1 ***');
		value = 1;
	}

	//Check animation direction
	if (value < previousFraction && forward == true)
	{
		forward = false;
		nextIndex = nextIndex - 1;
		tracePrint('Animate backward');
	}
	else if (value > previousFraction && forward == false)
	{
		forward = true;
		//nextIndex = 0;
		tracePrint('Animate forward');
	}

	previousFraction = value;

	if (forward == true)
	{
		for (i = nextIndex; i < key.length; i++)
		{
			if (value < key[i])
				return;

			nextIndex = i + 1;
			tracePrint('nextIndex =' + nextIndex);
			if (nextIndex < key.length)
			{
				if (value <= key[nextIndex])
				{
					//Fire event
					if (keyValueArray[nextIndex-1] == 0)
						value_changed = false;
					else
						value_changed = true;
					tracePrint('value_changed eventOut is:' + value_changed);
				}
			}
			else if (nextIndex == key.length)
			{
				//Fire event
				if (keyValueArray[nextIndex-1] == 0)
					value_changed = false;
				else
					value_changed = true;
				tracePrint('value_changed eventOut is:' + value_changed);
			}
			else //nextIndex > key.length
			{
				//nextIndex = 0;
				break;
			}
		}
	}
	else //backward
	{
		for (i = nextIndex; i > 0; i--)
		{
			if (value >= key[i])
				return;

			nextIndex = i - 1;
			tracePrint('nextIndex =' + nextIndex);
			if (nextIndex >= 0)
			{
				if (value >= key[nextIndex])
				{
					//Fire event
					if (keyValueArray[nextIndex] == 0)
						value_changed = false;
					else
						value_changed = true;
					tracePrint('value_changed eventOut is:' + value_changed);
				}
			}
			else //nextIndex < 0
			{
				//nextIndex = key.length;
				break;
			}
		}
	}
}

function set_key(value, timeStamp)
{
	key = value;
	keyHolderNode.key  = key;
	recheckValidity = true;
}

function set_keyValue(value, timeStamp)
{
	keyValue = value;
	keyValueHolderNode.description = keyValue;
	recheckValidity = true;
	keyValueToKeyValueArray ();
	keyValue_changed = keyValue;
}

function validityCheck()
{
	//Check if key & keyValueArray array length matches
	if (key.length != keyValueArray.length)
	{
		alwaysPrint('*** error: key and keyValue arrays must be of the same length.  BooleanSequencer ignored ***');
		valid = false;
		return;
	}

	//Check if key array has values in the range of [0..1] in an increasing order
	if (key[0] < 0 || key[0] > 1)
	{
		alwaysPrint('*** error: key[0] value is NOT in the range of [0..1].  BooleanSequencer ignored ***');
		valid = false;
		return;
	}
	for (i = 1; i < key.length; i++)
	{
		if (key[i] < 0 || key[i] > 1)
		{
			alwaysPrint('*** error: key[' + i + '] value is NOT in the range of [0..1].  BooleanSequencer ignored ***');
			valid = false;
			return;
		}

		if (key[i] <= key [i-1])
		{
			alwaysPrint('*** error: values for key[] array must be listed in an increasing order.  BooleanSequencer ignored ***');
			valid = false;
			return;
		}
	}
	recheckValidity = false;
	key_changed = key;
	return;
}
function previous (SFBoolValue, timestamp)
{
	nextIndex = nextIndex - 1;
	if (nextIndex == 0) nextIndex = key.length - 1;
}
function next (SFBoolValue, timestamp)
{
	nextIndex = nextIndex + 1;
	if (nextIndex == key.length) nextIndex = 0;
}

function tracePrint(outputString)
{
	if (traceEnabled) Browser.println ('[ BooleanSequencer ]' + outputString);
}

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

          
]]>
 92                           </Script>
 93                      </Group>
 94                 </ProtoBody>
 95            </ProtoDeclare>
 96            <!-- ===============Example============== -->
 97            <Anchor description='BooleanSequencerExampleparameter='"target=_blank"'   url=' "BooleanSequencerExample.x3d" "https://www.web3d.org/x3d/content/examples/Basic/development/BooleanSequencerExample.x3d" "BooleanSequencerExample.wrl" "https://www.web3d.org/x3d/content/examples/Basic/development/BooleanSequencerExample.wrl" '>
 98                 <Shape>
 99                      <Text string='"BooleanSequencerPrototype" "defines a prototype" "" "Click on this text to see" "BooleanSequencerExample" " scene"'>
100                           <FontStyle justify='"MIDDLE" "MIDDLE"'/>
101                      </Text>
102                      <Appearance>
103                           <Material diffuseColor='1 1 0.2'/>
104                      </Appearance>
105                 </Shape>
106            </Anchor>
107       </Scene>
108  </X3D>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->

<!-- to top Index for DEF nodes: KeyHolder, KeyValueHolder, SequencerScript

Index for ProtoDeclare definition: BooleanSequencer
-->
X3D Tooltips element index: Anchor, Appearance, connect, field, FontStyle, Group, head, IS, Material, meta, ProtoBody, ProtoDeclare, ProtoInterface, ScalarInterpolator, Scene, Script, Shape, Text, WorldInfo, X3D, accessType and type, XML data types, field types

-->
<!-- Online at
https://www.web3d.org/x3d/content/examples/Basic/development/BooleanSequencerPrototypeIndex.html -->
<!-- Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/development/BooleanSequencerPrototype.x3d -->

<!-- Color legend: X3D terminology <X3dNode  DEF='idNamefield='value'/> matches XML terminology <XmlElement  DEF='idNameattribute='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. -->