X3D Model Documentation: Slider.x3d

  1  <?xml version="1.0" encoding="UTF-8"?>
  2  <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.2//EN" "https://www.web3d.org/specifications/x3d-3.2.dtd">
  3  <X3D profile='Immersive' version='3.2 xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.2.xsd'>
  4       <head>
  5            <meta name='titlecontent='Slider.x3d'/>
  6            <meta name='descriptioncontent='X3D Follower example'/>
  7            <meta name='creatorcontent='Herbert Stocker'/>
  8            <meta name='translatorcontent='Don Brutzman'/>
  9            <meta name='createdcontent='18 April 2006'/>
 10            <meta name='translatedcontent='2 December 2011'/>
 11            <meta name='modifiedcontent='2 January 2025'/>
 12            <meta name='referencecontent='originals/test_Sliders.wrl'/>
 13            <meta name='referencecontent='Stocker_06_Followers.pdf'/>
 14            <meta name='referencecontent='http://www.hersto.com/Publications/Followers'/>
 15            <meta name='requirescontent='X3D version 3.2 or greater'/>
 16            <meta name='subjectcontent='X3D Follower Chaser Damper'/>
 17            <meta name=' warning content=' under development '/>
 18            <meta name='referencecontent='https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html'/>
 19            <meta name='identifiercontent='https://www.web3d.org/x3d/content/examples/Basic/Followers/Slider.x3d'/>
 20            <meta name='generatorcontent='Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html'/>
 21            <meta name='generatorcontent='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit'/>
 22            <meta name='licensecontent='../../license.html'/>
 23       </head>
<!--

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

<!-- to top Index for DEF nodes: EFFS, SensKnob, TchPgDown, TchPgUp, Timer, TrKnob, TrStickAbove, TrStickBelow, Worker

