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