<?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='PushButtonPrototype.x3d'/>
<meta name='descriptioncontent='PushButton widget prototype declaration, inner button and outer shape can be round or square'/>
<meta name='creatorcontent='Don Brutzman, Murat Onder and MV4205 class, Spring 2004 Quarter'/>
<meta name='createdcontent='11 May 2004'/>
<meta name='modifiedcontent='9 July 2018'/>
<meta name='referencecontent='PushButtonExample.x3d'/>
<meta name='identifiercontent=' https://savage.nps.edu/Savage/Tools/Animation/PushButtonPrototype.x3d '/>
<meta name='generatorcontent='X3D-Edit 3.2, https://savage.nps.edu/X3D-Edit'/>
<meta name='licensecontent=' ../../license.html'/>
</head>
<!-- -->
<Scene>
<!-- Material Toggle Prototype is being used to be able to provide the color toggle. -->
<ExternProtoDeclare name='MaterialToggleappinfo='MaterialToggle selects one of two different Material values'
  url=' "MaterialTogglePrototype.x3d#MaterialToggle" "../../Tools/Animation/MaterialTogglePrototype.x3d#MaterialToggle" "https://savage.nps.edu/Savage/Tools/Animation/MaterialTogglePrototype.x3d#MaterialToggle" "../../Tools/Animation/MaterialTogglePrototype.wrl#MaterialToggle" "MaterialTogglePrototype.wrl#MaterialToggle" "https://savage.nps.edu/Savage/Tools/Animation/MaterialTogglePrototype.wrl#MaterialToggle" '>
<field name='defaultMaterialtype='SFNodeaccessType='initializeOnly'
 appinfo='Material node that is enabled when toggle=false'/>

<field name='toggleMaterialtype='SFNodeaccessType='initializeOnly'
 appinfo='Material node that is enabled when toggle=true'/>

<field name='set_toggletype='SFBoolaccessType='inputOnly'/>
<field name='set_defaultMaterialtype='SFNodeaccessType='inputOnly'
 appinfo='provide replacement default Material node'/>

<field name='toggletype='SFBoolaccessType='initializeOnly'
 appinfo='whether to use DefaultMaterial or ToggleMaterial'/>

<field name='toggle_changedtype='SFBoolaccessType='outputOnly'/>
<field name='set_toggleMaterialtype='SFNodeaccessType='inputOnly'
 appinfo='provide replacement toggle Material node'/>
</ExternProtoDeclare>
<!-- TimeDelaySensor is being used to provide the time delay for button's color change delay -->
<ExternProtoDeclare name='TimeDelaySensorappinfo='TimeSensor functionality commences after delayInterval pause'
  url=' "TimeDelaySensorPrototype.x3d#TimeDelaySensor" "../../Tools/Animation/TimeDelaySensorPrototype.x3d#TimeDelaySensor" "https://savage.nps.edu/Savage/Tools/Animation/TimeDelaySensorPrototype.x3d#TimeDelaySensor" "../../Tools/Animation/TimeDelaySensorPrototype.wrl#TimeDelaySensor" "TimeDelaySensorPrototype.wrl#TimeDelaySensor" "https://savage.nps.edu/Savage/Tools/Animation/TimeDelaySensorPrototype.wrl#TimeDelaySensor" '>
<field name='startTimetype='SFTimeaccessType='inputOutput'
 appinfo='when current time exceeds startTime, isActive becomes true and sensor becomes active'/>

<field name='delayIntervaltype='SFTimeaccessType='inputOutput'
 appinfo='seconds'/>

<field name='delayCompleteTimetype='SFTimeaccessType='outputOnly'/>
<field name='enabledtype='SFBoolaccessType='inputOutput'
 appinfo='whether sensor is active'/>

<field name='descriptiontype='SFStringaccessType='inputOutput'
 appinfo='describe the purpose of this sensor'/>

<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'/>
</ExternProtoDeclare>
<!-- PushButton Prototype definition starts here.. -->
<ProtoDeclare name='PushButtonappinfo='PushButton widget, inner button and outer shape can be round or square'>
<ProtoInterface>
<field name='traceEnabledtype='SFBoolvalue='trueaccessType='initializeOnly'
 appinfo='enables the console print-out in case of assigning wrong values default is true'/>

<field name='outerShapeMaterialtype='SFNodeaccessType='initializeOnly'>
<Material DEF='BluediffuseColor='0 0 1'/>
</field>
<field name='defaultMaterialtype='SFNodeaccessType='initializeOnly'
 appinfo='defaultMaterial for inner pushbutton'>
