4c4 < --- > 17c17 <

This document can be found at http://reality.sgi.com/employees/gavin/vrml/Newbehaviors.html. It was last updated on November 24, 1995.

--- >

This document can be found at http://reality.sgi.com/employees/gavin/vrml/Behaviors.Dec1.html. It was last updated on Dec. 1, 1995.

101c101 < received. For example, the Transform node may receive "translation" events --- > received. For example, the Transform node may receive "setTranslation" events 103,105c103,107 < "rotation", "scaleFactor", ... events).

<

In my opinion, some fields should not be allowed to change after file-read; < for many browsers, allowing things like the fields of IndexedFaceSet or ShapeHints to change over time will just be too hard to implement.

--- > "setRotation", "setScaleFactor", ...etc events).

>

In Gavin's opinion, some fields should not be allowed to change after file-read; for > many browsers, allowing things like the fields of IndexedFaceSet or ShapeHints > to change over time will be hard to implement (perhaps IndexedFaceSets are tesselated into triangles at file-read time, > or normals calculated based on the creaseAngle of ShapeHints, or...).

117a120,121 >

Routes are not nodes; ROUTE is merely a syntactic construct for establishing > event paths between nodes.

120c124,130 < read-in is covered below in the section discussing how scripts should be allowed to edit the scene.

--- > read-in is covered below in the section discussing how scripts should be allowed to edit the scene.

>

Issue: Should you be allowed to ROUTE inputs to inputs as a way of 'slaving' > inputs, so I'm connected to whatever is connected to something else? Gavin > thought that was a good idea but changed his mind, because there are some > nasty cases, like:
> ROUTE foo.in -> bar.in
> ROUTE bar.in -> foo.in # Uh-oh, what does this do...

175,182c185,192 <

We're making distinctions between fields, which can be given an initial value but cannot be changed except by the node that < they're contained in, and events, which (at least for the built-in nodes) < are requests to change fields. So, if we want our TwoColorChair to have < colors that can be changed, we'd need to expose the leg.diffuseColor 'eventIn' < and seat.diffuseColor 'eventIn' events. All of which may make for confusing < and wordy prototype declarations. Are there ever cases where you might want < to ONLY allow initial values to be set, and NOT allow them to be changed < later?

--- >

We're making distinctions between fields, which can be given an initial > value but cannot be changed except by the node that they're contained in, > and events, which (at least for the built-in nodes) are requests to change > fields. So, if we want our TwoColorChair to have colors that can be changed, > we'd need to expose the leg.setDiffuseColor 'eventIn' and seat.diffuseColor 'eventIn' events. All of which > may make for confusing and wordy prototype declarations. Are there ever > cases where you might want to ONLY allow initial values to be set, and NOT > allow them to be changed later?

211c221 < We need some way of taking an SFNode eventIn and inserting it into the scene. --- > We need some way of taking an SFNode field and inserting it into the scene. 216c226,227 < # May also receive SFNode nodeToUse events to set nodeToUse --- > # eventIn SFNode setNodeToUse > # -- may also receive SFNode setNodeToUse events to set nodeToUse 333a345,347 >

If it is necessary, the language field could contain something like "REMOTE:fortran" to specify both that a URL is being used, and the language contained in > that URL (for transport methods like ftp that do not provide the MIME type > of their content).

466,469c480,502 <

What other API needs to be supported? I've glossed over the details of GET/SET/SEND; < certainly at least those are necessary. It might be useful to be able to < ask "ISROUTED("eventName") to see if anybody is listening to your "eventName" < events-- if not, the script might be able to save doing some work.

--- >

Logic API

>

By "API", I mean the actual code that the VRML world creator will type into > her Logic nodes (and not a lower-level API used to communicate between a > VRML implementation and a scripting language, although the lower level API > will likely be very similar to what is described here).

>

At least the following will be necessary:

>
    >
  1. Some kind of initialization, process events, and cleanup routines. If a > language does not support asynchronous threads, then the initialization > and cleanup routines may not be necessary. >
  2. Methods to get/set the fields of the Logic node >
  3. Methods to get information out of input events >
  4. Methods to generate output events >
  5. Methods that allow the manipulation of the standard VRML data types (all > of the field types-- SFFloat, MFVec3f, SFRotation, etc). The "editing the scene" section discusses what should or should not be allowed once a Logic node > gets a pointer to a node, either from an SFNode field or from an SFNode > input event. >
  6. When receiving an input event, some way of determining which node generated > that event. This can be used in combination with fan-in and Logic nodes that edit the scene graph to do some interesting things. >
