View Javadoc

1   /*
2    * $RCSfile: MouseTranslate.java,v $
3    *
4    * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved.
5    *
6    * Redistribution and use in source and binary forms, with or without
7    * modification, are permitted provided that the following conditions
8    * are met:
9    *
10   * - Redistribution of source code must retain the above copyright
11   *   notice, this list of conditions and the following disclaimer.
12   *
13   * - Redistribution in binary form must reproduce the above copyright
14   *   notice, this list of conditions and the following disclaimer in
15   *   the documentation and/or other materials provided with the
16   *   distribution.
17   *
18   * Neither the name of Sun Microsystems, Inc. or the names of
19   * contributors may be used to endorse or promote products derived
20   * from this software without specific prior written permission.
21   *
22   * This software is provided "AS IS," without a warranty of any
23   * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
24   * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
25   * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
26   * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
27   * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
28   * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
29   * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
30   * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
31   * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
32   * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
33   * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
34   * POSSIBILITY OF SUCH DAMAGES.
35   *
36   * You acknowledge that this software is not designed, licensed or
37   * intended for use in the design, construction, operation or
38   * maintenance of any nuclear facility.
39   *
40   * $Revision: 1.1 $
41   * $Date: 2009/04/08 06:31:15 $
42   * $State: Exp $
43   */
44  
45  package edu.uci.ics.jung.visualization3d.control;
46  
47  import java.awt.*;
48  import java.awt.event.*;
49  import java.util.*;
50  import javax.media.j3d.*;
51  import javax.vecmath.*;
52  
53  import com.sun.j3d.utils.behaviors.mouse.MouseBehavior;
54  import com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback;
55  
56  /**
57   * MouseTranslate is a Java3D behavior object that lets users control the 
58   * translation (X, Y) of an object via a mouse drag motion with the third
59   * mouse button (alt-click on PC). See MouseRotate for similar usage info.
60   */
61  
62  public class MouseTranslate extends MouseBehavior {
63  
64  	double x_factor = .02;
65  	double y_factor = .02;
66  	Vector3d translation = new Vector3d();
67  
68  	private MouseBehaviorCallback callback = null;
69  
70  	/**
71  	 * Creates a mouse translate behavior given the transform group.
72  	 * @param transformGroup The transformGroup to operate on.
73  	 */
74  	public MouseTranslate(TransformGroup transformGroup) {
75  		super(transformGroup);
76  	}
77  
78  	/**
79  	 * Creates a default translate behavior.
80  	 */
81  	public MouseTranslate(){
82  		super(0);
83  	}
84  
85  	/**
86  	 * Creates a translate behavior.
87  	 * Note that this behavior still needs a transform
88  	 * group to work on (use setTransformGroup(tg)) and
89  	 * the transform group must add this behavior.
90  	 * @param flags
91  	 */
92  	public MouseTranslate(int flags) {
93  		super(flags);
94  	}
95  
96  	/**
97  	 * Creates a translate behavior that uses AWT listeners and behavior
98  	 * posts rather than WakeupOnAWTEvent.  The behavior is added to the
99  	 * specified Component. A null component can be passed to specify
100 	 * the behavior should use listeners.  Components can then be added
101 	 * to the behavior with the addListener(Component c) method.
102 	 * @param c The Component to add the MouseListener
103 	 * and MouseMotionListener to.
104 	 * @since Java 3D 1.2.1
105 	 */
106 	public MouseTranslate(Component c) {
107 		super(c, 0);
108 	} 
109 
110 	/**
111 	 * Creates a translate behavior that uses AWT listeners and behavior
112 	 * posts rather than WakeupOnAWTEvent.  The behaviors is added to
113 	 * the specified Component and works on the given TransformGroup.
114 	 * A null component can be passed to specify the behavior should use
115 	 * listeners.  Components can then be added to the behavior with the
116 	 * addListener(Component c) method.
117 	 * @param c The Component to add the MouseListener and
118 	 * MouseMotionListener to.
119 	 * @param transformGroup The TransformGroup to operate on.
120 	 * @since Java 3D 1.2.1
121 	 */
122 	public MouseTranslate(Component c, TransformGroup transformGroup) {
123 		super(c, transformGroup);
124 	}
125 
126 	/**
127 	 * Creates a translate behavior that uses AWT listeners and behavior
128 	 * posts rather than WakeupOnAWTEvent.  The behavior is added to the
129 	 * specified Component.  A null component can be passed to specify
130 	 * the behavior should use listeners.  Components can then be added to
131 	 * the behavior with the addListener(Component c) method.
132 	 * Note that this behavior still needs a transform
133 	 * group to work on (use setTransformGroup(tg)) and the transform
134 	 * group must add this behavior.
135 	 * @param flags interesting flags (wakeup conditions).
136 	 * @since Java 3D 1.2.1
137 	 */
138 	public MouseTranslate(Component c, int flags) {
139 		super(c, flags);
140 	}
141 
142 	public void initialize() {
143 		super.initialize();
144 		if ((flags & INVERT_INPUT) == INVERT_INPUT) {
145 			invert = true;
146 			x_factor *= -1;
147 			y_factor *= -1;
148 		}
149 	}
150 
151 	/**
152 	 * Return the x-axis movement multipler.
153 	 **/
154 	public double getXFactor() {
155 		return x_factor;
156 	}
157 
158 	/**
159 	 * Return the y-axis movement multipler.
160 	 **/
161 	public double getYFactor() {
162 		return y_factor;
163 	}
164 
165 	/**
166 	 * Set the x-axis amd y-axis movement multipler with factor.
167 	 **/
168 	public void setFactor( double factor) {
169 		x_factor = y_factor = factor;
170 	}
171 
172 	/**
173 	 * Set the x-axis amd y-axis movement multipler with xFactor and yFactor
174 	 * respectively.
175 	 **/
176 	public void setFactor( double xFactor, double yFactor) {
177 		x_factor = xFactor;
178 		y_factor = yFactor;    
179 	}
180 
181 	public void processStimulus (Enumeration criteria) {
182 		WakeupCriterion wakeup;
183 		AWTEvent[] events;
184 		MouseEvent evt;
185 //		int id;
186 //		int dx, dy;
187 
188 		while (criteria.hasMoreElements()) {
189 			wakeup = (WakeupCriterion) criteria.nextElement();
190 
191 			if (wakeup instanceof WakeupOnAWTEvent) {
192 				events = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
193 				if (events.length > 0) {
194 					evt = (MouseEvent) events[events.length-1];
195 					doProcess(evt);
196 				}
197 			}
198 
199 			else if (wakeup instanceof WakeupOnBehaviorPost) {
200 				while (true) {
201 					// access to the queue must be synchronized
202 					synchronized (mouseq) {
203 						if (mouseq.isEmpty()) break;
204 						evt = (MouseEvent)mouseq.remove(0);
205 						// consolodate MOUSE_DRAG events
206 						while ((evt.getID() == MouseEvent.MOUSE_DRAGGED) &&
207 								!mouseq.isEmpty() &&
208 								(((MouseEvent)mouseq.get(0)).getID() ==
209 									MouseEvent.MOUSE_DRAGGED)) {
210 							evt = (MouseEvent)mouseq.remove(0);
211 						}
212 					}
213 					doProcess(evt);
214 				}
215 			}
216 
217 		}
218 		wakeupOn(mouseCriterion);
219 	}
220 
221 	void doProcess(MouseEvent evt) {
222 		int id;
223 		int dx, dy;
224 
225 		processMouseEvent(evt);
226 
227 		if (((buttonPress)&&((flags & MANUAL_WAKEUP) == 0)) ||
228 				((wakeUp)&&((flags & MANUAL_WAKEUP) != 0))){
229 			id = evt.getID();
230 			if ((id == MouseEvent.MOUSE_DRAGGED) &&
231 					!evt.isAltDown() && !evt.isMetaDown()) {
232 
233 				x = evt.getX();
234 				y = evt.getY();
235 
236 				dx = x - x_last;
237 				dy = y - y_last;
238 
239 				if ((!reset) && ((Math.abs(dy) < 50) && (Math.abs(dx) < 50))) {
240 					//System.out.println("dx " + dx + " dy " + dy);
241 					transformGroup.getTransform(currXform);
242 					
243 					
244 //					System.err.println("currXform is \n"+currXform);
245 					Transform3D origCurrentXform = new Transform3D(currXform);
246 					
247 					Transform3D ltvw = new Transform3D();
248 					transformGroup.getLocalToVworld(ltvw);
249 //					System.err.println("ltvw is \n"+ltvw);
250 					Matrix3d mat = new Matrix3d();
251 					ltvw.getRotationScale(mat);
252 					Transform3D rot = new Transform3D();
253 					rot.set(mat);
254 //					x_factor = y_factor = 1/ltvw.getScale();
255 					
256 //					currXform.mulInverse(origCurrentXform);
257 //					currXform.mul(rot);
258 					
259 					
260 //					System.err.println("after mul. currXform is \n"+currXform);
261 //					Transform3D scale = new Transform3D();
262 //					scale.setScale(ltvw.getScale());
263 //					scale.invert();
264 //					rot.mul(scale);
265 					
266 					
267 					
268 					translation.x = dx*x_factor; 
269 					translation.y = -dy*y_factor;
270 					
271 					
272 //					Vector3d translationOut = new Vector3d();
273 //					rot.transform(translation, translationOut);
274 
275 					transformX.set(translation);
276 
277 					if (invert) {
278 						currXform.mul(currXform, transformX);
279 					} else {
280 						currXform.mul(transformX, currXform);
281 					}
282 
283 //					currXform.mulInverse(rot);
284 //					currXform.mul(origCurrentXform);
285 					transformGroup.setTransform(currXform);
286 
287 					transformChanged( currXform );
288 
289 					if (callback!=null)
290 						callback.transformChanged( MouseBehaviorCallback.TRANSLATE,
291 								currXform );
292 
293 				}
294 				else {
295 					reset = false;
296 				}
297 				x_last = x;
298 				y_last = y;
299 			}
300 			else if (id == MouseEvent.MOUSE_PRESSED) {
301 				x_last = evt.getX();
302 				y_last = evt.getY();
303 			}
304 		}
305 	}
306 
307 	/**
308 	 * Users can overload this method  which is called every time
309 	 * the Behavior updates the transform
310 	 *
311 	 * Default implementation does nothing
312 	 */
313 	public void transformChanged( Transform3D transform ) {
314 	}
315 
316 	/**
317 	 * The transformChanged method in the callback class will
318 	 * be called every time the transform is updated
319 	 */
320 	public void setupCallback( MouseBehaviorCallback callback ) {
321 		this.callback = callback;
322 	}
323 }
324