<Material DEF='ReddiffuseColor='0.8 0.1 0'/>
</field>
<field name='toggleMaterialtype='SFNodeaccessType='initializeOnly'
 appinfo='toggleMaterial for inner pushbutton'>
<Material DEF='GreendiffuseColor='0.1 0.8 0'/>
</field>
<field name='value_changedtype='SFBoolaccessType='outputOnly'
 appinfo='boolean output of button selection'/>

<!-- switch values for combination of the button, default: round-round -->
<field name='outerSwitchStyletype='SFStringvalue='roundaccessType='initializeOnly'
 appinfo='allowed values: round or square default is round'/>

<field name='set_outerSwitchStyletype='SFStringaccessType='inputOnly'
 appinfo='allowed values: round or square default is round'/>

<field name='innerSwitchStyletype='SFStringvalue='roundaccessType='initializeOnly'
 appinfo='allowed values: round square. default is round'/>

<field name='set_innerSwitchStyletype='SFStringaccessType='inputOnly'
 appinfo='allowed values: round square. default is round'/>

<field name='delayIntervaltype='SFTimevalue='.5accessType='initializeOnly'
 appinfo='time delay for button movement so for color change default is 0.5 sec.'/>
</ProtoInterface>
<ProtoBody>
<Group>
<!-- ROUTE information for DelayTimer node:  [from Toucher.touchTime to startTime ] [from delayCompleteTime to Clock2.set_startTime ] -->
<ProtoInstance name='TimeDelaySensorDEF='DelayTimer'>
<IS>
<connect nodeField='delayIntervalprotoField='delayInterval'/>
</IS>
</ProtoInstance>
<Transform DEF='OuterShapeTransformrotation='1 0 0 1.57'>
<Switch DEF='OuterShapeSwitchRoundwhichChoice='-1'>
<Shape>
<Cylinder height='.12radius='.5'/>
<Appearance>
<IS>
<connect nodeField='materialprotoField='outerShapeMaterial'/>
</IS>
</Appearance>
</Shape>
</Switch>
<Switch DEF='OuterShapeSwitchSquarewhichChoice='-1'>
<Shape>
<Box size='1 .12 1'/>
<Appearance>
<IS>
<connect nodeField='materialprotoField='outerShapeMaterial'/>
</IS>
</Appearance>
</Shape>
</Switch>
</Transform>
<!-- ROUTE information for InnerShapeTransform node:  [from SwitchAnimator1.value_changed to set_translation ] [from SwitchAnimator2.value_changed to set_translation ] -->
<Transform DEF='InnerShapeTransformrotation='1 0 0 1.57translation='0 0 .1'>
<Switch DEF='InnerShapeSwitchRoundwhichChoice='-1'>
<Shape>
<Cylinder height='.12radius='.35'/>
<Appearance>
<!-- ROUTE information for PushButtonToggleMaterial node:  [from BooleanToggler.toggle_changed to set_toggle ] -->
<ProtoInstance name='MaterialToggleDEF='PushButtonToggleMaterialcontainerField='material'>
<IS>
<connect nodeField='defaultMaterialprotoField='defaultMaterial'/>
<connect nodeField='toggleMaterialprotoField='toggleMaterial'/>
</IS>
</ProtoInstance>
</Appearance>
</Shape>
</Switch>
<Switch DEF='InnerShapeSwitchSquarewhichChoice='-1'>
<Shape>
<Box size='.57 .12 .57'/>
<Appearance>
<ProtoInstance USE='PushButtonToggleMaterialcontainerField='material'/>
</Appearance>
</Shape>
</Switch>
<Sound>
<!-- ROUTE information for ClickAudio node:  [from Toucher.touchTime to set_startTime ] -->
<AudioClip DEF='ClickAudiodescription='click sound'
  url=' "click.wav" "https://savage.nps.edu/Savage/Tools/Animation/click.wav" '/>