Index for ProtoDeclare definitions: EFFS, Slider
-->
 24       <Scene>
 25            <WorldInfo info=' " The original versions of the PROTO Slider was written by me, Herbert Stocker. The original versions and some test and demonstration Worlds can be found at http://www.hersto.de/ . " " You can use and modify the PROTO in this file if you keep the credit information valid and if you do not remove the link to the originating site http://www.hersto.de/ . In brief, keep this WorldInfo node along with the Proto. " " Please send a message to hersto@hersto.de where you describe how you use or improved the nodes. Especially if you included the improved versions. " ' title='Copyright (C) 2002 by Herbert Stocker (AKA hersto)'/>
 26            <ProtoDeclare name='Slider'>
 27                 <ProtoInterface>
 28                      <field name='initial_positiontype='SFFloatvalue='0.5accessType='initializeOnly'/>
 29                      <field name='creditstype='MFStringvalue=' "Initial idea and copyright by Herbert Stocker "http://www.hersto.com/"' accessType='initializeOnly'/>
 30                      <field name='radiusKnobtype='SFFloatvalue='0.3accessType='inputOutput'/>
 31                      <field name='radiusSticktype='SFFloatvalue='0.2accessType='inputOutput'/>
 32                      <field name='silently_set_unfiltered_positiontype='SFFloataccessType='inputOnly'/>
 33                      <field name='mintype='SFFloatvalue='0.0accessType='inputOutput'/>
 34                      <field name='position_changedtype='SFFloataccessType='outputOnly'/>
 35                      <field name='appearancetype='SFNodeaccessType='inputOutput'>
 36                           <Appearance>
 37                                <Material/>
 38                           </Appearance>
 39                      </field>
 40                      <field name='smoothMovementstype='SFBoolvalue='trueaccessType='inputOutput'/>
 41                      <field name='set_positiontype='SFFloataccessType='inputOnly'/>
 42                      <field name='pageSizetype='SFFloatvalue='0.2accessType='inputOutput'/>
 43                      <field name='maxtype='SFFloatvalue='1.0accessType='inputOutput'/>
 44                      <field name='unfiltered_position_changedtype='SFFloataccessType='outputOnly'/>
 45                      <field name='silently_set_positiontype='SFFloataccessType='inputOnly'/>
 46                      <field name='set_unfiltered_positiontype='SFFloataccessType='inputOnly'/>
 47                      <field name='heighttype='SFFloatvalue='2.0accessType='inputOutput'/>
 48                      <field name='positionInt_changedtype='SFInt32accessType='outputOnly'/>
 49                 </ProtoInterface>
 50                 <ProtoBody>
 51                      <Billboard>
 52 
                         <!-- Transform TrStickAbove is a DEF node that has 1 USE node: USE_1 -->
                         <Transform DEF='TrStickAbove'>
 53 
                              <!-- TouchSensor TchPgUp is a DEF node that has 1 USE node: USE_1 -->
                              <TouchSensor DEF='TchPgUpdescription='touch to activate PgUp'/>
 54                                <Shape>
 55                                     <IS>
 56                                          <connect nodeField='appearanceprotoField='appearance'/>
 57                                     </IS>
 58                                     <Cylinder height='1.0'/>
 59                                </Shape>
 60                           </Transform>
 61 
                         <!-- Transform TrStickBelow is a DEF node that has 1 USE node: USE_1 -->
                         <Transform DEF='TrStickBelow'>
 62 
                              <!-- TouchSensor TchPgDown is a DEF node that has 1 USE node: USE_1 -->
                              <TouchSensor DEF='TchPgDowndescription='touch to activate PgDown'/>
 63                                <Shape>
 64                                     <IS>
 65                                          <connect nodeField='appearanceprotoField='appearance'/>
 66                                     </IS>
 67                                     <Cylinder height='1.0'/>
 68                                </Shape>
 69                           </Transform>
 70                           <Group>
 71                                <PlaneSensor DEF='SensKnobautoOffset='falsedescription='touch to activatemaxPosition='0.0 -1.0'/>
 72 
                              <!-- Transform TrKnob is a DEF node that has 1 USE node: USE_1 -->
                              <Transform DEF='TrKnob'>
 73                                     <Shape>
 74                                          <IS>
 75                                               <connect nodeField='appearanceprotoField='appearance'/>
 76                                          </IS>
 77                                          <Cylinder height='1.0'/>
 78                                     </Shape>
 79                                </Transform>
 80                           </Group>
 81                      </Billboard>
 82                      <ProtoDeclare name='EFFS'>
 83                           <ProtoInterface>
 84                                <field name='heighttype='SFFloatvalue='2.0accessType='inputOutput'/>
 85                                <field name='maxtype='SFFloatvalue='1.0accessType='inputOutput'/>
 86                                <field name='radiusKnobtype='SFFloatvalue='0.5accessType='inputOutput'/>
 87                                <field name='pageSizetype='SFFloatvalue='0.2accessType='inputOutput'/>
 88                                <field name='smoothMovementstype='SFBoolvalue='trueaccessType='inputOutput'/>
 89                                <field name='radiusSticktype='SFFloatvalue='0.25accessType='inputOutput'/>
 90                                <field name='mintype='SFFloatvalue='0.0accessType='inputOutput'/>
 91                           </ProtoInterface>
 92                           <ProtoBody>
 93                                <Group/>
 94                           </ProtoBody>
 95                      </ProtoDeclare>
 96 
                    <!-- ProtoInstance EFFS is a DEF node that has 1 USE node: USE_1 -->
                    <ProtoInstance name='EFFSDEF='EFFS'>
 97                           <fieldValue name='maxvalue='1.0'/>
 98                           <fieldValue name='heightvalue='2.0'/>
 99                           <fieldValue name='pageSizevalue='0.2'/>
100                           <fieldValue name='radiusKnobvalue='0.5'/>
101                           <fieldValue name='smoothMovementsvalue='true'/>
102                           <fieldValue name='radiusStickvalue='0.25'/>
103                           <fieldValue name='minvalue='0.0'/>
104                      </ProtoInstance>
105 
                    <!-- TimeSensor Timer is a DEF node that has 1 USE node: USE_1 -->
                    <TimeSensor DEF='Timerloop='true'/>
