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 * Translation behavior defines how the camera is translated. Based on
70 * com.sun.j3d.utils.behaviors.mouse.MouseTranslate.
71 */
72 public class TranslateMouseBehavior extends MouseBehavior
73 {
74 /*** x translation factor */
75 private double xFactor = .02;
76
77 /*** y translation factor */
78 private double yFactor = .02;
79
80 /*** translation vector */
81 private Vector3d translation = new Vector3d();
82
83 /*** mouse behavior 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 * Creates a mouse translate behavior given the transform group.
100 *
101 * @param transformGroup The transformGroup to operate on.
102 */
103 public TranslateMouseBehavior(final TransformGroup transformGroup)
104 {
105 super(transformGroup);
106 }
107
108 /***
109 * Creates a default translate behavior.
110 */
111 public TranslateMouseBehavior()
112 {
113 super(0);
114 }
115
116 /***
117 * Creates a translate behavior. Note that this behavior still needs a
118 * transform group to work on (use setTransformGroup(tg)) and the transform
119 * group must add this behavior.
120 *
121 * @param flags flags
122 */
123 public TranslateMouseBehavior(final int flags)
124 {
125 super(flags);
126 }
127
128 /***
129 * Creates a translate behavior that uses AWT listeners and behavior posts
130 * rather than WakeupOnAWTEvent. The behavior is added to the specified
131 * Component. A null component can be passed to specify the behavior should
132 * use listeners. Components can then be added to the behavior with the
133 * addListener(Component c) method.
134 *
135 * @param c The Component to add the MouseListener and MouseMotionListener
136 * to.
137 * @since Java 3D 1.2.1
138 */
139 public TranslateMouseBehavior(final Component c)
140 {
141 super(c, 0);
142 }
143
144 /***
145 * Creates a translate behavior that uses AWT listeners and behavior posts
146 * rather than WakeupOnAWTEvent. The behaviors is added to the specified
147 * Component and works on the given TransformGroup. A null component can be
148 * passed to specify the behavior should use listeners. Components can then
149 * be added to the behavior with the addListener(Component c) method.
150 *
151 * @param c The Component to add the MouseListener and MouseMotionListener
152 * to.
153 * @param transformGroup The TransformGroup to operate on.
154 * @since Java 3D 1.2.1
155 */
156 public TranslateMouseBehavior(final Component c,
157 final TransformGroup transformGroup)
158 {
159 super(c, transformGroup);
160 }
161
162 /***
163 * Creates a translate behavior that uses AWT listeners and behavior posts
164 * rather than WakeupOnAWTEvent. The behavior is added to the specified
165 * Component. A null component can be passed to specify the behavior should
166 * use listeners. Components can then be added to the behavior with the
167 * addListener(Component c) method. Note that this behavior still needs a
168 * transform group to work on (use setTransformGroup(tg)) and the transform
169 * group must add this behavior.
170 *
171 * @param c The Component to add the MouseListener and MouseMotionListener
172 * to.
173 * @param flags interesting flags (wakeup conditions).
174 * @since Java 3D 1.2.1
175 */
176 public TranslateMouseBehavior(final Component c, final int flags)
177 {
178 super(c, flags);
179 }
180
181 /***
182 * @see javax.media.j3d.Behavior#initialize()
183 */
184 public void initialize()
185 {
186 super.initialize();
187 if ((flags & INVERT_INPUT) == INVERT_INPUT)
188 {
189 invert = true;
190 this.xFactor *= -1;
191 this.yFactor *= -1;
192 }
193 }
194
195 /***
196 * @return the x-axis movement multipler.
197 */
198 public double getXFactor()
199 {
200 return this.xFactor;
201 }
202
203 /***
204 * @return the y-axis movement multipler.
205 */
206 public double getYFactor()
207 {
208 return this.yFactor;
209 }
210
211 /***
212 * Set the x-axis amd y-axis movement multipler with factor.
213 *
214 * @param factor same factor for both x and y
215 */
216 public void setFactor(final double factor)
217 {
218 this.xFactor = factor;
219 this.yFactor = factor;
220 }
221
222 /***
223 * Set the x-axis amd y-axis movement multipler with xFactor and yFactor
224 * respectively.
225 *
226 * @param xFactor the xFactor
227 * @param yFactor the yFactor
228 */
229 public void setFactor(final double xFactor, final double yFactor)
230 {
231 this.xFactor = xFactor;
232 this.yFactor = yFactor;
233 }
234
235 /***
236 * Set the rotation around the x-axis.
237 *
238 * @param rotateXGroup rotation around x-axis.
239 */
240 public void setRotateXGroup(final TransformGroup rotateXGroup)
241 {
242 this.rotateXGroup = rotateXGroup;
243 }
244
245 /***
246 * Set the rotation around the y-axis.
247 *
248 * @param rotateYGroup rotation around y-axis.
249 */
250 public void setRotateYGroup(final TransformGroup rotateYGroup)
251 {
252 this.rotateYGroup = rotateYGroup;
253 }
254
255 /***
256 * @see javax.media.j3d.Behavior#processStimulus(java.util.Enumeration)
257 */
258 public void processStimulus(final Enumeration criteria)
259 {
260 WakeupCriterion wakeup;
261 AWTEvent[] events;
262 MouseEvent evt;
263
264
265
266 while (criteria.hasMoreElements())
267 {
268 wakeup = (WakeupCriterion) criteria.nextElement();
269
270 if (wakeup instanceof WakeupOnAWTEvent)
271 {
272 events = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
273 if (events.length > 0)
274 {
275 evt = (MouseEvent) events[events.length - 1];
276 doProcess(evt);
277 }
278 } else if (wakeup instanceof WakeupOnBehaviorPost)
279 {
280 while (true)
281 {
282
283 synchronized (mouseq)
284 {
285 if (mouseq.isEmpty())
286 {
287 break;
288 }
289 evt = (MouseEvent) mouseq.remove(0);
290
291 while ((evt.getID() == MouseEvent.MOUSE_DRAGGED)
292 && !mouseq.isEmpty()
293 && (((MouseEvent) mouseq.get(0)).getID() == MouseEvent.MOUSE_DRAGGED))
294 {
295 evt = (MouseEvent) mouseq.remove(0);
296 }
297 }
298 doProcess(evt);
299 }
300 }
301
302 }
303 wakeupOn(mouseCriterion);
304 }
305
306 /***
307 * @param evt mouse event
308 */
309 void doProcess(final MouseEvent evt)
310 {
311 int id;
312 int dx, dy;
313
314 processMouseEvent(evt);
315
316 if (((buttonPress) && ((flags & MANUAL_WAKEUP) == 0))
317 || ((wakeUp) && ((flags & MANUAL_WAKEUP) != 0)))
318 {
319 id = evt.getID();
320 if ((id == MouseEvent.MOUSE_DRAGGED) && !evt.isAltDown()
321 && evt.isMetaDown())
322 {
323
324 this.x = evt.getX();
325 this.y = evt.getY();
326
327 dx = this.x - this.x_last;
328 dy = this.y - this.y_last;
329
330 if ((!reset) && ((Math.abs(dy) < 50) && (Math.abs(dx) < 50)))
331 {
332
333 this.transformGroup.getTransform(this.currXform);
334
335 this.translation.x = dx * this.xFactor;
336 this.translation.y = -dy * this.yFactor;
337 this.translation.z = 0;
338
339 this.transformX.setZero();
340
341
342
343 if ((this.rotateYGroup != null)
344 && (this.rotateXGroup != null))
345 {
346 this.rotateYGroup.getTransform(this.rotateY);
347 this.rotateXGroup.getTransform(this.rotateX);
348 this.transformX.set(this.rotateY);
349 this.transformX.mul(this.rotateX);
350
351
352 this.transformX.transform(this.translation);
353 }
354 this.transformX.set(this.translation);
355
356 if (this.invert)
357 {
358 this.currXform.mul(this.currXform, this.transformX);
359 } else
360 {
361 this.currXform.mul(this.transformX, this.currXform);
362 }
363
364 this.transformGroup.setTransform(this.currXform);
365
366 this.transformChanged(this.currXform);
367
368 if (this.callback != null)
369 {
370 this.callback
371 .transformChanged(
372 MouseBehaviorCallback.TRANSLATE,
373 this.currXform);
374 }
375
376 } else
377 {
378 this.reset = false;
379 }
380 this.x_last = this.x;
381 this.y_last = this.y;
382 } else if (id == MouseEvent.MOUSE_PRESSED)
383 {
384 this.x_last = evt.getX();
385 this.y_last = evt.getY();
386 }
387 }
388 }
389
390 /***
391 * Users can overload this method which is called every time the Behavior
392 * updates the transform
393 *
394 * Default implementation does nothing
395 *
396 * @param transform the transform
397 */
398 public void transformChanged(final Transform3D transform)
399 {
400
401 }
402
403 /***
404 * The transformChanged method in the callback class will be called every
405 * time the transform is updated
406 *
407 * @param callback callback
408 */
409 public void setupCallback(final MouseBehaviorCallback callback)
410 {
411 this.callback = callback;
412 }
413 }