</Sound>
<!-- ROUTE information for Toucher node:  [from touchTime to ClickAudio.set_startTime ] [from touchTime to DelayTimer.startTime ] [from touchTime to Clock1.set_startTime ] -->
<TouchSensor DEF='Toucherdescription='touch to push the button'/>
<ROUTE fromNode='ToucherfromField='touchTimetoNode='ClickAudiotoField='set_startTime'/>
<ROUTE fromNode='ToucherfromField='touchTimetoNode='DelayTimertoField='startTime'/>
</Transform>
<Group DEF='AnimationGroup'>
<!-- ============================= -->
<!-- ROUTE information for Clock1 node:  [from Toucher.touchTime to set_startTime ] [from fraction_changed to SwitchAnimator1.set_fraction ] -->
<TimeSensor DEF='Clock1'/>
<ROUTE fromNode='ToucherfromField='touchTimetoNode='Clock1toField='set_startTime'/>
<!-- ============================= -->
<!-- ROUTE information for SwitchAnimator1 node:  [from Clock1.fraction_changed to set_fraction ] [from value_changed to InnerShapeTransform.set_translation ] -->
<PositionInterpolator DEF='SwitchAnimator1key='0 .5 1keyValue='0 0 .1 0 0 .05 0 0 .007'/>
<ROUTE fromNode='Clock1fromField='fraction_changedtoNode='SwitchAnimator1toField='set_fraction'/>
<ROUTE fromNode='SwitchAnimator1fromField='value_changedtoNode='InnerShapeTransformtoField='set_translation'/>
<!-- ============================= -->
<!-- ROUTE information for Clock2 node:  [from DelayTimer.delayCompleteTime to set_startTime ] [from fraction_changed to SwitchAnimator2.set_fraction ] [from isActive to BooleanToggler.set_boolean ] -->
<TimeSensor DEF='Clock2'/>
<ROUTE fromNode='DelayTimerfromField='delayCompleteTimetoNode='Clock2toField='set_startTime'/>
<!-- ============================= -->
<!-- ROUTE information for SwitchAnimator2 node:  [from Clock2.fraction_changed to set_fraction ] [from value_changed to InnerShapeTransform.set_translation ] -->
<PositionInterpolator DEF='SwitchAnimator2key='0 .5 1keyValue='0 0 .007 0 0 .05 0 0 .1'/>
<ROUTE fromNode='Clock2fromField='fraction_changedtoNode='SwitchAnimator2toField='set_fraction'/>
<ROUTE fromNode='SwitchAnimator2fromField='value_changedtoNode='InnerShapeTransformtoField='set_translation'/>
<!-- ============================= -->
<!-- ROUTE information for BooleanToggler node:  [from Clock2.isActive to set_boolean ] [from toggle_changed to PushButtonToggleMaterial.set_toggle ] -->
<BooleanToggle DEF='BooleanToggler'>
<IS>
<connect nodeField='toggle_changedprotoField='value_changed'/>
</IS>
</BooleanToggle>
<ROUTE fromNode='Clock2fromField='isActivetoNode='BooleanTogglertoField='set_boolean'/>
<ROUTE fromNode='BooleanTogglerfromField='toggle_changedtoNode='PushButtonToggleMaterialtoField='set_toggle'/>
</Group>
</Group>
<!-- Only first node in ProtoBody is rendered -->
<Script directOutput='true'>
<field name='traceEnabledtype='SFBoolaccessType='initializeOnly'/>
<field name='delayIntervaltype='SFTimeaccessType='initializeOnly'/>
<field name='outerSwitchStyletype='SFStringaccessType='initializeOnly'
 appinfo='allowed values: round square. default is round'/>

<field name='set_outerSwitchStyletype='SFStringaccessType='inputOnly'
 appinfo='allowed values: round square. default is round'/>

<field name='innerSwitchStyletype='SFStringaccessType='initializeOnly'
 appinfo='allowed values: round square. default is round'/>

<field name='set_innerSwitchStyletype='SFStringaccessType='inputOnly'
 appinfo='allowed values: round square. default is round'/>

