#VRML V2.0 utf8
WorldInfo {
  title "Rubic's VRML Cube"
  info "(c) 1998 Michael G. Wagner, all rights reserved"
}
Transform {
  rotation 0 0 1 2.1
  children [
    Transform {
      rotation 1 0 0 0.85
      children [
        Viewpoint {
          position 0 0 12
          description "startcam"
        }
      ]
    }
  ]
}
NavigationInfo {
  headlight TRUE
  speed 1.0
  type ["EXAMINE","ANY"]
}
PROTO arrow [ exposedField SFRotation rotation 0 0 1 0
              exposedField SFVec3f translation 0 0 0 ] {
  Transform {
    translation IS translation
    rotation IS rotation
    children [
      Transform {
        translation 0 0.85 0
        children Shape {
          appearance Appearance {
            material Material {
              diffuseColor 0.8 0.8 0.8
              emissiveColor 0.2 0.2 0.2
            }
          }
          geometry Cone {
            height 0.6
            bottomRadius 0.2
          }
        }
      }
      Transform {
        translation 0 0.3 0
        children Shape {
          appearance Appearance {
            material Material {
              diffuseColor 0.8 0.8 0.8
              emissiveColor 0.2 0.2 0.2
            }
          }
          geometry Cylinder {
            height 0.5
            radius 0.08
          }
        }
      }
    ]
  }
}
PROTO BlueSphere [ exposedField SFColor color 0 0 1 ] {
  Shape {
    appearance Appearance {
      material Material {
        diffuseColor IS color
      }
    }
    geometry Sphere {
      radius 0.2
    }
  }
}
PROTO ClickArrow [ field SFVec3f translation 0 4 0
                   field SFRotation rotation 0 0 1 0
                   field SFColor color 0 0 1
                   exposedField SFBool pEnabled TRUE
                   exposedField SFBool mEnabled TRUE
                   eventOut SFBool pActive
                   eventOut SFBool mActive
                   eventOut SFTime pTouchTime
                   eventOut SFTime mTouchTime ] {
  Transform {
    rotation IS rotation
    children Transform {
      translation IS translation
      children [
        Transform {
          children [
            TouchSensor {
              isActive IS pActive
              enabled IS pEnabled
              touchTime IS pTouchTime
            }
            arrow {}
          ]
        }
        Transform {
          children [
            TouchSensor {
              isActive IS mActive
              enabled IS mEnabled
              touchTime IS mTouchTime
            }
            arrow {
              rotation 0 0 1 3.14
            }
          ]
        }
        BlueSphere {
          color IS color
        }
      ]
    }
  }
}
PROTO RuCube [ exposedField SFVec3f translation 0 0 0
               exposedField SFRotation rotation 0 0 1 0
               field MFInt32 colorIndex [ 0 0 0 0 0 0 ] ] {
  Transform {
    rotation IS rotation
    children Transform {
      translation IS translation
      children Shape {
        geometry IndexedFaceSet {
          convex TRUE
          colorPerVertex FALSE
          coord Coordinate {
            point [
              0.42 0.42 0.42, 0.42 0.42 -0.42, 0.42 -0.42 -0.42, 0.42 -0.42 0.42,
              -0.42 0.42 0.42, -0.42 0.42 -0.42, -0.42 -0.42 -0.42, -0.42 -0.42 0.42
            ]
          }
          coordIndex [
            3 2 1 0 -1
            4 5 6 7 -1
            0 1 5 4 -1
            2 3 7 6 -1
            1 2 6 5 -1
            3 0 4 7 -1
          ]
          color Color {
            color [
              1 0 0, 0 1 1, 0 1 0, 1 0 1, 1 1 0, 0 0 1, 0.5 0.5 0.5
            ]
          }
          colorIndex IS colorIndex
        }
      }
    }
  }
}


