Home

hersto:  Slider.wrl

Source of Slider.wrl:

Here is a link for right-clicking and downloading the file: Slider.wrl (17.3 K Byte),

and below is its content to view online.


#VRML V2.0 utf8

 
WorldInfo
{
    title "Copyright (C) 2002 by Herbert Stocker (AKA hersto)"

    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 don't 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.
"
    ]
}



#
#EXTERNPROTO Slider
#[
#    exposedField SFFloat min                            # 0
#    exposedField SFFloat max                            # 1
#    exposedField SFFloat pageSize                       # .2
#
#    eventIn  SFFloat     set_position
#    field    SFFloat initial_position                   # .5
#    eventOut SFFloat         position_changed 
#    eventOut SFInt32         positionInt_changed
#
#    eventIn  SFFloat            silently_set_position
#    eventIn  SFFloat silently_set_unfiltered_position
#    eventIn  SFFloat          set_unfiltered_position
#    eventOut SFFloat              unfiltered_position_changed
#
#    exposedField SFFloat height                         # 2
#    exposedField SFFloat radiusKnob                     # .3
#    exposedField SFFloat radiusStick                    # .2
#
#    exposedField SFBool smoothMovements                 # TRUE
#
#    exposedField SFNode appearance                      #  Appearance { material Material {} }
#]
#  "Slider.wrl#Slider"
#




