<?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='DoubleClickTouchSensorPrototype.x3d'/>
<meta name='descriptioncontent='Double-click TouchSensor design pattern, implemented as a reusable prototype node.'/>
<meta name='creatorcontent='Don Brutzman'/>
<meta name='createdcontent='26 May 2004'/>
<meta name='modifiedcontent='6 June 2020'/>
<meta name='referencecontent='DoubleClickTouchSensorExample.x3d'/>
<meta name='referencecontent=' https://www.web3d.org/x3d/specifications/ISO-IEC-19775-FDIS-X3dAbstractSpecification/Part01/components/pointingsensor.html#TouchSensor '/>
<meta name='subjectcontent='DoubleClickTouchSensor'/>
<meta name='identifiercontent=' https://savage.nps.edu/Savage/Tools/Animation/DoubleClickTouchSensorPrototype.x3d '/>
<meta name='generatorcontent='X3D-Edit 3.2, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../../license.html'/>
</head>
<!--

Index for ProtoDeclare definition : DoubleClickTouchSensor

Index for DEF nodes : DoubleClickTouchScript, MetadataHolder, TouchSensorNode
-->
<Scene>
<WorldInfo title='DoubleClickTouchSensorPrototype.x3d'/>
<ProtoDeclare name='DoubleClickTouchSensorappinfo='DoubleClickTouchSensor functionality activates when user double clicks (or double selects) within maxDelayInterval'>
<ProtoInterface>
<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='describe the purpose of this sensor'/>

<field name='maxDelayIntervaltype='SFTimevalue='0.5accessType='initializeOnly'
 appinfo='seconds'/>

<field name='enabledtype='SFBoolvalue='trueaccessType='inputOutput'/>
<field name='isActivetype='SFBoolaccessType='outputOnly'/>
<field name='isOvertype='SFBoolaccessType='outputOnly'/>
<field name='touchTimetype='SFTimeaccessType='outputOnly'
 appinfo='seconds'/>

<field name='hitPoint_changedtype='SFVec3faccessType='outputOnly'/>
<field name='hitNormal_changedtype='SFVec3faccessType='outputOnly'/>
<field name='hitTexCoord_changedtype='SFVec2faccessType='outputOnly'/>
<field name='metadatatype='SFNodeaccessType='initializeOnly'
 appinfo='can contain one of Metadata nodes'>
<!-- initialization node (if any) goes here -->
</field>
<field name='traceEnabledtype='SFBoolvalue='falseaccessType='initializeOnly'/>
</ProtoInterface>
<ProtoBody>
<!-- ROUTE information for TouchSensorNode node:  [from isActive to DoubleClickTouchScript.checkClicks ] -->
<TouchSensor DEF='TouchSensorNode'>
<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='enabledprotoField='enabled'/>
<connect nodeField='isOverprotoField='isOver'/>
</IS>
</TouchSensor>
<!-- Only first node inside a ProtoBody is rendered. TouchSensor must remain outside Group to be externally active. -->
<Group>
<!-- ROUTE information for DoubleClickTouchScript node:  [from TouchSensorNode.isActive to checkClicks ] -->
<Script DEF='DoubleClickTouchScriptdirectOutput='true'>
<field name='descriptiontype='SFStringaccessType='inputOutput'/>
<field name='checkClickstype='SFBoolaccessType='inputOnly'/>
<field name='maxDelayIntervaltype='SFTimeaccessType='initializeOnly'
 appinfo='seconds'/>

<field name='priorTouchTimetype='SFTimevalue='-1accessType='initializeOnly'/>
<field name='currentTouchTimetype='SFTimevalue='-1accessType='initializeOnly'/>
<field name='touchSensortype='SFNodeaccessType='initializeOnly'
 appinfo='permits controlled access to various TouchSensorNode fields'>
<TouchSensor USE='TouchSensorNode'/>
</field>
<field name='isActivetype='SFBoolaccessType='outputOnly'/>
<field name='touchTimetype='SFTimeaccessType='outputOnly'
 appinfo='seconds'/>

