1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
|
3 | <X3D profile='Immersive' version='3.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.0.xsd'> |
4 | <head> |
5 | <meta name='title' content=' SliderFloatPrototype.x3d '/> |
6 | <meta name='description' content='A Slider prototype enabling mouse input where float output values are needed. Size, min/max values and color are defined by the author.'/> |
7 | <meta name='creator' content='Mike Hunsberger, Jane Wu'/> |
8 | <meta name='created' content='17 October 2001'/> |
9 | <meta name='modified' content='15 October 2023'/> |
10 | <meta name='subject' content='animation slider'/> |
11 | <meta name='identifier' content=' https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/SliderFloatPrototype.x3d '/> |
12 | <meta name='generator' content='X3D-Edit 4.0, https://www.web3d.org/x3d/tools/X3D-Edit'/> |
13 | <meta name='license' content='../../license.html'/> |
14 | </head> |
15 | <Scene> |
16 | <WorldInfo title='SliderFloatPrototype.x3d'/> |
17 | <ProtoDeclare name='SliderFloat' appinfo='Slider user-interface widget that produces floating-point output values'> |
18 | <ProtoInterface> |
19 |
<field name='layoutDirection' type='SFString' value='vertical' accessType='initializeOnly'
appinfo='Allowed values: vertical, horizontal'/> |
20 |
<field name='height' type='SFFloat' value='1.0' accessType='initializeOnly'
appinfo='default value 1.0'/> |
21 |
<field name='radius' type='SFFloat' value='0.1' accessType='initializeOnly'
appinfo='default value 0.1'/> |
22 |
<field name='barRadius' type='SFFloat' value='0.02' accessType='initializeOnly'
appinfo='default value 0.02'/> |
23 |
<field name='sliderBarColor' type='SFColor' value='.8 .4 .8' accessType='initializeOnly'
appinfo='default value .8 .4 .8'/> |
24 |
<field name='sliderBallColor' type='SFColor' value='.3 .4 .8' accessType='initializeOnly'
appinfo='default value .3 .4 .8'/> |
25 |
<field name='sliderEndColor' type='SFColor' value='.2 .3 .9' accessType='initializeOnly'
appinfo='default value .2 .3 .9'/> |
26 |
<field name='min' type='SFFloat' value='0.0' accessType='initializeOnly'
appinfo='default value 0.0'/> |
27 |
<field name='max' type='SFFloat' value='10.0' accessType='initializeOnly'
appinfo='default value 10.0'/> |
28 |
<field name='value' type='SFFloat' value='0.0' accessType='initializeOnly'
appinfo='default value 0.0'/> |
29 |
<field name='setMin' type='SFFloat' accessType='inputOnly'
appinfo='set minimum value for slider bar'/> |
30 |
<field name='setMax' type='SFFloat' accessType='inputOnly'
appinfo='set maximum value for slider bar'/> |
31 |
<field name='setValue' type='SFFloat' accessType='inputOnly'
appinfo='set value for slider bar'/> |
32 |
<field name='valueChanged' type='SFFloat' accessType='outputOnly'
appinfo='output value for slider bar'/> |
33 |
<field name='traceEnabled' type='SFBool' value='false' accessType='initializeOnly'
appinfo='enable/disable console output for troubleshooting'/> |
34 | </ProtoInterface> |
35 | <ProtoBody> |
36 | <Group> |
37 |
<!-- ROUTE information for LayoutDirectionTransform node:
[from LayoutDirectionScript.directionRotation to set_rotation
]
-->
<Transform DEF='LayoutDirectionTransform'> |
38 | <Transform DEF='SliderBarTransform'> |
39 | <Shape> |
40 | <Appearance> |
41 | <Material DEF='SliderBarMaterial'> |
42 | <IS> |
43 | <connect nodeField='diffuseColor' protoField='sliderBarColor'/> |
44 | <connect nodeField='emissiveColor' protoField='sliderBarColor'/> |
45 | </IS> |
46 | </Material> |
47 | </Appearance> |
48 | <Cylinder DEF='SliderBar'> |
49 | <IS> |
50 | <connect nodeField='height' protoField='height'/> |
51 | <connect nodeField='radius' protoField='barRadius'/> |
52 | </IS> |
53 | </Cylinder> |
54 | </Shape> |
55 | </Transform> |
56 |
<!-- ROUTE information for SliderBallTransform node:
[from SliderScript.ballPositionChanged to set_translation
]
-->
<Transform DEF='SliderBallTransform'> |
57 |
<!-- ROUTE information for SliderBallPlaneSensor node:
[from SliderScript.minBallPositionChanged to set_minPosition
]
[from SliderScript.maxBallPositionChanged to set_maxPosition
]
[from translation_changed to SliderScript.setBallPosition
]
-->
<PlaneSensor DEF='SliderBallPlaneSensor' description='select and drag to change values'/> |
58 | <Shape> |
59 | <Appearance> |
60 | <Material DEF='SliderBallMaterial'> |
61 | <IS> |
62 | <connect nodeField='diffuseColor' protoField='sliderBallColor'/> |
63 | </IS> |
64 | </Material> |
65 | </Appearance> |
66 | <Sphere DEF='SliderBall'> |
67 | <IS> |
68 | <connect nodeField='radius' protoField='radius'/> |
69 | </IS> |
70 | </Sphere> |
71 | </Shape> |
72 | </Transform> |
73 |
<!-- ROUTE information for BottomEndTransform node:
[from SliderScript.bottomEndPositionChanged to set_translation
]
-->
<Transform DEF='BottomEndTransform'> |
74 |
<!-- ROUTE information for BottomEndSensor node:
[from isActive to SliderScript.bottomEndTouched
]
-->
<TouchSensor DEF='BottomEndSensor' description='touch bottom end to decrement'/> |
75 | <Shape> |
76 | <Appearance> |
77 | <Material> |
78 | <IS> |
79 | <connect nodeField='diffuseColor' protoField='sliderEndColor'/> |
80 | </IS> |
81 | </Material> |
82 | </Appearance> |
83 | <Cylinder height='.05' radius='.1'/> |
84 | </Shape> |
85 | <Transform translation='0 -0.1 0'> |
86 |
<!-- Shape
TransparentEndShape is a DEF node that has 1 USE node: USE_1 -->
<Shape DEF='TransparentEndShape'> |
87 | <Appearance> |
88 | <Material transparency='1'/> |
89 | </Appearance> |
90 | <Box size='0.2 0.2 0.01'/> |
91 | </Shape> |
92 | </Transform> |
93 | </Transform> |
94 |
<!-- ROUTE information for TopEndTransform node:
[from SliderScript.topEndPositionChanged to set_translation
]
-->
<Transform DEF='TopEndTransform'> |
95 |
<!-- ROUTE information for TopEndSensor node:
[from isActive to SliderScript.topEndTouched
]
-->
<TouchSensor DEF='TopEndSensor' description='touch top end to increment'/> |
96 | <Shape> |
97 | <Appearance> |
98 | <Material> |
99 | <IS> |
100 | <connect nodeField='diffuseColor' protoField='sliderEndColor'/> |
101 | </IS> |
102 | </Material> |
103 | </Appearance> |
104 | <Cylinder height='.05' radius='.1'/> |
105 | </Shape> |
106 | <Transform translation='0 0.1 0'> |
107 | <Shape USE='TransparentEndShape'/> |
108 | </Transform> |
109 | </Transform> |
110 |
<!-- ROUTE information for SliderScript node:
[from SliderBallPlaneSensor.translation_changed to setBallPosition
]
[from BottomEndSensor.isActive to bottomEndTouched
]
[from TopEndSensor.isActive to topEndTouched
]
[from minBallPositionChanged to SliderBallPlaneSensor.set_minPosition
]
[from maxBallPositionChanged to SliderBallPlaneSensor.set_maxPosition
]
[from bottomEndPositionChanged to BottomEndTransform.set_translation
]
[from topEndPositionChanged to TopEndTransform.set_translation
]
[from ballPositionChanged to SliderBallTransform.set_translation
]
-->
<Script DEF='SliderScript'> |
111 | <!-- local variables --> |
112 | <field name='height' type='SFFloat' accessType='initializeOnly'/> |
113 | <field name='radius' type='SFFloat' accessType='initializeOnly'/> |
114 | <field name='min' type='SFFloat' accessType='initializeOnly'/> |
115 | <field name='max' type='SFFloat' accessType='initializeOnly'/> |
116 | <field name='value' type='SFFloat' accessType='initializeOnly'/> |
117 | <field name='lastBallPosition' type='SFVec3f' value='0 0 0' accessType='initializeOnly'/> |
118 | <field name='beginPosition' type='SFVec3f' value='0 0 0' accessType='initializeOnly'/> |
119 | <field name='endPosition' type='SFVec3f' value='0 1 0' accessType='initializeOnly'/> |
120 | <field name='incrementInterval' type='SFFloat' value='0.1' accessType='initializeOnly'/> |
121 | <field name='setMin' type='SFFloat' accessType='inputOnly'/> |
122 | <field name='setMax' type='SFFloat' accessType='inputOnly'/> |
123 | <field name='setValue' type='SFFloat' accessType='inputOnly'/> |
124 | <field name='valueChanged' type='SFFloat' accessType='outputOnly'/> |
125 | <field name='bottomEndTouched' type='SFBool' accessType='inputOnly'/> |
126 | <field name='topEndTouched' type='SFBool' accessType='inputOnly'/> |
127 | <field name='setBallPosition' type='SFVec3f' accessType='inputOnly'/> |
128 | <field name='bottomEndPositionChanged' type='SFVec3f' accessType='outputOnly'/> |
129 | <field name='topEndPositionChanged' type='SFVec3f' accessType='outputOnly'/> |
130 | <field name='ballPositionChanged' type='SFVec3f' accessType='outputOnly'/> |
131 | <field name='minBallPositionChanged' type='SFVec2f' accessType='outputOnly'/> |
132 | <field name='maxBallPositionChanged' type='SFVec2f' accessType='outputOnly'/> |
133 | <field name='partialIncrement' type='SFFloat' value='0.0' accessType='initializeOnly'/> |
134 | <field name='traceEnabled' type='SFBool' accessType='initializeOnly'/> |
135 | <IS> |
136 | <connect nodeField='height' protoField='height'/> |
137 | <connect nodeField='radius' protoField='radius'/> |
138 | <connect nodeField='min' protoField='min'/> |
139 | <connect nodeField='max' protoField='max'/> |
140 | <connect nodeField='value' protoField='value'/> |
141 | <connect nodeField='setMin' protoField='setMin'/> |
142 | <connect nodeField='setMax' protoField='setMax'/> |
143 | <connect nodeField='setValue' protoField='setValue'/> |
144 | <connect nodeField='valueChanged' protoField='valueChanged'/> |
145 | <connect nodeField='traceEnabled' protoField='traceEnabled'/> |
146 | </IS> |
<![CDATA[
ecmascript: function initialize() { tracePrint('initialize() commenced...'); beginPosition = new SFVec3f(0, (height/2) * (-1) + radius, 0); endPosition = new SFVec3f(0, (height/2) - radius, 0); tracePrint('beginPosition=' + beginPosition.toString() + ', endPosition=' + endPosition.toString()); incrementInterval = (height - (2 * radius)) / (max - min); tracePrint('incrementInterval=' + incrementInterval.toString()); bottomEndPositionChanged = new SFVec3f(0, (height/2) * (-1), 0); topEndPositionChanged = new SFVec3f(0, (height/2), 0); tracePrint('bottomEndPositionChanged=' + bottomEndPositionChanged.toString() + ', topEndPositionChanged=' + topEndPositionChanged.toString()); minBallPositionChanged = new SFVec2f(0, bottomEndPositionChanged.y + radius); maxBallPositionChanged = new SFVec2f(0, topEndPositionChanged.y - radius); tracePrint('minBallPositionChanged=' + minBallPositionChanged.toString() + ', maxBallPositionChanged=' + maxBallPositionChanged.toString()); ballPositionChanged = new SFVec3f(0, beginPosition.y + (incrementInterval * (value - min)), 0); lastBallPosition = ballPositionChanged; if (value < min) value = min; if (value > max) value = max; valueChanged = value; tracePrint('value=' + value.toString()); tracePrint('...initialize() complete'); } function setMin(inputValue, timeStamp) { min = inputValue; if (value < min) value = min; incrementInterval = (height - (2 * radius)) / (max - min); tracePrint('incrementInterval=' + incrementInterval.toString()); ballPositionChanged = new SFVec3f(0, beginPosition.y + (incrementInterval * (value - min)), 0); lastBallPosition = ballPositionChanged; valueChanged = value; tracePrint('min=' + min + ', valueChanged=' + valueChanged); } function setMax(inputValue, timeStamp) { max = inputValue; if (value > max) value = max; incrementInterval = (height - (2 * radius)) / (max - min); tracePrint('incrementInterval=' + incrementInterval.toString()); ballPositionChanged = new SFVec3f(0, beginPosition.y + (incrementInterval * (value - min)), 0); lastBallPosition = ballPositionChanged; valueChanged = value; tracePrint('max=' + max + ', valueChanged=' + valueChanged); } function setValue(inputValue, timeStamp) { if (inputValue <= min) { valueChanged = value = min; ballPositionChanged = beginPosition; lastBallPosition = ballPositionChanged; } else if (inputValue >= max) { valueChanged = value = max; ballPositionChanged = endPosition; lastBallPosition = ballPositionChanged; } else { if (inputValue > value) //getting bigger { ballPositionChanged = new SFVec3f(0, lastBallPosition.y + (incrementInterval * (inputValue - value)), 0); lastBallPosition = ballPositionChanged; } else if (inputValue < value) //getting smaller { ballPositionChanged = new SFVec3f(0, lastBallPosition.y - (incrementInterval * (value - inputValue)), 0); lastBallPosition = ballPositionChanged; } valueChanged = value = inputValue; } tracePrint('valueChanged=' + valueChanged); } function bottomEndTouched(inputValue, timeStamp) { tracePrint('bottomEndTouched(' + inputValue.toString() + ')'); if (inputValue == false) return; // ignore deselection if (value <= Math.round(value)) value = Math.round(value); else value = Math.round(value) + 1; partialIncrement = incrementInterval * (valueChanged - (value - 1)); if (value > min) { valueChanged = --value; if (partialIncrement != incrementInterval) { ballPositionChanged = new SFVec3f(0, lastBallPosition.y - partialIncrement, 0); partialIncrement = incrementInterval; } else ballPositionChanged = new SFVec3f(0, lastBallPosition.y - incrementInterval, 0); lastBallPosition = ballPositionChanged; } } function topEndTouched(inputValue, timeStamp) { tracePrint('topEndTouched(' + inputValue.toString() + ')'); if (inputValue == false) return; // ignore deselection if (value < Math.round(value)) value = Math.round(value) - 1; else value = Math.round(value); partialIncrement = incrementInterval * (value + 1 - valueChanged); if (value < max) { valueChanged = ++value; if (partialIncrement != incrementInterval) { ballPositionChanged = new SFVec3f(0, lastBallPosition.y + partialIncrement, 0); partialIncrement = incrementInterval; } else ballPositionChanged = new SFVec3f(0, lastBallPosition.y + incrementInterval, 0); lastBallPosition = ballPositionChanged; } } function setBallPosition(inputValue, timeStamp) { tracePrint('setBallPosition(' + inputValue.toString() + ')'); if (inputValue.y > lastBallPosition.y) // moving upwards { if (value >= max) { value = max; lastBallPosition = endPosition; } else { value = (inputValue.y - beginPosition.y) * ((max - min) / (endPosition.y - beginPosition.y)); lastBallPosition = inputValue; } valueChanged = value; ballPositionChanged = lastBallPosition; } else if (inputValue.y < lastBallPosition.y) // moving downwards { if (value <= min) { value = min; lastBallPosition = beginPosition; } else { value = (inputValue.y - beginPosition.y) * ((max - min) / (endPosition.y - beginPosition.y)); lastBallPosition = inputValue; } valueChanged = value; ballPositionChanged = lastBallPosition; } } function tracePrint (text) { if (traceEnabled) Browser.println ('[SliderFloat SliderScript] ' + text); }
]]>
|
|
148 | </Script> |
149 | < ROUTE fromNode='SliderBallPlaneSensor' fromField='translation_changed' toNode='SliderScript' toField='setBallPosition'/> |
150 | < ROUTE fromNode='BottomEndSensor' fromField='isActive' toNode='SliderScript' toField='bottomEndTouched'/> |
151 | < ROUTE fromNode='TopEndSensor' fromField='isActive' toNode='SliderScript' toField='topEndTouched'/> |
152 | < ROUTE fromNode='SliderScript' fromField='minBallPositionChanged' toNode='SliderBallPlaneSensor' toField='set_minPosition'/> |
153 | < ROUTE fromNode='SliderScript' fromField='maxBallPositionChanged' toNode='SliderBallPlaneSensor' toField='set_maxPosition'/> |
154 | < ROUTE fromNode='SliderScript' fromField='bottomEndPositionChanged' toNode='BottomEndTransform' toField='set_translation'/> |
155 | < ROUTE fromNode='SliderScript' fromField='topEndPositionChanged' toNode='TopEndTransform' toField='set_translation'/> |
156 | < ROUTE fromNode='SliderScript' fromField='ballPositionChanged' toNode='SliderBallTransform' toField='set_translation'/> |
157 | </Transform> |
158 |
<!-- ROUTE information for LayoutDirectionScript node:
[from directionRotation to LayoutDirectionTransform.set_rotation
]
-->
<Script DEF='LayoutDirectionScript'> |
159 | <field name='direction' type='SFString' accessType='initializeOnly'/> |
160 | <field name='directionRotation' type='SFRotation' accessType='outputOnly'/> |
161 | <field name='traceEnabled' type='SFBool' accessType='initializeOnly'/> |
162 | <IS> |
163 | <connect nodeField='direction' protoField='layoutDirection'/> |
164 | <connect nodeField='traceEnabled' protoField='traceEnabled'/> |
165 | </IS> |
<![CDATA[
ecmascript: function initialize () { if ((direction=='vertical') || (direction=='Vertical') || (direction=='VERTICAL')) { directionRotation = new SFRotation(0, 0, 1, 0); } else if ((direction=='horizontal') || (direction=='Horizontal') || (direction=='HORIZONTAL')) { directionRotation = new SFRotation(0, 0, 1, -1.57); } else { Browser.println ('[SliderFloat LayoutDirectionScript] unrecognized direction: ' + direction + ', using vertical'); directionRotation = new SFRotation(0, 0, 1, 0); } tracePrint ('direction=' + direction); } function tracePrint (text) { if (traceEnabled) Browser.println ('[SliderFloat LayoutDirectionScript] ' + text); }
]]>
|
|
167 | </Script> |
168 | < ROUTE fromNode='LayoutDirectionScript' fromField='directionRotation' toNode='LayoutDirectionTransform' toField='set_rotation'/> |
169 | </Group> |
170 | </ProtoBody> |
171 | </ProtoDeclare> |
172 | <!-- ==================== --> |
173 | <Anchor description='SliderFloatExample' parameter='"target=_blank"' url=' "SliderFloatExample.x3d" "https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/SliderFloatExample.x3d" "SliderFloatExample.wrl" "https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/SliderFloatExample.wrl" '> |
174 | <Shape> |
175 | <Appearance> |
176 | <Material diffuseColor='0 1 1' emissiveColor='0 1 1'/> |
177 | </Appearance> |
178 | <Text string='"SliderFloatPrototype" "is a Prototype definition file." "" "To see an example scene" "select this text and view" "SliderFloatExample"'> |
179 | <FontStyle justify='"MIDDLE" "MIDDLE"' size='0.8'/> |
180 | </Text> |
181 | </Shape> |
182 | </Anchor> |
183 | </Scene> |
184 | </X3D> |
Event Graph ROUTE Table entries with 9 ROUTE connections total, showing X3D event-model relationships for this scene.
Each row shows an event cascade that may occur during a single timestamp interval between frame renderings, as part of the X3D execution model.
LayoutDirectionScript
Script directionRotation SFRotation |
LayoutDirectionTransform
Transform set_rotation SFRotation |
line 173
Anchor |
description='SliderFloatExample' User-interaction hint for this node. |
<!--
Color-coding legend: X3D terminology
<X3dNode
DEF='idName' field='value'/>
matches XML terminology
<XmlElement
DEF='idName' attribute='value'/>
(Light-blue background: event-based behavior node or statement)
(Grey background inside box: inserted documentation)
(Magenta background: X3D Extensibility)
<ProtoDeclare name='ProtoName'>
<field
name='fieldName'/> </ProtoDeclare>
-->
<!--
For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources, and X3D Scene Authoring Hints.
-->