PROTO Slider 
[
    exposedField SFFloat min           0
    exposedField SFFloat max           1
    exposedField SFFloat pageSize      .2
#    field        SFBool  snapToInt     FALSE   # not tested, probably doesn't work.

    eventIn  SFFloat     set_position
    field    SFFloat initial_position  .5
    eventOut SFFloat         position_changed 
    eventOut SFInt32         positionInt_changed # TBD: Didn't test this.

    eventIn  SFFloat            silently_set_position   # like set_position, but without updates on position_changed.  To be used if an object is modified by the slider, but also modifies the slider.
    eventIn  SFFloat silently_set_unfiltered_position   
    eventIn  SFFloat          set_unfiltered_position
    eventOut SFFloat              unfiltered_position_changed # like position_changed but without any filtering.       To be used if the receiving object has its own filtering.

    exposedField SFFloat height        2
    exposedField SFFloat radiusKnob    .3
    exposedField SFFloat radiusStick   .2

    exposedField SFBool smoothMovements TRUE

    exposedField SFNode appearance Appearance { material Material {} }



    field MFString credits "Initial idea and copyright by Herbert Stocker, http://www.hersto.com/"
]
{
            
    Billboard
    {
        children
        [
            DEF TrStickAbove Transform 
            {
               children 
               [ 
                   DEF TchPgUp TouchSensor {}
                   
                   Shape
                   {
                       appearance IS appearance

                       geometry Cylinder 
                       { 
                           height 1 
                           radius 1 
                       }
                   }
               ]
            }

            DEF TrStickBelow Transform 
            { 
                children 
                [ 
                    DEF TchPgDown TouchSensor {} 

                    Shape
                    {
                        appearance IS appearance

                        geometry Cylinder 
                        { 
                            height 1 
                            radius 1 
                        } 
                    }
                ] 
            }
            
            Group 
            { 
                children 
                [ 
                    DEF SensKnob PlaneSensor 
                    { 
                        autoOffset FALSE  
                        maxPosition 0 -1 
                    } 

                    DEF TrKnob Transform 
                    {

                        children Shape
                        {
                            appearance IS appearance

                            geometry Cylinder 
                            { 
                                height 1 
                                radius 1 
                            } 
                        }
                    } 
                ] 
            }
           
#            DEF TrLineUp    Transform { children Cone     {  } }
#            DEF TrLineDown  Transform { children Cone     {  } }
        ]
    }


    PROTO EFFS 
    [
        exposedField SFFloat min          0
        exposedField SFFloat max          1
        exposedField SFFloat pageSize     .2
        exposedField SFFloat height       2
        exposedField SFFloat radiusKnob   .5
        exposedField SFFloat radiusStick  .25
        exposedField SFBool  smoothMovements TRUE
    ]
      { Group {} }


    DEF EFFS EFFS
    {
        min          IS min
        max          IS max
        pageSize     IS pageSize
        height       IS height
        radiusKnob   IS radiusKnob
        radiusStick  IS radiusStick 
        smoothMovements IS smoothMovements
    }

    DEF Timer TimeSensor { loop TRUE }

    DEF Worker Script
    {
        directOutput TRUE

        field SFNode EFFS USE EFFS
        field SFFloat min         0        eventIn SFFloat set_min        
        field SFFloat max         1        eventIn SFFloat set_max        
        field SFFloat pageSize    .2       eventIn SFFloat set_pageSize   
		field SFFloat height	  2		   eventIn SFFloat set_height		
        field SFFloat radiusKnob  .5       eventIn SFFloat set_radiusKnob 
        field SFFloat radiusStick .25      eventIn SFFloat set_radiusStick
        field SFBool  smoothMovements TRUE eventIn SFBool  set_smooothMovements
        field SFBool  snapToInt  FALSE # IS snapToInt

        eventIn  SFFloat     set_position            IS     set_position
        field    SFFloat         position            IS initial_position
        field    SFFloat         positionSmo1        0
        field    SFFloat         positionSmo2        0
        field    SFFloat         positionSmo3        0

         
        eventOut SFFloat              position_changed     IS      position_changed
        eventOut SFInt32              positionInt_changed  IS      positionInt_changed
        eventIn  SFFloat silently_set_position             IS      silently_set_position
        eventIn  SFFloat silently_set_unfiltered_position  IS      silently_set_unfiltered_position
        eventIn  SFFloat          set_unfiltered_position  IS      set_unfiltered_position
        eventOut SFFloat   unfiltered_position_changed     IS      unfiltered_position_changed


        field SFNode TrStickAbove  USE TrStickAbove
        field SFNode TrStickBelow  USE TrStickBelow
        field SFNode TrKnob        USE TrKnob
#        field SFNode TrLineUp      USE TrLineUp
#        field SFNode TrLineDown    USE TrLineDown
    
        field SFNode TchPgUp      USE TchPgUp      
        field SFNode TchPgDown    USE TchPgDown
        eventIn SFTime  incPage     
        eventIn SFTime  decPage   


          eventIn SFVec3f SensKnob_translationChanged  
        eventIn SFBool  SensKnob_isActive         

        field SFFloat SensKnobOrigin  0

        field   SFNode Timer        USE Timer 
        eventIn SFTime Tick         
        field   SFTime lastTick     0

        field SFFloat KnobSize      0 
        field SFFloat KnobCenterPos 0


        field SFFloat SmoothTau1     .05
        field SFFloat SmoothTau2     .05
        field SFFloat SmoothTau3     .05

        field SFBool initialUpdate   TRUE         # achieves that            position_changed is sent initially.
        field SFBool initialUnfilteredUpdate TRUE # achieves that unfiltered_position_changed is sent initially.


        field SFBool silent FALSE
        field SFTime snapTime 0

#        field SFVec3f last_SensKnob_translationChange  0 0 0


        url "vrmlscript:

        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;
        }

        "


    }


    ROUTE EFFS.min         TO Worker.set_min
    ROUTE EFFS.max         TO Worker.set_max
    ROUTE EFFS.pageSize    TO Worker.set_pageSize
    ROUTE EFFS.height      TO Worker.set_height
    ROUTE EFFS.radiusKnob  TO Worker.set_radiusKnob
    ROUTE EFFS.radiusStick TO Worker.set_radiusStick
    ROUTE EFFS.smoothMovements TO Worker.set_smooothMovements

    ROUTE TchPgUp.touchTime            TO Worker.incPage
    ROUTE TchPgDown.touchTime          TO Worker.decPage
    ROUTE SensKnob.translation_changed TO Worker.SensKnob_translationChanged          
    ROUTE SensKnob.isActive            TO Worker.SensKnob_isActive
    ROUTE Timer.time TO Worker.Tick


}

     

__.-.__
end of document