1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 package nl.tudelft.simulation.dsol.gui.animation3D.mouse;
52
53 import java.awt.AWTEvent;
54 import java.awt.Component;
55 import java.awt.event.MouseEvent;
56 import java.util.Enumeration;
57
58 import javax.media.j3d.Transform3D;
59 import javax.media.j3d.TransformGroup;
60 import javax.media.j3d.WakeupCriterion;
61 import javax.media.j3d.WakeupOnAWTEvent;
62 import javax.media.j3d.WakeupOnBehaviorPost;
63 import javax.vecmath.Vector3d;
64
65 import com.sun.j3d.utils.behaviors.mouse.MouseBehavior;
66 import com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback;
67
68 /***
69 * ZoomMouseBehavior is a Java3D behavior object that lets users control the Z
70 * axis translation of an object via a mouse drag motion with the second mouse
71 * button. See MouseRotate for similar usage info.
72 * Based on com.sun.j3d.utils.behaviors.mouse.MouseZoom.
73 */
74
75 public class ZoomMouseBehavior extends MouseBehavior
76 {
77 /*** zoom factor */
78 private double zFactor = .04;
79
80 /*** translation */
81 private Vector3d translation = new Vector3d();
82
83 /*** callback */
84 private MouseBehaviorCallback callback = null;
85
86 /*** rotation group around x-axis */
87 private TransformGroup rotateXGroup = null;
88
89 /*** rotation group around y-axis */
90 private TransformGroup rotateYGroup = null;
91
92 /*** rotation around x-axis */
93 private Transform3D rotateX = new Transform3D();
94
95 /*** rotation around y-axis */
96 private Transform3D rotateY = new Transform3D();
97
98
99 /***
100 * Creates a zoom behavior given the transform group.
101 *
102 * @param transformGroup The transformGroup to operate on.
103 */
104 public ZoomMouseBehavior(final TransformGroup transformGroup)
105 {
106 super(transformGroup);
107 }
108
109 /***
110 * Creates a default mouse zoom behavior.
111 */
112 public ZoomMouseBehavior()
113 {
114 super(0);
115 }
116
117 /***
118 * Creates a zoom behavior. Note that this behavior still needs a transform
119 * group to work on (use setTransformGroup(tg)) and the transform group must
120 * add this behavior.
121 *
122 * @param flags flags
123 */
124 public ZoomMouseBehavior(final int flags)
125 {
126 super(flags);
127 }
128
129 /***
130 * Creates a zoom behavior that uses AWT listeners and behavior posts rather
131 * than WakeupOnAWTEvent. The behavior is added to the specified Component.
132 * A null component can be passed to specify the behavior should use
133 * listeners. Components can then be added to the behavior with the
134 * addListener(Component c) method.
135 *
136 * @param c The Component to add the MouseListener and MouseMotionListener
137 * to.
138 * @since Java 3D 1.2.1
139 */
140 public ZoomMouseBehavior(final Component c)
141 {
142 super(c, 0);
143 }
144
145 /***
146 * Creates a zoom behavior that uses AWT listeners and behavior posts rather
147 * than WakeupOnAWTEvent. The behaviors is added to the specified Component
148 * and works on the given TransformGroup.
149 *
150 * @param c The Component to add the MouseListener and MouseMotionListener
151 * to. A null component can be passed to specify the behavior
152 * should use listeners. Components can then be added to the
153 * behavior with the addListener(Component c) method.
154 * @param transformGroup The TransformGroup to operate on.
155 * @since Java 3D 1.2.1
156 */
157 public ZoomMouseBehavior(final Component c,
158 final TransformGroup transformGroup)
159 {
160 super(c, transformGroup);
161 }
162
163 /***
164 * Creates a zoom behavior that uses AWT listeners and behavior posts rather
165 * than WakeupOnAWTEvent. The behavior is added to the specified Component.
166 * A null component can be passed to specify the behavior should use
167 * listeners. Components can then be added to the behavior with the
168 * addListener(Component c) method. Note that this behavior still needs a
169 * transform group to work on (use setTransformGroup(tg)) and the transform
170 * group must add this behavior.
171 *
172 * @param c The Component to add the MouseListener and MouseMotionListener
173 * to. A null component can be passed to specify the behavior
174 * should use listeners. Components can then be added to the
175 * behavior with the addListener(Component c) method.
176 * @param flags interesting flags (wakeup conditions).
177 * @since Java 3D 1.2.1
178 */
179 public ZoomMouseBehavior(final Component c, final int flags)
180 {
181 super(c, flags);
182 }
183
184 /***
185 * @see javax.media.j3d.Behavior#initialize()
186 */
187 public void initialize()
188 {
189 super.initialize();
190 if ((flags & INVERT_INPUT) == INVERT_INPUT)
191 {
192 zFactor *= -1;
193 invert = true;
194 }
195 }
196
197 /***
198 * @return the y-axis movement multipler.
199 */
200 public double getFactor()
201 {
202 return zFactor;
203 }
204
205 /***
206 * Set the y-axis movement multipler with factor.
207 *
208 * @param factor the zoom factor
209 */
210 public void setFactor(final double factor)
211 {
212 zFactor = factor;
213 }
214
215 /***
216 * Set the rotation around the x-axis.
217 *
218 * @param rotateXGroup rotation around x-axis.
219 */
220 public void setRotateXGroup(final TransformGroup rotateXGroup)
221 {
222 this.rotateXGroup = rotateXGroup;
223 }
224
225 /***
226 * Set the rotation around the y-axis.
227 *
228 * @param rotateYGroup rotation around y-axis.
229 */
230 public void setRotateYGroup(final TransformGroup rotateYGroup)
231 {
232 this.rotateYGroup = rotateYGroup;
233 }
234
235 /***
236 * @see javax.media.j3d.Behavior#processStimulus(java.util.Enumeration)
237 */
238 public void processStimulus(final Enumeration criteria)
239 {
240 WakeupCriterion wakeup;
241 AWTEvent[] events;
242 MouseEvent evt;
243
244
245
246 while (criteria.hasMoreElements())
247 {
248 wakeup = (WakeupCriterion) criteria.nextElement();
249 if (wakeup instanceof WakeupOnAWTEvent)
250 {
251 events = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
252 if (events.length > 0)
253 {
254 evt = (MouseEvent) events[events.length - 1];
255 doProcess(evt);
256 }
257 } else if (wakeup instanceof WakeupOnBehaviorPost)
258 {
259 while (true)
260 {
261 synchronized (mouseq)
262 {
263 if (mouseq.isEmpty())
264 {
265 break;
266 }
267 evt = (MouseEvent) mouseq.remove(0);
268
269 while ((evt.getID() == MouseEvent.MOUSE_DRAGGED)
270 && !mouseq.isEmpty()
271 && (((MouseEvent) mouseq.get(0)).getID() == MouseEvent.MOUSE_DRAGGED))
272 {
273 evt = (MouseEvent) mouseq.remove(0);
274 }
275 }
276 doProcess(evt);
277 }
278 }
279
280 }
281 wakeupOn(mouseCriterion);
282 }
283
284 /***
285 * @param evt mouse event
286 */
287 void doProcess(final MouseEvent evt)
288 {
289 int id;
290 int dy;
291
292 processMouseEvent(evt);
293
294 if (((buttonPress) && ((flags & MANUAL_WAKEUP) == 0))
295 || ((wakeUp) && ((flags & MANUAL_WAKEUP) != 0)))
296 {
297 id = evt.getID();
298 if ((id == MouseEvent.MOUSE_DRAGGED) && evt.isAltDown()
299 && !evt.isMetaDown())
300 {
301
302 this.y = evt.getY();
303
304 dy = this.y - this.y_last;
305
306 if ((!reset) && ((Math.abs(dy) < 50)))
307 {
308
309 this.transformGroup.getTransform(this.currXform);
310
311 this.translation.x = 0;
312 this.translation.y = 0;
313 this.translation.z = -dy * this.zFactor;
314
315 this.transformX.setZero();
316
317
318
319 if ((this.rotateYGroup != null)
320 && (this.rotateXGroup != null))
321 {
322 this.rotateYGroup.getTransform(this.rotateY);
323 this.rotateXGroup.getTransform(this.rotateX);
324 this.transformX.set(this.rotateY);
325 this.transformX.mul(this.rotateX);
326
327
328 this.transformX.transform(this.translation);
329 }
330 this.transformX.set(this.translation);
331
332 if (this.invert)
333 {
334 this.currXform.mul(this.currXform, this.transformX);
335 } else
336 {
337 this.currXform.mul(this.transformX, this.currXform);
338 }
339
340 this.transformGroup.setTransform(this.currXform);
341
342 this.transformChanged(this.currXform);
343
344 if (this.callback != null)
345 {
346 this.callback.transformChanged(
347 MouseBehaviorCallback.ZOOM, this.currXform);
348 }
349
350 } else
351 {
352 this.reset = false;
353 }
354
355 this.x_last = this.x;
356 this.y_last = this.y;
357 } else if (id == MouseEvent.MOUSE_PRESSED)
358 {
359 this.x_last = evt.getX();
360 this.y_last = evt.getY();
361 }
362 }
363 }
364
365 /***
366 * Users can overload this method which is called every time the Behavior
367 * updates the transform
368 *
369 * Default implementation does nothing
370 *
371 * @param transform transform
372 */
373 public void transformChanged(final Transform3D transform)
374 {
375
376 }
377
378 /***
379 * The transformChanged method in the callback class will be called every
380 * time the transform is updated
381 *
382 * @param callback callback
383 */
384 public void setupCallback(final MouseBehaviorCallback callback)
385 {
386 this.callback = callback;
387 }
388 }
389