<field name='hitPoint_changedtype='SFVec3faccessType='outputOnly'/>
<field name='hitNormal_changedtype='SFVec3faccessType='outputOnly'/>
<field name='hitTexCoord_changedtype='SFVec2faccessType='outputOnly'/>
<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'/>
<IS>
<connect nodeField='descriptionprotoField='description'/>
<connect nodeField='maxDelayIntervalprotoField='maxDelayInterval'/>
<connect nodeField='isActiveprotoField='isActive'/>
<connect nodeField='touchTimeprotoField='touchTime'/>
<connect nodeField='hitPoint_changedprotoField='hitPoint_changed'/>
<connect nodeField='hitNormal_changedprotoField='hitNormal_changed'/>
<connect nodeField='hitTexCoord_changedprotoField='hitTexCoord_changed'/>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
</IS>
<![CDATA[
            
ecmascript:

//  inputOnly events are handled by functions,
//  initializeOnly fields are variable objects,
//  outputOnly events are sent by setting values

function initialize ()
{
	tracePrint ('initialize (); enabled=' + touchSensor.enabled);
}

// trigger on isActive to filter touchTime events when unclicking

function checkClicks (value, timestamp)  // activated from TouchSensorNode.isActive
{
	if (value == false) // doubleClick isActive=false events
	{
		if (isActive == true) // need to unclick
		{
			isActive  = false;	// send output events
			touchTime = timestamp;
			tracePrint ('DoubleClick isActive=false;');
		}
		return;
	}
	priorTouchTime = currentTouchTime;
	currentTouchTime = timestamp;
	computedDelay = (currentTouchTime - priorTouchTime);

	if      (priorTouchTime == -1)
	{
		tracePrint ('priorTouchTime == -1, return;');
		return;
	}
	else if (computedDelay <= maxDelayInterval)
	{
		tracePrint ('computedDelay=' + computedDelay + ', DoubleClick isActive=true;');

		isActive  = true;	// send output events
		touchTime = timestamp;
		hitPoint_changed    = touchSensor.hitPoint_changed;
		hitNormal_changed   = touchSensor.hitNormal_changed;
		hitTexCoord_changed = touchSensor.hitTexCoord_changed;
	}
	else
	{
		tracePrint ('computedDelay=' + computedDelay + ', single click');
		return;
	}

}
function set_description (newDescription)
{
    description = newDescription;
}
function tracePrint (outputString)
{
	if (traceEnabled) Browser.print ('[DoubleClickTouchSensor] ' + outputString);
}

          
]]>
</Script>
<ROUTE fromNode='TouchSensorNodefromField='isActivetoNode='DoubleClickTouchScripttoField='checkClicks'/>
<Collision DEF='MetadataHolderenabled='false'>
<IS>
<connect nodeField='proxyprotoField='metadata'/>
</IS>
</Collision>
</Group>
</ProtoBody>
</ProtoDeclare>
<!-- ====================================== -->
<!-- Example use -->
<Anchor description='DoubleClickTouchSensor Exampleparameter='"target=_blank"'
  url=' "DoubleClickTouchSensorExample.x3d" "https://savage.nps.edu/Savage/Tools/Animation/DoubleClickTouchSensorExample.x3d" "DoubleClickTouchSensorExample.wrl" "https://savage.nps.edu/Savage/Tools/Animation/DoubleClickTouchSensorExample.wrl" '>
<Shape>
<Text string='"DoubleClickTouchSensorPrototype" "defines a prototype" "" "Click text to see" "DoubleClickTouchSensorExample scene"'>
<FontStyle justify='"MIDDLE" "MIDDLE"size='0.7'/>
</Text>
<Appearance>
<Material diffuseColor='1 1 0.2'/>
</Appearance>
</Shape>
</Anchor>
</Scene>
</X3D>
<!--

Index for ProtoDeclare definition : DoubleClickTouchSensor

Index for DEF nodes : DoubleClickTouchScript, MetadataHolder, TouchSensorNode
-->

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

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