<field name='switchOuterRoundtype='SFNodeaccessType='initializeOnly'>
<Switch USE='OuterShapeSwitchRoundwhichChoice='-1'/>
</field>
<field name='switchOuterSquaretype='SFNodeaccessType='initializeOnly'>
<Switch USE='OuterShapeSwitchSquarewhichChoice='-1'/>
</field>
<field name='switchInnerRoundtype='SFNodeaccessType='initializeOnly'>
<Switch USE='InnerShapeSwitchRoundwhichChoice='-1'/>
</field>
<field name='switchInnerSquaretype='SFNodeaccessType='initializeOnly'>
<Switch USE='InnerShapeSwitchSquarewhichChoice='-1'/>
</field>
<field name='clock1type='SFNodeaccessType='initializeOnly'>
<TimeSensor USE='Clock1'/>
</field>
<field name='clock2type='SFNodeaccessType='initializeOnly'>
<TimeSensor USE='Clock2'/>
</field>
<IS>
<connect nodeField='traceEnabledprotoField='traceEnabled'/>
<connect nodeField='outerSwitchStyleprotoField='outerSwitchStyle'/>
<connect nodeField='set_outerSwitchStyleprotoField='set_outerSwitchStyle'/>
<connect nodeField='innerSwitchStyleprotoField='innerSwitchStyle'/>
<connect nodeField='set_innerSwitchStyleprotoField='set_innerSwitchStyle'/>
<connect nodeField='delayIntervalprotoField='delayInterval'/>
</IS>
<![CDATA[
          
ecmascript:

function initialize()
{
   clock1.cycleInterval = delayInterval;
   clock2.cycleInterval = delayInterval;

   set_innerSwitchStyle(innerSwitchStyle);
   set_outerSwitchStyle(outerSwitchStyle);
}

function set_innerSwitchStyle(stringValue)
{
   if (stringValue != null)  //security check
   {
      if (stringValue != 'round')
      {
         if (stringValue != 'square')
         {
            printError(stringValue, 'inner');
            innerSwitchStyle = 'round';
         }
         else
         {
            innerSwitchStyle = stringValue;
         }
      }
      else
      {
          innerSwitchStyle = stringValue;
      }
   }

   if      (innerSwitchStyle == 'round')
   {
        switchInnerSquare.whichChoice = -1;
         switchInnerRound.whichChoice =  0;
   }
   else // (innerSwitchStyle == 'square')
   {
        switchInnerSquare.whichChoice =  0;
         switchInnerRound.whichChoice = -1;
   }
}

function set_outerSwitchStyle(stringValue)
{
   if (stringValue != null)    //security check
   {
      if (stringValue != 'round')
      {
         if (stringValue != 'square')
         {
            printError(stringValue, 'outer');
            outerSwitchStyle = 'round';
         }
         else
         {
            outerSwitchStyle = stringValue;
         }
      }
      else
      {
          outerSwitchStyle = stringValue;
      }
   }

   if      (outerSwitchStyle == 'round')
   {
        switchOuterSquare.whichChoice = -1;
         switchOuterRound.whichChoice =  0;
   }
   else // (outerSwitchStyle == 'square')
   {
        switchOuterSquare.whichChoice =  0;
         switchOuterRound.whichChoice = -1;
   }
}

function printError(s1, s2)
{
    if (traceEnabled)
    {
      Browser.print ('\nAllowed values are [round] and [square].' +
            '\nAssigned value [' + s1 + '] (The values are case/whitespace-sensitive).' +
            '\nDefault value  [round] will be used for [' + s2 + 'SwitchStyle].\n');
    }
}

        
]]>
</Script>
</ProtoBody>
</ProtoDeclare>
<!-- ==================== -->
<Anchor description='PushButtonExampleparameter='"target=_blank"'
  url=' "PushButtonExample.x3d" "../../Tools/Animation/PushButtonExample.x3d" "https://savage.nps.edu/Savage/Tools/Animation/PushButtonExample.x3d" "../../Tools/Animation/PushButtonExample.wrl" "PushButtonExample.wrl" "https://savage.nps.edu/Savage/Tools/Animation/PushButtonExample.wrl" '>
<Shape>
<Text string='"PushButtonPrototype" "defines a prototype" "" "Click text to see example scene" "" "You can define 4 different buttons" "with the combination of round&square" "(default is round-round)"'>
<FontStyle justify='"MIDDLE" "MIDDLE"size='0.7'/>
</Text>
<Appearance>
<Material diffuseColor='.8 .7 0.2'/>
</Appearance>
</Shape>
</Anchor>
</Scene>
</X3D>
<!--

Index for ExternProtoDeclare definitions : MaterialToggle, TimeDelaySensor

Index for ProtoDeclare definition : PushButton

Index for DEF nodes : AnimationGroup, Blue, BooleanToggler, ClickAudio, Clock1, Clock2, DelayTimer, Green, InnerShapeSwitchRound, InnerShapeSwitchSquare, InnerShapeTransform, OuterShapeSwitchRound, OuterShapeSwitchSquare, OuterShapeTransform, PushButtonToggleMaterial, Red, SwitchAnimator1, SwitchAnimator2, 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 -->