Transform {
  #fix examine problem in CP with invisible dummy node
  children [
    DEF SCRAMBLER TouchSensor {}
    Shape {
      appearance Appearance {
        material Material {
          transparency 1
        }
      }
      geometry Box {
        size 2.65 2.65 2.65
      }
    }
  ]
}
Group {
  children [
    DEF CLICK_YP ClickArrow {
      translation 0 4 0
      color 0 1 0
    }
    DEF CLICK_YM ClickArrow {
      translation 0 -4 0
      color 1 0 1
    }
    DEF CLICK_XP ClickArrow {
      translation 0 4 0
      rotation 0 0 1 -1.57
      color 1 0 0
    }
    DEF CLICK_XM ClickArrow {
      translation 0 -4 0
      rotation 0 0 1 -1.57
      color 0 1 1
    }
    DEF CLICK_ZP ClickArrow {
      translation 0 4 0
      rotation 1 0 0 1.57
      color 0 0 1
    }
    DEF CLICK_ZM ClickArrow {
      translation 0 -4 0
      rotation 1 0 0 1.57
      color 1 1 0
    }
    DEF VERT0 RuCube {
      translation 0.9 0.9 0.9
      colorIndex [ 0 6 2 6 6 5 ]
    }
    DEF VERT1 RuCube {
      translation -0.9 -0.9 -0.9
      colorIndex [ 6 1 6 3 4 6 ]
    }
    DEF VERT2 RuCube {
      translation 0.9 0.9 -0.9
      colorIndex [ 0 6 2 6 4 6 ]
    }
    DEF VERT3 RuCube {
      translation -0.9 -0.9 0.9
      colorIndex [ 6 1 6 3 6 5 ]
    }
    DEF VERT4 RuCube {
      translation 0.9 -0.9 0.9
      colorIndex [ 0 6 6 3 6 5 ]
    }
    DEF VERT5 RuCube {
      translation -0.9 0.9 -0.9
      colorIndex [ 6 1 2 6 4 6 ]
    }
    DEF VERT6 RuCube {
      translation -0.9 0.9 0.9
      colorIndex [ 6 1 2 6 6 5 ]
    }
    DEF VERT7 RuCube {
      translation 0.9 -0.9 -0.9
      colorIndex [ 0 6 6 3 4 6 ]
    }
    DEF FACE0 RuCube {
      translation 0.9 0 0
      colorIndex [ 0 6 6 6 6 6 ]
    }
    DEF FACE1 RuCube {
      translation 0 0.9 0
      colorIndex [ 6 6 2 6 6 6 ]
    }
    DEF FACE2 RuCube {
      translation 0 0 0.9
      colorIndex [ 6 6 6 6 6 5 ]
    }
    DEF FACE3 RuCube {
      translation 0 0 -0.9
      colorIndex [ 6 6 6 6 4 6 ]
    }
    DEF FACE4 RuCube {
      translation 0 -0.9 0
      colorIndex [ 6 6 6 3 6 6 ]
    }
    DEF FACE5 RuCube {
      translation -0.9 0 0
      colorIndex [ 6 1 6 6 6 6 ]
    }
    DEF EDGE0 RuCube {
      translation 0.9 0 -0.9
      colorIndex [ 0 6 6 6 4 6 ]
    }
    DEF EDGE1 RuCube {
      translation 0 0.9 -0.9
      colorIndex [ 6 6 2 6 4 6 ]
    }
    DEF EDGE2 RuCube {
      translation -0.9 0 -0.9
      colorIndex [ 6 1 6 6 4 6 ]
    }
    DEF EDGE3 RuCube {
      translation 0 -0.9 -0.9
      colorIndex [ 6 6 6 3 4 6 ]
    }
    DEF EDGE4 RuCube {
      translation 0.9 0.9 0
      colorIndex [ 0 6 2 6 6 6 ]
    }
    DEF EDGE5 RuCube {
      translation -0.9 0.9 0
      colorIndex [ 6 1 2 6 6 6 ]
    }
    DEF EDGE6 RuCube {
      translation -0.9 -0.9 0
      colorIndex [ 6 1 6 3 6 6 ]
    }
    DEF EDGE7 RuCube {
      translation 0.9 -0.9 0
      colorIndex [ 0 6 6 3 6 6 ]
    }
    DEF EDGE8 RuCube {
      translation 0.9 0 0.9
      colorIndex [ 0 6 6 6 6 5 ]
    }
    DEF EDGE9 RuCube {
      translation 0 0.9 0.9
      colorIndex [ 6 6 2 6 6 5 ]
    }
    DEF EDGE10 RuCube {
      translation -0.9 0 0.9
      colorIndex [ 6 1 6 6 6 5 ]
    }
    DEF EDGE11 RuCube {
      translation 0 -0.9 0.9
      colorIndex [ 6 6 6 3 6 5 ]
    }
  ]
}
DEF TIMER TimeSensor {
  cycleInterval 1.2
}
DEF SCRAMBLETIMER TimeSensor {
  cycleInterval 6
}
DEF MOVER Script {
  field MFRotation pos [0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0,
                        0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0]
  field MFRotation curpos [0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0,
                           0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0]
  field MFRotation e_pos [0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0,
                          0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0,
                          0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0]
  field MFRotation e_curpos [0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0,
                             0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0,
                             0 0 1 0, 0 0 1 0, 0 0 1 0, 0 0 1 0]
  field MFInt32 oncubeind [2, 5, 1, 7, 0, 6, 3, 4]
  field MFInt32 e_oncubeind [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
  field SFInt32 rotind 0
  field SFFloat rotori 1
  field SFVec3f rotdir 0 0 1
  field SFInt32 scrambleIndex 0
  field SFInt32 oldDir 6

  eventIn SFBool set_rotxpp
  eventIn SFBool set_rotxpm
  eventIn SFBool set_rotxmp
  eventIn SFBool set_rotxmm
  eventIn SFBool set_rotypp
  eventIn SFBool set_rotypm
  eventIn SFBool set_rotymp
  eventIn SFBool set_rotymm
  eventIn SFBool set_rotzpp
  eventIn SFBool set_rotzpm
  eventIn SFBool set_rotzmp
  eventIn SFBool set_rotzmm
  eventIn SFBool set_scramble
  eventOut SFBool allowSensorXpp
  eventOut SFBool allowSensorXpm
  eventOut SFBool allowSensorXmp
  eventOut SFBool allowSensorXmm
  eventOut SFBool allowSensorYpp
  eventOut SFBool allowSensorYpm
  eventOut SFBool allowSensorYmp
  eventOut SFBool allowSensorYmm
  eventOut SFBool allowSensorZpp
  eventOut SFBool allowSensorZpm
  eventOut SFBool allowSensorZmp
  eventOut SFBool allowSensorZmm
  eventOut SFBool allowScrambleSensor
  eventIn SFFloat set_fraction
  eventIn SFFloat set_scrambleFraction
  eventOut SFRotation rot0_changed
  eventOut SFRotation rot1_changed
  eventOut SFRotation rot2_changed
  eventOut SFRotation rot3_changed
  eventOut SFRotation rot4_changed
  eventOut SFRotation rot5_changed
  eventOut SFRotation rot6_changed
  eventOut SFRotation rot7_changed
  eventOut SFRotation face0_rot_changed
  eventOut SFRotation face1_rot_changed
  eventOut SFRotation face2_rot_changed
  eventOut SFRotation face3_rot_changed
  eventOut SFRotation face4_rot_changed
  eventOut SFRotation face5_rot_changed
  eventOut SFRotation edge0_rot_changed
  eventOut SFRotation edge1_rot_changed
  eventOut SFRotation edge2_rot_changed
  eventOut SFRotation edge3_rot_changed
  eventOut SFRotation edge4_rot_changed
  eventOut SFRotation edge5_rot_changed
  eventOut SFRotation edge6_rot_changed
  eventOut SFRotation edge7_rot_changed
  eventOut SFRotation edge8_rot_changed
  eventOut SFRotation edge9_rot_changed
  eventOut SFRotation edge10_rot_changed
  eventOut SFRotation edge11_rot_changed
  eventIn SFBool finish

  url "vrmlscript:
    function changeRotation(ind) {
      if(ind==0)
        rot0_changed=curpos[0];
      if(ind==1)
        rot1_changed=curpos[1];
      if(ind==2)
        rot2_changed=curpos[2];
      if(ind==3)
        rot3_changed=curpos[3];
      if(ind==4)
        rot4_changed=curpos[4];
      if(ind==5)
        rot5_changed=curpos[5];
      if(ind==6)
        rot6_changed=curpos[6];
      if(ind==7)
        rot7_changed=curpos[7];
    }
    function changeEdgeRotation(ind) {
      if(ind==0)
        edge0_rot_changed=e_curpos[0];
      if(ind==1)
        edge1_rot_changed=e_curpos[1];
      if(ind==2)
        edge2_rot_changed=e_curpos[2];
      if(ind==3)
        edge3_rot_changed=e_curpos[3];
      if(ind==4)
        edge4_rot_changed=e_curpos[4];
      if(ind==5)
        edge5_rot_changed=e_curpos[5];
      if(ind==6)
        edge6_rot_changed=e_curpos[6];
      if(ind==7)
        edge7_rot_changed=e_curpos[7];
      if(ind==8)
        edge8_rot_changed=e_curpos[8];
      if(ind==9)
        edge9_rot_changed=e_curpos[9];
      if(ind==10)
        edge10_rot_changed=e_curpos[10];
      if(ind==11)
        edge11_rot_changed=e_curpos[11];
    }
    function disableSensors(ind) {
      if(ind!=0)
        allowSensorXpp=FALSE;
      if(ind!=1)
        allowSensorXpm=FALSE;
      if(ind!=2)
        allowSensorXmp=FALSE;
      if(ind!=3)
        allowSensorXmm=FALSE;
      if(ind!=4)
        allowSensorYpp=FALSE;
      if(ind!=5)
        allowSensorYpm=FALSE;
      if(ind!=6)
        allowSensorYmp=FALSE;
      if(ind!=7)
        allowSensorYmm=FALSE;
      if(ind!=8)
        allowSensorZpp=FALSE;
      if(ind!=9)
        allowSensorZpm=FALSE;
      if(ind!=10)
        allowSensorZmp=FALSE;
      if(ind!=11)
        allowSensorZmm=FALSE;
      allowScrambleSensor=FALSE;
    }
    function toQuaternion(rot) {
      s=Math.sin(rot[3]/2);
      return new MFFloat(rot[0]*s,rot[1]*s,rot[2]*s,Math.cos(rot[3]/2));
    }           
    function fromQuaternion(rot) {
      s=Math.sqrt(rot[0]*rot[0]+rot[1]*rot[1]+rot[2]*rot[2]);
      if(s<0.01) {
        return new SFRotation(1,0,0,0);
      } else {
        return new SFRotation(rot[0]/s,rot[1]/s,rot[2]/s,2*Math.acos(rot[3]));
      }
    }           
    function multiply(a,b) {
      return new MFFloat(a[3]*b[0]+a[0]*b[3]+a[1]*b[2]-a[2]*b[1],
                         a[3]*b[1]+a[1]*b[3]+a[2]*b[0]-a[0]*b[2],
                         a[3]*b[2]+a[2]*b[3]+a[0]*b[1]-a[1]*b[0],
                         a[3]*b[3]-a[0]*b[0]-a[1]*b[1]-a[2]*b[2]);
    }           
    function getCurrot(time,cubeind) {
      rot=toQuaternion(pos[cubeind]);
      rot0=new MFFloat(rot[0],rot[1],rot[2],rot[3]);
      // ! rot0=toQuaternion(pos[cubeind]); doesn't work on CP 1.0.2/IRIX !
      rot=toQuaternion(new SFRotation(rotdir,time*rotori*Math.PI/2));
      curpos[cubeind]=fromQuaternion(multiply(rot,rot0));
      changeRotation(cubeind);
    }
    function getLastCurrot(time,cubeind) {
      getCurrot(time,cubeind);
      pos[cubeind]=curpos[cubeind];
    }
    function getEdgeCurrot(time,cubeind) {
      rot=toQuaternion(e_pos[cubeind]);
      rot0=new MFFloat(rot[0],rot[1],rot[2],rot[3]);
      // ! rot0=toQuaternion(e_pos[cubeind]); doesn't work on CP 1.0.2/IRIX !
      rot=toQuaternion(new SFRotation(rotdir,time*rotori*Math.PI/2));
      e_curpos[cubeind]=fromQuaternion(multiply(rot,rot0));
      changeEdgeRotation(cubeind);
    }
    function getLastEdgeCurrot(time,cubeind) {
      getEdgeCurrot(time,cubeind);
      e_pos[cubeind]=e_curpos[cubeind];
    }
    function calcRotation(time) {
      if(rotind==0) {
        getCurrot(time,oncubeind[0]);
        getCurrot(time,oncubeind[3]);
        getCurrot(time,oncubeind[4]);
        getCurrot(time,oncubeind[7]);
        face0_rot_changed=new SFRotation(rotdir,time*rotori*Math.PI/2);
        getEdgeCurrot(time,e_oncubeind[0]);
        getEdgeCurrot(time,e_oncubeind[4]);
        getEdgeCurrot(time,e_oncubeind[7]);
        getEdgeCurrot(time,e_oncubeind[8]);
      }
      if(rotind==1) {
        getCurrot(time,oncubeind[0]);
        getCurrot(time,oncubeind[1]);
        getCurrot(time,oncubeind[4]);
        getCurrot(time,oncubeind[5]);
        face1_rot_changed=new SFRotation(rotdir,time*rotori*Math.PI/2);
        getEdgeCurrot(time,e_oncubeind[1]);
        getEdgeCurrot(time,e_oncubeind[4]);
        getEdgeCurrot(time,e_oncubeind[5]);
        getEdgeCurrot(time,e_oncubeind[9]);
      }
      if(rotind==5) {
        getCurrot(time,oncubeind[1]);
        getCurrot(time,oncubeind[2]);
        getCurrot(time,oncubeind[5]);
        getCurrot(time,oncubeind[6]);
        face5_rot_changed=new SFRotation(rotdir,time*rotori*Math.PI/2);
        getEdgeCurrot(time,e_oncubeind[2]);
        getEdgeCurrot(time,e_oncubeind[5]);
        getEdgeCurrot(time,e_oncubeind[6]);
        getEdgeCurrot(time,e_oncubeind[10]);
      }
      if(rotind==4) {
        getCurrot(time,oncubeind[2]);
        getCurrot(time,oncubeind[3]);
        getCurrot(time,oncubeind[6]);
        getCurrot(time,oncubeind[7]);
        face4_rot_changed=new SFRotation(rotdir,time*rotori*Math.PI/2);
        getEdgeCurrot(time,e_oncubeind[3]);
        getEdgeCurrot(time,e_oncubeind[6]);
        getEdgeCurrot(time,e_oncubeind[7]);
        getEdgeCurrot(time,e_oncubeind[11]);
      }
      if(rotind==2) {
        getCurrot(time,oncubeind[4]);
        getCurrot(time,oncubeind[5]);
        getCurrot(time,oncubeind[6]);
        getCurrot(time,oncubeind[7]);
        face2_rot_changed=new SFRotation(rotdir,time*rotori*Math.PI/2);
        getEdgeCurrot(time,e_oncubeind[8]);
        getEdgeCurrot(time,e_oncubeind[9]);
        getEdgeCurrot(time,e_oncubeind[10]);
        getEdgeCurrot(time,e_oncubeind[11]);
      }
      if(rotind==3) {
        getCurrot(time,oncubeind[0]);
        getCurrot(time,oncubeind[1]);
        getCurrot(time,oncubeind[2]);
        getCurrot(time,oncubeind[3]);
        face3_rot_changed=new SFRotation(rotdir,time*rotori*Math.PI/2);
        getEdgeCurrot(time,e_oncubeind[0]);
        getEdgeCurrot(time,e_oncubeind[1]);
        getEdgeCurrot(time,e_oncubeind[2]);
        getEdgeCurrot(time,e_oncubeind[3]);
      }
    }
    function calcLastRotation() {
      if(rotind==0) {
        getLastCurrot(1.0,oncubeind[0]);
        getLastCurrot(1.0,oncubeind[3]);
        getLastCurrot(1.0,oncubeind[4]);
        getLastCurrot(1.0,oncubeind[7]);
        face0_rot_changed=new SFRotation(0,0,1,0);
        getLastEdgeCurrot(1.0,e_oncubeind[0]);
        getLastEdgeCurrot(1.0,e_oncubeind[4]);
        getLastEdgeCurrot(1.0,e_oncubeind[7]);
        getLastEdgeCurrot(1.0,e_oncubeind[8]);
      }
      if(rotind==1) {
        getLastCurrot(1.0,oncubeind[0]);
        getLastCurrot(1.0,oncubeind[1]);
        getLastCurrot(1.0,oncubeind[4]);
        getLastCurrot(1.0,oncubeind[5]);
        face1_rot_changed=new SFRotation(0,0,1,0);
        getLastEdgeCurrot(1.0,e_oncubeind[1]);
        getLastEdgeCurrot(1.0,e_oncubeind[4]);
        getLastEdgeCurrot(1.0,e_oncubeind[5]);
        getLastEdgeCurrot(1.0,e_oncubeind[9]);
      }
      if(rotind==5) {
        getLastCurrot(1.0,oncubeind[1]);
        getLastCurrot(1.0,oncubeind[2]);
        getLastCurrot(1.0,oncubeind[5]);
        getLastCurrot(1.0,oncubeind[6]);
        face5_rot_changed=new SFRotation(0,0,1,0);
        getLastEdgeCurrot(1.0,e_oncubeind[2]);
        getLastEdgeCurrot(1.0,e_oncubeind[5]);
        getLastEdgeCurrot(1.0,e_oncubeind[6]);
        getLastEdgeCurrot(1.0,e_oncubeind[10]);
      }
      if(rotind==4) {
        getLastCurrot(1.0,oncubeind[2]);
        getLastCurrot(1.0,oncubeind[3]);
        getLastCurrot(1.0,oncubeind[6]);
        getLastCurrot(1.0,oncubeind[7]);
        face4_rot_changed=new SFRotation(0,0,1,0);
        getLastEdgeCurrot(1.0,e_oncubeind[3]);
        getLastEdgeCurrot(1.0,e_oncubeind[6]);
        getLastEdgeCurrot(1.0,e_oncubeind[7]);
        getLastEdgeCurrot(1.0,e_oncubeind[11]);
      }
      if(rotind==2) {
        getLastCurrot(1.0,oncubeind[4]);
        getLastCurrot(1.0,oncubeind[5]);
        getLastCurrot(1.0,oncubeind[6]);
        getLastCurrot(1.0,oncubeind[7]);
        face2_rot_changed=new SFRotation(0,0,1,0);
        getLastEdgeCurrot(1.0,e_oncubeind[8]);
        getLastEdgeCurrot(1.0,e_oncubeind[9]);
        getLastEdgeCurrot(1.0,e_oncubeind[10]);
        getLastEdgeCurrot(1.0,e_oncubeind[11]);
      }
      if(rotind==3) {
        getLastCurrot(1.0,oncubeind[0]);
        getLastCurrot(1.0,oncubeind[1]);
        getLastCurrot(1.0,oncubeind[2]);
        getLastCurrot(1.0,oncubeind[3]);
        face3_rot_changed=new SFRotation(0,0,1,0);
        getLastEdgeCurrot(1.0,e_oncubeind[0]);
        getLastEdgeCurrot(1.0,e_oncubeind[1]);
        getLastEdgeCurrot(1.0,e_oncubeind[2]);
        getLastEdgeCurrot(1.0,e_oncubeind[3]);
      }
    }
    function set_rotxpp(value) {
      if(value==TRUE) {
        rotind=0;
        rotori=1;
        rotdir=new SFVec3f(1,0,0);
        disableSensors(0);
      }
    }
    function set_rotxpm(value) {
      if(value==TRUE) {
        rotind=0;
        rotori=-1;
        rotdir=new SFVec3f(1,0,0);
        disableSensors(1);
      }
    }
    function set_rotxmp(value) {
      if(value==TRUE) {
        rotind=5;
        rotori=1;
        rotdir=new SFVec3f(1,0,0);
        disableSensors(2);
      }
    }
    function set_rotxmm(value) {
      if(value==TRUE) {
        rotind=5;
        rotori=-1;
        rotdir=new SFVec3f(1,0,0);
        disableSensors(3);
      }
    }
    function set_rotypp(value) {
      if(value==TRUE) {
        rotind=1;
        rotori=1;
        rotdir=new SFVec3f(0,1,0);
        disableSensors(4);
      }
    }
    function set_rotypm(value) {
      if(value==TRUE) {
        rotind=1;
        rotori=-1;
        rotdir=new SFVec3f(0,1,0);
        disableSensors(5);
      }
    }
    function set_rotymp(value) {
      if(value==TRUE) {
        rotind=4;
        rotori=1;
        rotdir=new SFVec3f(0,1,0);
        disableSensors(6);
     }
    }
    function set_rotymm(value) {
      if(value==TRUE) {
        rotind=4;
        rotori=-1;
        rotdir=new SFVec3f(0,1,0);
        disableSensors(7);
      }
    }
    function set_rotzpp(value) {
      if(value==TRUE) {
        rotind=2;
        rotori=1;
        rotdir=new SFVec3f(0,0,1);
        disableSensors(8);
      }
    }
    function set_rotzpm(value) {
      if(value==TRUE) {
        rotind=2;
        rotori=-1;
        rotdir=new SFVec3f(0,0,1);
        disableSensors(9);
      }
    }
    function set_rotzmp(value) {
      if(value==TRUE) {
        rotind=3;
        rotori=1;
        rotdir=new SFVec3f(0,0,1);
        disableSensors(10);
      }
    }
    function set_rotzmm(value) {
      if(value==TRUE) {
        rotind=3;
        rotori=-1;
        rotdir=new SFVec3f(0,0,1);
        disableSensors(11);
      }
    }
    function switchOnCubeInd() {
      if(rotind==0) {
        puf=oncubeind[0];
        oncubeind[0]=oncubeind[3];
        oncubeind[3]=oncubeind[7];
        oncubeind[7]=oncubeind[4];
        oncubeind[4]=puf;
        puf=e_oncubeind[0];
        e_oncubeind[0]=e_oncubeind[7];
        e_oncubeind[7]=e_oncubeind[8];
        e_oncubeind[8]=e_oncubeind[4];
        e_oncubeind[4]=puf;
      }
      if(rotind==1) {
        puf=oncubeind[0];
        oncubeind[0]=oncubeind[4];
        oncubeind[4]=oncubeind[5];
        oncubeind[5]=oncubeind[1];
        oncubeind[1]=puf;
        puf=e_oncubeind[1];
        e_oncubeind[1]=e_oncubeind[4];
        e_oncubeind[4]=e_oncubeind[9];
        e_oncubeind[9]=e_oncubeind[5];
        e_oncubeind[5]=puf;
      }
      if(rotind==2) {
        puf=oncubeind[4];
        oncubeind[4]=oncubeind[7];
        oncubeind[7]=oncubeind[6];
        oncubeind[6]=oncubeind[5];
        oncubeind[5]=puf;
        puf=e_oncubeind[8];
        e_oncubeind[8]=e_oncubeind[11];
        e_oncubeind[11]=e_oncubeind[10];
        e_oncubeind[10]=e_oncubeind[9];
        e_oncubeind[9]=puf;
      }
      if(rotind==3) {
        puf=oncubeind[0];
        oncubeind[0]=oncubeind[3];
        oncubeind[3]=oncubeind[2];
        oncubeind[2]=oncubeind[1];
        oncubeind[1]=puf;
        puf=e_oncubeind[0];
        e_oncubeind[0]=e_oncubeind[3];
        e_oncubeind[3]=e_oncubeind[2];
        e_oncubeind[2]=e_oncubeind[1];
        e_oncubeind[1]=puf;
      }
      if(rotind==4) {
        puf=oncubeind[3];
        oncubeind[3]=oncubeind[7];
        oncubeind[7]=oncubeind[6];
        oncubeind[6]=oncubeind[2];
        oncubeind[2]=puf;
        puf=e_oncubeind[3];
        e_oncubeind[3]=e_oncubeind[7];
        e_oncubeind[7]=e_oncubeind[11];
        e_oncubeind[11]=e_oncubeind[6];
        e_oncubeind[6]=puf;
      }
      if(rotind==5) {
        puf=oncubeind[1];
        oncubeind[1]=oncubeind[2];
        oncubeind[2]=oncubeind[6];
        oncubeind[6]=oncubeind[5];
        oncubeind[5]=puf;
        puf=e_oncubeind[2];
        e_oncubeind[2]=e_oncubeind[6];
        e_oncubeind[6]=e_oncubeind[10];
        e_oncubeind[10]=e_oncubeind[5];
        e_oncubeind[5]=puf;
      }
    }
    function allowSensors() {
      allowSensorXpp=TRUE;
      allowSensorXpm=TRUE;
      allowSensorXmp=TRUE;
      allowSensorXmm=TRUE;
      allowSensorYpp=TRUE;
      allowSensorYpm=TRUE;
      allowSensorYmp=TRUE;
      allowSensorYmm=TRUE;
      allowSensorZpp=TRUE;
      allowSensorZpm=TRUE;
      allowSensorZmp=TRUE;
      allowSensorZmm=TRUE;
      allowScrambleSensor=TRUE;
    }
    function reset() {
      calcLastRotation();
      switchOnCubeInd();
      if(rotori<0) {
        switchOnCubeInd();
        switchOnCubeInd();
      }
    }
    function finish(value) {
      if(value==FALSE) {
        allowSensors();
        reset();
      }
    }
    function set_fraction(value) {
      calcRotation(value);
    }
    function chooseRotation() {
      dir=Math.floor(5.99*Math.random());
      while(oldDir==dir)
        dir=Math.floor(5.99*Math.random());
      oldDir=dir;
      ori=Math.floor(1.99*Math.random());
      if(dir==0) {
        if(ori==0)
          set_rotxpp(TRUE);
        else
          set_rotxpm(TRUE);
      }
      if(dir==1) {
        if(ori==0)
          set_rotypp(TRUE);
        else
          set_rotypm(TRUE);
      }
      if(dir==2) {
        if(ori==0)
          set_rotzpp(TRUE);
        else
          set_rotzpm(TRUE);
      }
      if(dir==3) {
        if(ori==0)
          set_rotxmp(TRUE);
        else
          set_rotxmm(TRUE);
      }
      if(dir==4) {
        if(ori==0)
          set_rotymp(TRUE);
        else
          set_rotymm(TRUE);
      }
      if(dir==5) {
        if(ori==0)
          set_rotzmp(TRUE);
        else
          set_rotzmm(TRUE);
      }
    }
    function set_scrambleFraction(value) {
      t=5*value-scrambleIndex;
      if(t>1) {
        scrambleIndex++;
        reset();
        chooseRotation();
      } else
        calcRotation(t);
    }
    function set_scramble(value) {
      if(value==TRUE) {
        chooseRotation();
        disableSensors(12);
      } else {
        scrambleIndex=0;
        reset();
        allowSensors();
      }
    }
  "
}

ROUTE MOVER.allowSensorXpp TO CLICK_XP.set_pEnabled
ROUTE MOVER.allowSensorXpm TO CLICK_XP.set_mEnabled
ROUTE MOVER.allowSensorXmp TO CLICK_XM.set_pEnabled
ROUTE MOVER.allowSensorXmm TO CLICK_XM.set_mEnabled
ROUTE MOVER.allowSensorYpp TO CLICK_YP.set_pEnabled
ROUTE MOVER.allowSensorYpm TO CLICK_YP.set_mEnabled
ROUTE MOVER.allowSensorYmp TO CLICK_YM.set_pEnabled
ROUTE MOVER.allowSensorYmm TO CLICK_YM.set_mEnabled
ROUTE MOVER.allowSensorZpp TO CLICK_ZP.set_pEnabled
ROUTE MOVER.allowSensorZpm TO CLICK_ZP.set_mEnabled
ROUTE MOVER.allowSensorZmp TO CLICK_ZM.set_pEnabled
ROUTE MOVER.allowSensorZmm TO CLICK_ZM.set_mEnabled
ROUTE MOVER.allowScrambleSensor TO SCRAMBLER.set_enabled
ROUTE CLICK_XP.pTouchTime TO TIMER.startTime
ROUTE CLICK_XP.mTouchTime TO TIMER.startTime
ROUTE CLICK_XM.pTouchTime TO TIMER.startTime
ROUTE CLICK_XM.mTouchTime TO TIMER.startTime
ROUTE CLICK_YP.pTouchTime TO TIMER.startTime
ROUTE CLICK_YP.mTouchTime TO TIMER.startTime
ROUTE CLICK_YM.pTouchTime TO TIMER.startTime
ROUTE CLICK_YM.mTouchTime TO TIMER.startTime
ROUTE CLICK_ZP.pTouchTime TO TIMER.startTime
ROUTE CLICK_ZP.mTouchTime TO TIMER.startTime
ROUTE CLICK_ZM.pTouchTime TO TIMER.startTime
ROUTE CLICK_ZM.mTouchTime TO TIMER.startTime
ROUTE SCRAMBLER.touchTime TO SCRAMBLETIMER.startTime
ROUTE CLICK_XP.pActive TO MOVER.set_rotxpp
ROUTE CLICK_XP.mActive TO MOVER.set_rotxpm
ROUTE CLICK_XM.pActive TO MOVER.set_rotxmp
ROUTE CLICK_XM.mActive TO MOVER.set_rotxmm
ROUTE CLICK_YP.pActive TO MOVER.set_rotypp
ROUTE CLICK_YP.mActive TO MOVER.set_rotypm
ROUTE CLICK_YM.pActive TO MOVER.set_rotymp
ROUTE CLICK_YM.mActive TO MOVER.set_rotymm
ROUTE CLICK_ZP.pActive TO MOVER.set_rotzpp
ROUTE CLICK_ZP.mActive TO MOVER.set_rotzpm
ROUTE CLICK_ZM.pActive TO MOVER.set_rotzmp
ROUTE CLICK_ZM.mActive TO MOVER.set_rotzmm
ROUTE SCRAMBLETIMER.fraction_changed TO MOVER.set_scrambleFraction
ROUTE SCRAMBLETIMER.isActive TO MOVER.set_scramble
ROUTE TIMER.fraction_changed TO MOVER.set_fraction
ROUTE TIMER.isActive TO MOVER.finish
ROUTE MOVER.rot0_changed TO VERT0.set_rotation
ROUTE MOVER.rot1_changed TO VERT1.set_rotation
ROUTE MOVER.rot2_changed TO VERT2.set_rotation
ROUTE MOVER.rot3_changed TO VERT3.set_rotation
ROUTE MOVER.rot4_changed TO VERT4.set_rotation
ROUTE MOVER.rot5_changed TO VERT5.set_rotation
ROUTE MOVER.rot6_changed TO VERT6.set_rotation
ROUTE MOVER.rot7_changed TO VERT7.set_rotation
ROUTE MOVER.face0_rot_changed TO FACE0.set_rotation
ROUTE MOVER.face1_rot_changed TO FACE1.set_rotation
ROUTE MOVER.face2_rot_changed TO FACE2.set_rotation
ROUTE MOVER.face3_rot_changed TO FACE3.set_rotation
ROUTE MOVER.face4_rot_changed TO FACE4.set_rotation
ROUTE MOVER.face5_rot_changed TO FACE5.set_rotation
ROUTE MOVER.edge0_rot_changed TO EDGE0.set_rotation
ROUTE MOVER.edge1_rot_changed TO EDGE1.set_rotation
ROUTE MOVER.edge2_rot_changed TO EDGE2.set_rotation
ROUTE MOVER.edge3_rot_changed TO EDGE3.set_rotation
ROUTE MOVER.edge4_rot_changed TO EDGE4.set_rotation
ROUTE MOVER.edge5_rot_changed TO EDGE5.set_rotation
ROUTE MOVER.edge6_rot_changed TO EDGE6.set_rotation
ROUTE MOVER.edge7_rot_changed TO EDGE7.set_rotation
ROUTE MOVER.edge8_rot_changed TO EDGE8.set_rotation
ROUTE MOVER.edge9_rot_changed TO EDGE9.set_rotation
ROUTE MOVER.edge10_rot_changed TO EDGE10.set_rotation
ROUTE MOVER.edge11_rot_changed TO EDGE11.set_rotation