#VRML V2.0 utf8 PROTO Shuttle [ exposedField SFBool enabled TRUE field SFFloat rate 1 eventIn SFBool moveRight eventOut SFBool isAtLeft # next line does not work with Cosmo Beta 3 Windoze field MFNode children [ DEF CUBE Box {} ] ] { DEF F Transform { children IS children } DEF T TimeSensor { cycleInterval IS rate enabled IS enabled } DEF S Script { eventIn SFBool enabled IS set_enabled field SFFloat rate IS rate eventIn SFBool moveRight IS moveRight eventIn SFBool isActive eventOut SFBool isAtLeft IS isAtLeft eventOut SFTime start eventOut SFTime stop field SFNode timeSensor USE T url "javascript: // constructor: send initial isAtLeft eventOut function initialize() { isAtLeft = true; } function moveRight(move, ts) { if (move) { // want to start move right start = ts; stop = ts + rate / 2; } else { // want to start move left start = ts - rate / 2; stop = ts + rate / 2; } } function isActive(active) { if (!active) isAtLeft = !moveRight; } function set_enabled(value, ts) { if (value) { // continue from where we left off start = ts - (timeSensor.time - start); stop = ts - (timeSensor.time - stop); } }" } DEF I PositionInterpolator { keys [ 0, 0.5, 1 ] values [ -1 0 0, 1 0 0, -1 0 0 ] } ROUTE T.fraction_changed TO I.set_fraction ROUTE T.isActive TO S.isActive ROUTE I.value_changed TO F.set_translation ROUTE S.start TO T.set_startTime ROUTE S.stop TO T.set_stopTime } PROTO Pendulum [ exposedField SFBool enabled TRUE field SFFloat rate 1 field SFFloat maxAngle eventIn SFBool moveCCW eventOut SFBool isAtCW field MFNode children NULL] { DEF F Transform { children IS children } DEF T TimeSensor { cycleInterval IS rate enabled IS enabled } DEF S Script { eventIn SFBool enabled IS set_enabled field SFFloat rate IS rate field SFFloat maxAngle IS maxAngle eventIn SFBool moveCCW IS moveCCW eventIn SFBool isActive eventOut SFBool isAtCW IS isAtCW eventOut SFTime start eventOut SFTime stop eventOut MFRotation rotation field SFNode timeSensor USE T url "javascript: function initialize() { // constructor:setup interpolator, // send initial isAtCW eventOut isAtCW = true; rot[0] = 0; rot[1] = 1; rot[2] = 0; rot[3] = 0; rotation[0] = rot; rotation[2] = rot; rot[3] = maxAngle; rotation[1] = rot; } function moveCCW(move, ts) { if (move) { // want to start CCW half (0.0 - 0.5) of move start = ts; stop = start + rate / 2; } else { // want to start CW half (0.5 - 1.0) of move start = ts - rate / 2; stop = ts + rate / 2; } } function isActive(active) { if (!active) isAtCW = !moveCCW; } function set_enabled(value, ts) { if (value) { // continue from where we left off start = ts - (timeSensor.time - start); stop = ts - (timeSensor.time - stop); } }" } DEF I OrientationInterpolator { keys [ 0, 0.5, 1 ] } ROUTE T.fraction_changed TO I.set_fraction ROUTE I.value_changed TO F.set_rotation ROUTE T.isActive TO S.isActive ROUTE S.start TO T.set_startTime ROUTE S.stop TO T.set_stopTime ROUTE S.rotation TO I.set_values } DEF Walk Shuttle { enabled FALSE rate 10 children [ DEF Near ProximitySensor { size 10 10 10 } DEF Turn Pendulum { enabled FALSE children [ # The Robot Shape { geometry Box { } # head } Transform { scale 1 5 1 translation 0 -5 0 children [ Shape { geometry Sphere { } } ] # body } DEF Arm Pendulum { maxAngle 0.52 # 30 degrees enabled FALSE children [ Transform { scale 1 7 1 translation 1 -5 0 rotation 1 0 0 4.45 # rotate so swing # centers on Y axis center 0 3.5 0 children [ Shape { geometry Cylinder { } } ] } ] } # duplicate arm on other side and flip so it swings # in opposition Transform { rotation 0 1 0 3.14159 translation 10 0 0 children [ USE Arm ] } ] } ] } # hook up the sentry. The arms will swing infinitely. He walks # along the shuttle path, then turns, then walks back, etc. ROUTE Near.isActive TO Arm.enabled ROUTE Near.isActive TO Walk.enabled ROUTE Arm.isAtCW TO Arm.moveCCW ROUTE Walk.isAtLeft TO Turn.moveCCW ROUTE Turn.isAtCW TO Walk.moveRight