<?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 content='EventUtilityPrototypes.x3d' name='title'/>
    <meta content='Event utility node prototypes for boolean filtering and other event utility nodes.' name='description'/>
    <meta content='Nick Polys, Tony Parisi, Don Brutzman, Justin Couch' name='creator'/>
    <meta content='25 September 2002' name='created'/>
    <meta content='20 January 2020' name='modified'/>
    <meta content='Under development, IntegerTrigger example needed.' name='warning'/>
    <meta content='EventUtilityExamples.x3d' name='reference'/>
    <meta content='BooleanFilter BooleanToggle BooleanTrigger IntegerTrigger TimeTrigger' name='subject'/>
    <meta content='https://www.web3d.org/x3d/content/examples/Basic/development/EventUtilityPrototypes.x3d' name='identifier'/>
    <meta content='X3D-Edit 3.3, https://www.web3d.org/x3d/tools/X3D-Edit' name='generator'/>
    <meta content='../license.html' name='license'/>
  </head>
  <Scene>
    <WorldInfo title='EventUtilityPrototypes.x3d'/>
    <ProtoDeclare appinfo='BooleanFilter selectively passes true false or negated events.' name='BooleanFilter'>
      <ProtoInterface>
        <field accessType='inputOnly' appinfo='set_boolean is the input value to be filtered.' name='set_boolean' type='SFBool'/>
        <field accessType='outputOnly' appinfo='inputTrue only passes a true value when set_boolean input is true.' name='inputTrue' type='SFBool'/>
        <field accessType='outputOnly' appinfo='inputFalse only passes a false value when set_boolean is false.' name='inputFalse' type='SFBool'/>
        <field accessType='outputOnly' appinfo='inputNegate provides opposite value by negating set_boolean input.' name='inputNegate' type='SFBool'/>
      </ProtoInterface>
      <ProtoBody>
        <Script DEF='BooleanFilterScript'>
          <field accessType='inputOnly' name='set_boolean' type='SFBool'/>
          <field accessType='outputOnly' name='inputTrue' type='SFBool'/>
          <field accessType='outputOnly' name='inputFalse' type='SFBool'/>
          <field accessType='outputOnly' name='inputNegate' type='SFBool'/>
          <IS>
            <connect nodeField='set_boolean' protoField='set_boolean'/>
            <connect nodeField='inputTrue' protoField='inputTrue'/>
            <connect nodeField='inputFalse' protoField='inputFalse'/>
            <connect nodeField='inputNegate' protoField='inputNegate'/>
          </IS>
          <![CDATA[
ecmascript:

function set_boolean (value, timestamp)
{
	if (value) inputTrue  = value;
	else       inputFalse = value;
	inputNegate = !value;

//	if (value) Browser.println ('[BooleanFilter] set_boolean=' + value + ', inputTrue='  + inputTrue  + ', inputNegate=' + inputNegate);
//	else       Browser.println ('[BooleanFilter] set_boolean=' + value + ', inputFalse=' + inputFalse + ', inputNegate=' + inputNegate);
}
]]>
        </Script>
      </ProtoBody>
    </ProtoDeclare>
    <!-- ======================================== -->
    <ProtoDeclare appinfo='BooleanToggle maintains state and negates output when a true input is provided.' name='BooleanToggle'>
      <ProtoInterface>
        <field accessType='inputOnly' appinfo='If set_boolean input is true toggle state.' name='set_boolean' type='SFBool'/>
        <field accessType='inputOnly' appinfo='Reset persistent state value.' name='set_toggle' type='SFBool'/>
        <field accessType='initializeOnly' appinfo='Persistent state value that gets toggled or reset.' name='toggle' type='SFBool' value='false'/>
        <field accessType='outputOnly' appinfo='Output toggled persistent state value.' name='toggle_changed' type='SFBool'/>
        <!-- warning: toggle depends on exposedField functionality in Script node, not compatible with VRML 97. implemented as inputOnly/initializeOnly/outputOnly triplet. -->
      </ProtoInterface>
      <ProtoBody>
        <Group>
          <Script DEF='BooleanToggleScript'>
            <field accessType='inputOnly' name='set_boolean' type='SFBool'/>
            <field accessType='inputOnly' name='set_toggle' type='SFBool'/>
            <field accessType='initializeOnly' name='toggle' type='SFBool' value='false'/>
            <field accessType='outputOnly' name='toggle_changed' type='SFBool'/>
            <field accessType='initializeOnly' name='traceEnabled' type='SFBool' value='false'/>
            <IS>
              <connect nodeField='set_boolean' protoField='set_boolean'/>
              <connect nodeField='set_toggle' protoField='set_toggle'/>
              <connect nodeField='toggle_changed' protoField='toggle_changed'/>
            </IS>
            <![CDATA[
ecmascript:

function initialize ()
{
	if (traceEnabled) Browser.println ('[BooleanToggle] toggle=' + toggle);

}
function set_boolean (value, timestamp)
{
	if (value == true)  // only toggle on true input
	{
		if (toggle == true) toggle = false;
		else                toggle = true;
	}
	toggle_changed = toggle;
//	Browser.println ('[BooleanToggle] traceEnabled=' + traceEnabled);
	if (traceEnabled) Browser.println ('[BooleanToggle] set_boolean=' + value + ', toggle=' + toggle);
}
function set_toggle (value, timestamp)
{
	toggle = value;
	toggle_changed = toggle;
	if (traceEnabled) Browser.println ('[BooleanToggle] set_toggle=' + set_toggle);
}
]]>
          </Script>
        </Group>
      </ProtoBody>
    </ProtoDeclare>
    <!-- ======================================== -->
    <ProtoDeclare appinfo='BooleanTrigger converts time events to boolean true events.' name='BooleanTrigger'>
      <ProtoInterface>
        <field accessType='inputOnly' appinfo='set_triggerTime provides input time event typical event sent is TouchSensor touchTime.' name='set_triggerTime' type='SFTime'/>
        <field accessType='outputOnly' appinfo='triggerTrue outputs a true value whenever a triggerTime event is received.' name='triggerTrue' type='SFBool'/>
      </ProtoInterface>
      <ProtoBody>
        <Script DEF='TriggerBooleanScript'>
          <field accessType='inputOnly' name='set_triggerTime' type='SFTime'/>
          <field accessType='outputOnly' name='triggerTrue' type='SFBool'/>
          <IS>
            <connect nodeField='set_triggerTime' protoField='set_triggerTime'/>
            <connect nodeField='triggerTrue' protoField='triggerTrue'/>
          </IS>
          <![CDATA[
ecmascript:

function set_triggerTime (value, timestamp)
{
	triggerTrue = true;
//	Browser.println ('triggerTrue = true');
}
]]>
        </Script>
      </ProtoBody>
    </ProtoDeclare>
    <!-- ======================================== -->
    <ProtoDeclare appinfo='IntegerTrigger converts boolean true or time input events to integer value (suitable for Switch node).' name='IntegerTrigger'>
      <ProtoInterface>
        <field accessType='inputOnly' appinfo='If set_boolean input is true trigger output of integer value.' name='set_boolean' type='SFBool'/>
        <field accessType='inputOnly' appinfo='Resets value used for output when triggered later.' name='set_integerKey' type='SFInt32'/>
        <field accessType='inputOutput' appinfo='integerKey is value for output when triggered.' name='integerKey' type='SFInt32' value='-1'/>
        <field accessType='outputOnly' appinfo='Reports change in integerKey value.' name='integerKey_changed' type='SFInt32'/>
        <field accessType='outputOnly' appinfo='triggerValue provides integer event output matching integerKey when true set_boolean received.' name='triggerValue' type='SFInt32'/>
      </ProtoInterface>
      <ProtoBody>
        <Group>
          <Switch DEF='IntegerKeyHolder' whichChoice='-1'>
            <IS>
              <connect nodeField='whichChoice' protoField='integerKey'/>
            </IS>
          </Switch>
          <Script DEF='TriggerIntegerScript' directOutput='true'>
            <field accessType='inputOnly' name='set_boolean' type='SFBool'/>
            <field accessType='inputOnly' name='set_integerKey' type='SFInt32'/>
            <field accessType='initializeOnly' name='integerKeyHolderNode' type='SFNode'>
              <Switch USE='IntegerKeyHolder' whichChoice='-1'/>
            </field>
            <field accessType='outputOnly' name='integerKey_changed' type='SFInt32'/>
            <field accessType='outputOnly' name='triggerValue' type='SFInt32'/>
            <IS>
              <connect nodeField='set_boolean' protoField='set_boolean'/>
              <connect nodeField='set_integerKey' protoField='set_integerKey'/>
              <connect nodeField='integerKey_changed' protoField='integerKey_changed'/>
              <connect nodeField='triggerValue' protoField='triggerValue'/>
            </IS>
            <![CDATA[
ecmascript:

function set_boolean (inputValue, timestamp)
{
	if (inputValue == true)
	{
		integerKey = integerKeyHolderNode.whichChoice;
		triggerValue = integerKey; // send output event
	}
}
function set_integerKey (inputValue, timestamp)
{
	integerKey = inputValue;
	integerKeyHolderNode.whichChoice = integerKey;
	integerKey_changed = integerKey; // send output event
}
]]>
          </Script>
        </Group>
      </ProtoBody>
    </ProtoDeclare>
    <!-- ======================================== -->
    <ProtoDeclare appinfo='TimeTrigger converts boolean true events to time events.' name='TimeTrigger'>
      <ProtoInterface>
        <field accessType='inputOnly' appinfo='If set_boolean input is true trigger output time value.' name='set_boolean' type='SFBool'/>
        <field accessType='outputOnly' appinfo='triggerTime is output time event sent when set_boolean input is true.' name='triggerTime' type='SFTime'/>
      </ProtoInterface>
      <ProtoBody>
        <Script DEF='TriggerTimeScript'>
          <field accessType='inputOnly' name='set_boolean' type='SFBool'/>
          <field accessType='outputOnly' name='triggerTime' type='SFTime'/>
          <IS>
            <connect nodeField='set_boolean' protoField='set_boolean'/>
            <connect nodeField='triggerTime' protoField='triggerTime'/>
          </IS>
          <![CDATA[
ecmascript:

function set_boolean (value, timestamp)
{
	if (value) triggerTime = timestamp;
}
]]>
        </Script>
      </ProtoBody>
    </ProtoDeclare>
    <!-- ======================================== -->
    <Anchor description='EventUtilityExamples' parameter='"target=_blank"' url='"EventUtilityExamples.x3d" "https://www.web3d.org/x3d/content/examples/Basic/development/EventUtilityExamples.x3d" "EventUtilityExamples.wrl" "https://www.web3d.org/x3d/content/examples/Basic/development/EventUtilityExamples.wrl"'>
      <Shape>
        <Text string='"EventUtilityPrototype" "defines prototypes" "" "Click text to see" "EventUtilityExamples"'>
          <FontStyle justify='"MIDDLE" "MIDDLE"' size='0.9'/>
        </Text>
        <Appearance>
          <Material diffuseColor='1 1 0.2'/>
        </Appearance>
      </Shape>
    </Anchor>
  </Scene>
</X3D>