106                      <Script DEF='WorkerdirectOutput='true'>
107                           <field name='heighttype='SFFloatvalue='2.0accessType='initializeOnly'/>
108                           <field name='set_maxtype='SFFloataccessType='inputOnly'/>
109                           <field name='silenttype='SFBoolvalue='falseaccessType='initializeOnly'/>
110                           <field name='lastTicktype='SFTimevalue='0.0accessType='initializeOnly'/>
111                           <field name='set_pageSizetype='SFFloataccessType='inputOnly'/>
112                           <field name='decPagetype='SFTimeaccessType='inputOnly'/>
113                           <field name='set_radiusSticktype='SFFloataccessType='inputOnly'/>
114                           <field name='set_heighttype='SFFloataccessType='inputOnly'/>
115                           <field name='position_changedtype='SFFloataccessType='outputOnly'/>
116                           <field name='Timertype='SFNodeaccessType='initializeOnly'>
117                                <TimeSensor USE='Timer'/>
118                           </field>
119                           <field name='set_positiontype='SFFloataccessType='inputOnly'/>
120                           <field name='snapTimetype='SFTimevalue='0.0accessType='initializeOnly'/>
121                           <field name='TrStickAbovetype='SFNodeaccessType='initializeOnly'>
122                                <Transform USE='TrStickAbove'/>
123                           </field>
124                           <field name='set_radiusKnobtype='SFFloataccessType='inputOnly'/>
125                           <field name='smoothMovementstype='SFBoolvalue='trueaccessType='initializeOnly'/>
126                           <field name='maxtype='SFFloatvalue='1.0accessType='initializeOnly'/>
127                           <field name='initialUpdatetype='SFBoolvalue='trueaccessType='initializeOnly'/>
128                           <field name='EFFStype='SFNodeaccessType='initializeOnly'>
129                                <ProtoInstance USE='EFFS'/>
130                           </field>
131                           <field name='SensKnobOrigintype='SFFloatvalue='0.0accessType='initializeOnly'/>
132                           <field name='pageSizetype='SFFloatvalue='0.2accessType='initializeOnly'/>
133                           <field name='positionInt_changedtype='SFInt32accessType='outputOnly'/>
134                           <field name='SmoothTau3type='SFFloatvalue='0.05accessType='initializeOnly'/>
135                           <field name='SmoothTau2type='SFFloatvalue='0.05accessType='initializeOnly'/>
136                           <field name='SmoothTau1type='SFFloatvalue='0.05accessType='initializeOnly'/>
137                           <field name='set_mintype='SFFloataccessType='inputOnly'/>
138                           <field name='SensKnob_isActivetype='SFBoolaccessType='inputOnly'/>
139                           <field name='KnobSizetype='SFFloatvalue='0.0accessType='initializeOnly'/>
140                           <field name='silently_set_positiontype='SFFloataccessType='inputOnly'/>
141                           <field name='initialUnfilteredUpdatetype='SFBoolvalue='trueaccessType='initializeOnly'/>
142                           <field name='positionSmo3type='SFFloatvalue='0.0accessType='initializeOnly'/>
143                           <field name='snapToInttype='SFBoolvalue='falseaccessType='initializeOnly'/>
144                           <field name='positionSmo2type='SFFloatvalue='0.0accessType='initializeOnly'/>
145                           <field name='set_unfiltered_positiontype='SFFloataccessType='inputOnly'/>
146                           <field name='positionSmo1type='SFFloatvalue='0.0accessType='initializeOnly'/>
147                           <field name='silently_set_unfiltered_positiontype='SFFloataccessType='inputOnly'/>
148                           <field name='radiusSticktype='SFFloatvalue='0.25accessType='initializeOnly'/>
149                           <field name='KnobCenterPostype='SFFloatvalue='0.0accessType='initializeOnly'/>
150                           <field name='positiontype='SFFloataccessType='initializeOnly'/>
151                           <field name='SensKnob_translationChangedtype='SFVec3faccessType='inputOnly'/>
152                           <field name='radiusKnobtype='SFFloatvalue='0.5accessType='initializeOnly'/>
153                           <field name='TrStickBelowtype='SFNodeaccessType='initializeOnly'>
154                                <Transform USE='TrStickBelow'/>
155                           </field>
156                           <field name='TchPgUptype='SFNodeaccessType='initializeOnly'>
157                                <TouchSensor USE='TchPgUp'/>
158                           </field>
159                           <field name='incPagetype='SFTimeaccessType='inputOnly'/>
160                           <field name='unfiltered_position_changedtype='SFFloataccessType='outputOnly'/>
161                           <field name='Ticktype='SFTimeaccessType='inputOnly'/>
162                           <field name='set_smooothMovementstype='SFBoolaccessType='inputOnly'/>
163                           <field name='mintype='SFFloatvalue='0.0accessType='initializeOnly'/>
164                           <field name='TchPgDowntype='SFNodeaccessType='initializeOnly'>
165                                <TouchSensor USE='TchPgDown'/>
166                           </field>
167                           <field name='TrKnobtype='SFNodeaccessType='initializeOnly'>
168                                <Transform USE='TrKnob'/>
169                           </field>
170                           <IS>
171                                <connect nodeField='position_changedprotoField='position_changed'/>
172                                <connect nodeField='set_positionprotoField='set_position'/>
173                                <connect nodeField='positionInt_changedprotoField='positionInt_changed'/>
174                                <connect nodeField='silently_set_positionprotoField='silently_set_position'/>
175                                <connect nodeField='set_unfiltered_positionprotoField='set_unfiltered_position'/>
176                                <connect nodeField='silently_set_unfiltered_positionprotoField='silently_set_unfiltered_position'/>
177                                <connect nodeField='positionprotoField='initial_position'/>
178                                <connect nodeField='unfiltered_position_changedprotoField='unfiltered_position_changed'/>
179                           </IS>
  <![CDATA[
          
ecmascript:

function initialize()
{            
    positionSmo1= position;
    positionSmo2= position;
    positionSmo3= position;

    min=             EFFS.min;
    max=             EFFS.max;
    pageSize=        EFFS.pageSize;
    height=          EFFS.height;
    radiusKnob=      EFFS.radiusKnob;
    radiusStick=     EFFS.radiusStick;
    smoothMovements= EFFS.smoothMovements;

    // work around the initialization bug in Contact 5.
    if(   Browser.getName() == 'blaxxunCC3D'
       && Browser.getVersion() <= 5.104
       && !position && !min && !max && !pageSize && !height && !radiusKnob && !radiusStick
      )
    {
        position= .5;
        min= 0;
        max= 1;
        pageSize= .2;
        height= 2;
        radiusKnob= .3;
        radiusStick= .2;

        positionSmo1= 
        positionSmo2= 
        positionSmo3=
            position;
    }


    Update();

    Timer.enabled= true; // TBD: Shouldn't we start with false?
}

function set_min(m)           {          min= m;  Update();          }
function set_max(m)           {          max= m;  Update();          }
function set_pageSize(s)      {     pageSize= s;  Update();          }
function set_height(h)        {       height= h;  UpdateGeometry();  }
function set_radiusKnob(r)    {   radiusKnob= r;  UpdateGeometry();  }
function set_radiusStick(r)   {  radiusStick= r;  UpdateGeometry();  }
function set_position(p) 
{ 
    silent= false; 
    snapTime= 0; 
    position= snapToInt? Math.floor(p + .5) : p;
    Update();
}

function set_smooothMovements(s)
{
    smoothMovements= s;
    Update();
}

function silently_set_position(p) 
{ 
    silent= true;
    snapTime= 0;
    position= snapToInt? Math.floor(p + .5) : p;
    Update();        
}

function silently_set_unfiltered_position(p, now)  
{ 
    silent= true; 
    snapTime= 0;
    position= positionSmo1= positionSmo2= positionSmo3= p;
    snapTime= now + .1;
    Update(); 
}

 function set_unfiltered_position(p, now)  
{ 
    snapTime= 0;
    position= positionSmo1= positionSmo2= positionSmo3= p;
    snapTime= now + .1;
    Update(); 
}

function incPage(t, now)
{
    silent= false;
    position+= pageSize;
    snapTime= now + .3;
    Update();
}

function decPage(t, now)
{
    silent= false;
    position-= pageSize;
    snapTime= now + .3;
    Update();
}

function SensKnob_isActive(a, now)
{
    if(a)
    {
        SensKnobOrigin= smoothMovements? positionSmo3 : position;  // TBD: Da stimmt noch was nicht.
        SmoothTau1= .07;
        SmoothTau2= .001;
        SmoothTau3= .001;
//                last_SensKnob_translationChange= SensKnob_translationChanged;
    }else{
        SmoothTau1= .06;
        SmoothTau2= .06;
        SmoothTau3= .06;
        snapTime=   now;
    }
}

function SensKnob_translationChanged(t, now)
{
    silent= false;
//            if(t.subtract(last_SensKnob_translationChange).length() > .0001 )
//            {
        position= SensKnobOrigin + ( height? t.y * (max - min) / (height - KnobSize)
                                           : 0
                                   );
//                snapTime= now + .3;

//                last_SensKnob_translationChange= t;
//            }
    Update();
}

function Update()
{
    UpdateLogic();

    UpdateGeometry();

    if(smoothMovements) 
    {
        setUPC(position);
    }else{
        setUPC(position);
        positionSmo1= position;
        positionSmo2= position;
        positionSmo3= position;
        setPC(position);
    }
}

function UpdateLogic()
{
    if(max < min)
        max= min;

    if(position     > max)    position=     max;
    if(positionSmo1 > max)    positionSmo1= max;
    if(positionSmo2 > max)    positionSmo2= max;
    if(positionSmo3 > max)    positionSmo3= max;

    if(position     < min)    position=     min;
    if(positionSmo1 < min)    positionSmo1= min;
    if(positionSmo2 < min)    positionSmo2= min;
    if(positionSmo3 < min)    positionSmo3= min;
}

function UpdateGeometry()
{
    KnobSize= max - min? pageSize / (max - min) * height
                       : height
                       ;

    KnobCenterPos= max - min? ( ( smoothMovements? positionSmo3
                                                 : position
                                )
                              - (max + min)/2
                              ) / (max - min) * (height - KnobSize)
                            : 0
                            ;

    TrKnob.scale=             new SFVec3f(radiusKnob,   KnobSize,                     radiusKnob);
    TrKnob.translation=       new SFVec3f(0,            KnobCenterPos,                0);

    TrStickAbove.scale=       new SFVec3f(radiusStick,  (height/2 - KnobCenterPos),   radiusStick);
    TrStickAbove.translation= new SFVec3f(0,           (height/2 + KnobCenterPos)/2, 0          );

    TrStickBelow.scale=       new SFVec3f(radiusStick, (KnobCenterPos - -height/2),   radiusStick);
    TrStickBelow.translation= new SFVec3f(0,           (KnobCenterPos + -height/2)/2, 0          );
}

function Tick(now)
{
    if(!lastTick)
    {
        lastTick= now;
return;
    }

    var Delta= now - lastTick;

    if(smoothMovements)  // TBD: The timer should be completely off if !Smoothmovements.
    {
        positionSmo1= position     + (positionSmo1 - position    ) * Math.exp(-Delta/SmoothTau1);
        positionSmo2= positionSmo1 + (positionSmo2 - positionSmo1) * Math.exp(-Delta/SmoothTau2);
        positionSmo3= positionSmo2 + (positionSmo3 - positionSmo2) * Math.exp(-Delta/SmoothTau3);

        UpdateGeometry();

        setPC(positionSmo3);
    }

    if(snapToInt)
        if(snapTime && now >= snapTime)
        {
            var newPos= Math.floor(position + .5);
            SensKnobOrigin+= newPos - position;
            position= newPos;
            snapTime= 0;
        }


    //TBD: Set Timer.enabled

    lastTick= now;
}

function setUPC(value)
{
    if(unfiltered_position_changed != value || initialUnfilteredUpdate)
        if(!silent) unfiltered_position_changed= value;

    initialUnfilteredUpdate= false;
}

function setPC(value)
{
    if(position_changed != value || initialUpdate) 
        if(!silent) position_changed= value;

    if(Math.floor(position_changed + .5) != positionInt_changed || initialUpdate)
        if(!silent) positionInt_changed= Math.floor(position_changed + .5);

    initialUpdate= false;
}

        
]]>
181                      </Script>
182                 </ProtoBody>
183            </ProtoDeclare>
184            <!-- TODO anchor link -->
185       </Scene>
186  </X3D>
<!--

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

<!-- to top Index for DEF nodes: EFFS, SensKnob, TchPgDown, TchPgUp, Timer, TrKnob, TrStickAbove, TrStickBelow, Worker

Index for ProtoDeclare definitions: EFFS, Slider
-->
X3D Tooltips element index: Appearance, Billboard, connect, Cylinder, field, fieldValue, Group, head, IS, Material, meta, PlaneSensor, ProtoBody, ProtoDeclare, ProtoInstance, ProtoInterface, Scene, Script, Shape, TimeSensor, TouchSensor, Transform, WorldInfo, X3D, accessType and type, XML data types, field types

-->
<!-- Online at
https://www.web3d.org/x3d/content/examples/Basic/Followers/SliderIndex.html -->
<!-- Version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/content/examples/Basic/Followers/Slider.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)
    <ProtoInstance name='ProtoName'> <field name='fieldName'/> ProtoInstance> -->

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