| 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='title' content=' BooleanSequencerPrototype.x3d '/> |
| 6 | <meta name='description' content='BooleanSequencer is modeled after ScalarInterpolator and generates true or false values.'/> |
| 7 | <meta name='creator' content='Don Brutzman, Estuko Lippi, Jeff Weekley, Jane Wu'/> |
| 8 | <meta name='created' content='7 August 2001'/> |
| 9 | <meta name='modified' content='20 January 2020'/> |
| 10 | <meta name='reference' content='https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#ScalarInterpolator'/> |
| 11 | <meta name='subject' content='boolean sequencer'/> |
| 12 | <meta name='identifier' content=' https://www.web3d.org/x3d/content/examples/Basic/development/BooleanSequencerPrototype.x3d '/> |
| 13 | <meta name='generator' content='X3D-Edit 3.3, https://www.web3d.org/x3d/tools/X3D-Edit'/> |
| 14 | <meta name='license' content='../license.html'/> |
| 15 | </head> |
| 16 | <Scene> |
| 17 | <WorldInfo title='BooleanSequencerPrototype.x3d'/> |
| 18 | <ProtoDeclare name='BooleanSequencer'> |
| 19 | <ProtoInterface> |
| 20 |
<field name='set_fraction' type='SFFloat' accessType='inputOnly'
appinfo='Regular interpolator-style input, typical range [0..1]'/> |
| 21 | <field name='set_key' type='MFFloat' accessType='inputOnly'/> |
| 22 |
<field name='key' type='MFFloat' accessType='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_changed' type='MFFloat' accessType='outputOnly'/> |
| 26 | <field name='set_keyValue' type='MFBool' accessType='inputOnly'/> |
| 27 |
<field name='keyValue' type='MFBool' accessType='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_changed' type='MFBool' accessType='outputOnly'
appinfo='Regular interpolator-style input'/> |
| 31 |
<field name='value_changed' type='SFBool' accessType='outputOnly'
appinfo='Regular interpolator-style input'/> |
| 32 |
<field name='previous' type='SFBool' accessType='inputOnly'
appinfo='Utility method'/> |
| 33 |
<field name='next' type='SFBool' accessType='inputOnly'
appinfo='Utility method'/> |
| 34 | </ProtoInterface> |
| 35 | <ProtoBody> |
| 36 | <Group> |
| 37 | |
| 38 | <IS> |
| 39 | <connect nodeField='key' protoField='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='description' protoField='keyValue'/> |
| 45 | </IS> |
| 46 | </Anchor> |
| 47 | <Script DEF='SequencerScript' directOutput='true'> |
| 48 | <!-- Regular interpolator-style input --> |
| 49 |
<field name='set_fraction' type='SFFloat' accessType='inputOnly'
appinfo='typical range [0..1]'/> |
| 50 |
<field name='set_key' type='MFFloat' accessType='inputOnly'
appinfo='Array sequentially increasing typically [0..1]. Must have the same number of keys as keyValues.'/> |
| 51 | <field name='keyHolderNode' type='SFNode' accessType='initializeOnly'> |
| 52 | <ScalarInterpolator USE='KeyHolder'/> |
| 53 | </field> |
| 54 | <field name='key_changed' type='MFFloat' accessType='outputOnly'/> |
| 55 |
<field name='set_keyValue' type='MFBool' accessType='inputOnly'
appinfo='Array of true or false values. Must have the same number of keys as keyValues.'/> |
| 56 | <field name='keyValueHolderNode' type='SFNode' accessType='initializeOnly'> |
| 57 | <Anchor USE='KeyValueHolder'/> |
| 58 | </field> |
| 59 | <field name='keyValue_changed' type='MFBool' accessType='outputOnly'/> |
| 60 | <!-- Regular interpolator-style output --> |
| 61 | <field name='value_changed' type='SFBool' accessType='outputOnly'/> |
| 62 | <!-- Utility methods --> |
| 63 | <field name='previous' type='SFBool' accessType='inputOnly'/> |
| 64 | <field name='next' type='SFBool' accessType='inputOnly'/> |
| 65 | <!-- Script-specific interfaces, not needed for node definition --> |
| 66 | <field name='traceEnabled' type='SFBool' value='false' accessType='initializeOnly'/> |
| 67 | <field name='keyValueArray' type='MFInt32' accessType='initializeOnly'> |
| 68 | <!-- NULL initialization value --> |
| 69 | </field> |
| 70 | <field name='previousFraction' type='SFFloat' value='0.0' accessType='initializeOnly'/> |
| 71 | <field name='nextIndex' type='SFInt32' value='0' accessType='initializeOnly'/> |
| 72 | <field name='valid' type='SFBool' value='true' accessType='outputOnly'/> |
| 73 | <field name='recheckValidity' type='SFBool' value='false' accessType='initializeOnly'/> |
| 74 |
<field name='forward' type='SFBool' value='true' accessType='initializeOnly'
appinfo='leftToRight'/> |
| 75 | <field name='key' type='MFFloat' accessType='inputOnly'> |
| 76 | <!-- NULL initialization value --> |
| 77 | </field> |
| 78 | <field name='keyValue' type='MFInt32' accessType='inputOutput'> |
| 79 | <!-- NULL initialization value --> |
| 80 | </field> |
| 81 | <IS> |
| 82 | <connect nodeField='set_fraction' protoField='set_fraction'/> |
| 83 | <connect nodeField='set_key' protoField='set_key'/> |
| 84 | <connect nodeField='key_changed' protoField='key_changed'/> |
| 85 | <connect nodeField='set_keyValue' protoField='set_keyValue'/> |
| 86 | <connect nodeField='keyValue_changed' protoField='keyValue_changed'/> |
| 87 | <connect nodeField='value_changed' protoField='value_changed'/> |
| 88 | <connect nodeField='previous' protoField='previous'/> |
| 89 | <connect nodeField='next' protoField='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='BooleanSequencerExample' parameter='"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 with 0 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.
|
SequencerScript
Script |
No direct ROUTE connection found for events to/from this node. Contains SFNode fields with direct access to another node. |
| line 97
Anchor |
description='BooleanSequencerExample' User-interaction hint for this node. |
<!--
Color-coding 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>
-->
<!--
For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources, and X3D Scene Authoring Hints.
-->