>

What other API needs to be supported? It might be useful to be able to ask "ISROUTED("eventName") to see if anybody > is listening to your "eventName" output events-- if not, the script might > be able to save doing some work. Sensors might get simpler if events are time-stamped..

516c549 <

-- Events generated from user-eventIn are always ordered, with earlier events --- >

-- Events generated from user-input are always ordered, with earlier events 518,521c551,554 < to user-eventIn events; something like events that are generated are time-stamped < with the same time as the last event from the event list... or something... < One of our goals is to be able to detect "bad fan-in"-- getting two events < with the same name that sort to exactly the same place in the message queue. --- > to user-input events; something like events that are generated are time-stamped with > the same time as the last event from the event list... or something... One > of our goals is to be able to detect "bad fan-in"-- getting two events with > the same name that sort to exactly the same place in the message queue. 537c570,575 < be queued up by the system if doing so does not change the user experience.

--- > be queued up by the system if doing so does not change the user experience > (for example, if the user is waiting for the definition of an EXTERNPROTO > to come across the network, a browser might allow the user to push buttons > that affect the EXTERNPROTO'ed object, queuing up the input events to the > EXTERNPROTO until its implementation was loaded and processing them when > it arrived).

539c577 <

To support sources of eventIn from outside the virtual world (Logic nodes --- >

To support sources of input from outside the virtual world (Logic nodes 574c612 < wait for eventIn from somewhere in the real world OR (perhaps) --- > wait for input from somewhere in the real world OR (perhaps) 579c617 < set state of fields, send messages, based on VRML and real-world eventIns --- > set state of fields, send messages, based on VRML and real-world inputs 620c658,659 < -- Clone a node the script already has a pointer to (later)

--- > -- Copy a node the script already has a pointer to (later- issues of deep > vs shallow copy)

639,640c678,679 < PROTO Torus [ field SFFloat radius1 IS GenerateTorus.radius1, < field SFFloat radius2 IS GenerateTorus.radius2 ] --- > PROTO Torus [ field SFFloat radius1 IS GENTORUS.radius1, > field SFFloat radius2 IS GENTORUS.radius2 ] 652c691 < ROUTE GENTORUS.geometry -> NODEREF.nodeToUse --- > ROUTE GENTORUS.geometry -> NODEREF.setNodeToUse 659,661c698,700 < to maintain a pointer to a node it is eventOutting as part of either its < public or internal state. This allows a Logic node to make arbitrary changes < to one or more parts of the scene graph.

--- > to maintain a pointer to a node it is generating as part of either its public > or internal state. This allows a Logic node to make arbitrary changes to > one or more parts of the scene graph.

675,676c714,716 < NodeReference { < nodeToUse = Logic { .... } . geometry --- > DEF __N NodeReference { } > DEF __L Logic { ... eventOut SFNode gometry ... } > ROUTE __L.geometry -> __N.setNodeToUse 702a743,787 >

TimeSensor

>

TimeSensors generate events as time passes. TimeSensors remains inactive > until their startTime is reached. At the first simulation tick where real time >= startTime, > the TimeSensor will begin generating time and alpha events, which may be routed to other nodes to drive continuous animation > or simulated behaviors. The length of time a TimeSensor generates events > is controlled using cycleInterval and cycleCount; a TimeSensor stops generating time events at time startTime+cycleInterval*cycleCount. cycleMethod controls the mapping of time to alpha values (which are typically used > to drive Interpolators). It may be set to FORWARD, causing alpha to rise > from 0.0 to 1.0 over each interval, BACK which is equal to 1-FORWARD, or > it may be set to SWING, causing alpha to alternate 0.0 to 1.0, 1.0 to 0.0, > on each successive interval.

>

The minTick field specifies how often the TimeSensor will generate output events; output > events are guaranteed to be generated no less than one minTick interval apart. For example, setting minTick to 1.0 will guarantee that t TimeSensor will generate output events at > most once per second. By default, minTick is zero and a TimeSensor will generate time events as often as possible > (typically, as quickly as the world can be redrawn).

>

pauseTime may be set to interrupt the progress of a TimeSensor. If pauseTime is greater than startTime, time and alpha events will not be generated after the pause time. pauseTime is ignored if it is less than or equal to startTime.

>

If cycleCount is <= 0, the TimeSensor will continue to tick continuously, without a cycle > interval; in this case, cycleInterval and cycleMethod are ignored, and alpha events are not generated. This use of the TimeSensor > should be used with caution, since it incurs continuous overhead on the > simulation.

>

Setting cycleCount to 1 and cycleInterval to 0 will result in a single event being generated at startTime; this can be used to build alarms and timers that go off periodically.

>

No guarantees are made with respect to how often a TimeSensor will generate > time events, but at least one event must be generated if it is later than startTime and startTime was set to a time in the future.

>
> FILE FORMAT/DEFAULTS
>      TimeSensor {
>           startTime 0          # SFTime (double-precision seconds)
>           pauseTime 0          # SFTime
>           minTick 0            # SFTime
>           cycleInterval 1      # SFTime
>           cycleCount    1      # SFLong
>           cycleMethod  FORWARD # SFEnum FORWARD | BACK | SWING
>           # eventIn  SFTime  setStartTime
>           # eventIn  SFTime  setPauseTime
>           # eventIn  SFTime  setCycleInterval
>           # eventIn  SFLong  setCycleCount
>           # eventIn  SFEnum  setCycleMethod    # FORWARD | BACK | SWING
>           # eventOut SFTime  time
>           # eventOut SFFloat alpha
>      }
> 
>

Oops, need to add a description of the SFTime field. We could use SFFloat's > for time, except that if we expect to be dealing with absolute times( from > Jan 1 1970 0:00 GMT perhaps) then 32-bit floats don't give enough precision. > Inventor writes SFTime fields as 64-bit double-precision values, but stores > time values internally as two 32-bit integers

733c818 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 748c833 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 758c843,847 < by being sent enable events. There are two types of PointingDeviceSensors; ClickSensor and DragSensors.

--- > by being sent enable events. There are two types of PointingDeviceSensors; ClickSensor and DragSensors.

>

Pointing device sensors may be nested, with the rule being that the sensors > lowest in the scene hierarchy will have first change to 'grab' user input; > if user input is 'grabbed', sensors higher in the hierarchy will not have > a chance to process it.

797c886 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 830c919 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 855c944 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 881c970 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 906c995 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 934c1023 < # eventIn SFBool enable --- > # eventIn SFBool setEnabled 955,972c1044,1052 <

TimeSensor

<

TimeSensors generate events as time passes. TimeSensors remains inactive < until their startTime is reached. At the first simulation tick where real time >= startTime, < the TimeSensor will begin generating time and alpha events, which may be routed to the eventIn of other nodes to drive continuous < animation or simulated behaviors. The length of time a TimeSensor generates < events is controlled using cycleInterval and cycleCount; a TimeSensor stops generating time events at time startTime+cycleInterval*cycleCount. cycleMethod controls the mapping of time to alpha values (which are typically used < to drive Interpolators). It may be set to FORWARD, causing alpha to rise < from 0.0 to 1.0 over each interval, BACK which is equal to 1-FORWARD, or < it may be set to SWING, causing alpha to alternate 0.0 to 1.0, 1.0 to 0.0, < on each successive interval.

<

pauseTime may be set to interrupt the progress of a TimeSensor. If pauseTime is greater than startTime, time and alpha events will not be generated after the pause time. pauseTime is ignored if it is less than or equal to startTime.

<

If cycleCount is <= 0, the TimeSensor will continue to tick continuously, without a cycle < interval; in this case, cycleInterval and cycleMethod are ignored, and alpha events are not generated. This use of the TimeSensor < should be used with caution, since it incurs continuous overhead on the < simulation.

<

Setting cycleCount to 1 and cycleInterval to 0 will result in a single event being generated at startTime; this can be used to build alarms and timers that go off periodically.

<

No guarantees are made with respect to how often a TimeSensor will generate < time events, but at least one event must be generated if it is later than startTime and startTime was set to a time in the future.

--- >

VisibilitySensor

>

A visibility sensor generates visible/notVisible events, and can be used to make a script take up less CPU time when the things the script > is controlling are not visible (for example, don't bother doing an elaborate > walk-cycle animation if the character is not visible; instead, just modify > its overall position/orientation).

>

There are some issues here about when visibility should be determined; I predict it will be a bit tricky to implement a browser > that doesn't suffer from "off-by-one" visibility errors, but we might just > leave that as a quality-of-implementation issue and not spec exact behavior > (I'm sure we won't require exact visibility computation, anyway...).

975,988c1055,1059 < TimeSensor { < startTime 0 # SFTime (seconds) < pauseTime 0 # SFTime < cycleInterval 1 # SFTime < cycleCount 1 # SFLong < cycleMethod FORWARD # SFEnum FORWARD | BACK | SWING < # eventIn SFTime startTime < # eventIn SFTime pauseTime < # eventIn SFTime cycleInterval < # eventIn SFLong cycleCount < # eventIn SFEnum cycleMethod # FORWARD | BACK | SWING < # eventOut SFTime time < # eventOut SFFloat alpha < } --- > VisibilitySensor { > enabled TRUE # SFBool > # eventIn SFBool setEnabled > # eventOut SFBool visible > } 990,993d1060 <

Oops, need to add a description of the SFTime field. We could use SFFloat's < for time, except that if we expect to be dealing with absolute times( from Jan 1 1970 0:00 GMT perhaps) then 32-bit floats don't give enough precision. < Inventor writes SFTime fields as 64-bit double-precision values, but stores time values internally as < two 32-bit integers

1012c1079 < # eventIn SFFloat alpha --- > # eventIn SFFloat setAlpha 1024c1091 < # eventIn SFFloat alpha --- > # eventIn SFFloat setAlpha 1041c1108 < # eventIn SFFloat alpha --- > # eventIn SFFloat setAlpha 1053c1120 < # eventIn SFFloat alpha --- > # eventIn SFFloat setAlpha 1068c1135 < # eventIn SFFloat alpha --- > # eventIn SFFloat setAlpha 1082c1149 < # eventIn SFFloat alpha --- > # eventIn SFFloat setAlpha 1111c1178 < ROUTE LOGIC.color -> MATERIAL.diffuseColor --- > ROUTE LOGIC.color -> MATERIAL.setDiffuseColor 1126d1192 < isBeingClicked = USE CLICKSENSOR.isActive 1129a1196 > ROUTE CLICKSENSOR.isActive -> LOGIC.isBeingClicked 1152,1153c1219,1220 < ROUTE START.release -> TIME.start < ROUTE TIME.alpha -> INTERP.alpha --- > ROUTE START.release -> TIME.setStart > ROUTE TIME.alpha -> INTERP.setAlpha 1161c1228 < ROUTE INTERP.outValue -> TRANSFORM.translation --- > ROUTE INTERP.outValue -> TRANSFORM.setTranslation 1173d1239 < alpha = USE TIMESENSOR.alpha 1176,1177c1242,1243 < ROUTE TIME.alpha -> ROTATE_INTERP.alpha < ROUTE ROTATE_INTERP.outValue -> TRANSFORM.rotation --- > ROUTE TIME.alpha -> ROTATE_INTERP.setAlpha > ROUTE ROTATE_INTERP.outValue -> TRANSFORM.setRotation 1214c1280 < ROUTE TB.state -> LIGHT.on --- > ROUTE TB.state -> LIGHT.setOn 1225c1291 < [ eventIn MFColor ambientColor IS CONVERT.ambientIn, --- > [ eventIn MFColor setAmbientColor IS CONVERT.ambientIn, 1227c1293 < eventIn MFColor diffuseColor IS CONVERT.diffuseIn, --- > eventIn MFColor setDiffuseColor IS CONVERT.diffuseIn, 1229c1295 < eventIn MFColor specularColor IS CONVERT.specularIn, --- > eventIn MFColor setSpecularColor IS CONVERT.specularIn, 1231c1297 < eventIn MFColor emissiveColor IS CONVERT.emissiveIn, --- > eventIn MFColor setEmissiveColor IS CONVERT.emissiveIn, 1233c1299 < eventIn MFFloat shininess IS M.shininess, --- > eventIn MFFloat setShininess IS M.setShininess, 1235,1236c1301,1302 < eventIn MFFloat transparency IS M.transparency ] < field MFColor transparency IS M.transparency, --- > eventIn MFFloat setTransparency IS M.setTransparency, > field MFColor transparency IS M.transparency ] 1250,1251c1316,1317 < ROUTE CONVERT.ambientOut -> M.ambientColor < ROUTE CONVERT.diffuseOut -> M.diffuseColor --- > ROUTE CONVERT.ambientOut -> M.setAmbientColor > ROUTE CONVERT.diffuseOut -> M.setDiffuseColor 1279c1345 < eventIn SFVec3f currentPosition --- > eventIn SFVec3f setCurrentPosition 1282c1348 < ROUTE PositionReporter.position -> SEND_TO_SERVER.currentPosition --- > ROUTE PositionReporter.position -> SEND_TO_SERVER.setCurrentPosition 1308c1374 < ROUTE L.geometry -> NODEREF.nodeToUse --- > ROUTE L.geometry -> NODEREF.setNodeToUse