View Javadoc

1   /* -------------------------------------------------------------------
2    * Java source file for the class ManipulatableUniverse
3    * 
4    * Copyright (c), 2003, Masahiro Takatsuka.
5    * All Rights Researved.
6    * 
7    * Original Author: Masahiro Takatsuka (masa@jbeans.net)
8    * $Author: takatsukam $
9    * 
10   * $Date: 2004/03/03 11:53:06 $
11   * 
12   * $Id: ManipulatableUniverse.java,v 1.3 2004/03/03 11:53:06 takatsukam Exp $
13   * 
14   * Reference:		Document no:
15   * ___				___
16   * 
17   * To Do:
18   * ___
19   * 
20  ------------------------------------------------------------------- */
21  
22  /* --------------------------- Package ---------------------------- */
23  package net.jbeans.j3d.universe;
24  
25  /* ------------------ Import classes (packages) ------------------- *//package-summary/html">class="comment"> ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment"> ------------------ Import classes (packages) ------------------- */
26  import java.awt.*;
27  import java.awt.event.*;
28  import java.net.*;
29  import java.util.*;
30  import javax.vecmath.*;
31  import com.sun.j3d.utils.universe.*;
32  
33  import net.jbeans.j3d.transform.*;
34  import net.jbeans.j3d.util.*;
35  import net.jbeans.j3d.util.behavior.mouse.*;
36  import net.jbeans.j3d.util.picking.behavior.*;
37  import net.jbeans.j3d.util.manipulator.*;
38  
39  import net.jbeans.util.debug.*;
40  
41  /*====================================================================
42              Implementation of class ManipulatableUniverse             
43  ====================================================================*/
44  /***
45   * This class is basically the same as the SimpleUniverse.  It, however, uses
46   * Locale to view and edit the SceneGraph nodes.  
47   * 
48   * @version $Revision: 1.3 $
49   * @author Masahiro Takatsuka (masa@jbeans.net)
50   * @see SelectableUniverse
51   * @see PickMouseListener
52   */
53  
54  /*
55   * this class needs to be public but its constructors can be package.
56   */
57  public class ManipulatableUniverse extends SelectableUniverse implements PickMouseListener {
58  	private static final boolean DEBUG = Debug.getDebugFlag(ManipulatableUniverse.class);
59  	
60  	public static final int MOUSE_DEFAULT = 0x0;
61  	public static final int MOUSE_ROTATE = 0x1;	
62  	public static final int MOUSE_TRANSLATE = 0x2;
63  	public static final int MOUSE_ZOOM = 0x4;
64  	public static final int MOUSE_ROLL = 0x8;
65  	public static final int MOUSE_SCALE = 0x10;
66  	
67  	public static final int TARGET_WORLD = 0x01;
68  	public static final int TARGET_VIEWER = 0x02;
69  	public static final int TARGET_OBJECT = 0x04;
70  	
71  	protected MouseManipulatorBehavior mouseBehavior;
72  	private int mouseMode;
73  	protected int mouseButton1Mode;	
74  	private Rotate rotate;
75  	private Translate translate;
76  	private Zoom zoom;
77  	private Roll roll;
78  	private Scale scale;
79  
80      /***
81       * Creates a locale, a single ViewingPlatform, and
82       * and a Viewer object (both with their default values).
83       *
84       * @see Locale
85       * @see Viewer
86       * @see ViewingPlatform
87       */
88      ManipulatableUniverse() {
89          this(null, 1, null, null);
90      }
91  
92      /***
93       * Creates a locale, a single ViewingPlatform (with default values), and
94       * and a Viewer object.  The Viewer object uses default values for
95       * everything but the canvas.
96       *
97       * @param canvas The canvas to associate with the Viewer object.  Passing
98       *  in null will cause this parameter to be ignored and a canvas to be
99       *  created by the utility.
100      *
101      * @see Locale
102      * @see Viewer
103      * @see ViewingPlatform
104      */
105     ManipulatableUniverse(javax.media.j3d.Canvas3D canvas) {
106         this(null, 1, canvas, null);
107     }
108 
109     /***
110      * Creates the "view" side of the scene graph.  The passed in parameters
111      * override the default values where appropriate.
112      *
113      * @param origin The origin used to set the origin of the Locale object.
114      *  If this object is null, then 0.0 is used.
115      * @param numTransforms The number of transforms to be in the
116      *  MultiTransformGroup object.
117      * @param canvas The canvas to draw into.  If this is null, it is
118      *  ignored and a canvas will be created by the utility.
119      * @param userConfig The URL to the user's configuration file, used
120      *  by the Viewer object.  Passing in null causes the default values
121      *  to be used.
122      *
123      * @see Locale
124      * @see Viewer
125      * @see ViewingPlatform
126      * @see MultiTransformGroup
127      */
128     ManipulatableUniverse(javax.media.j3d.HiResCoord origin, int numTransforms,
129 						  javax.media.j3d.Canvas3D canvas, URL userConfig) {
130 		super(origin, numTransforms, canvas, userConfig);
131 		setMouseMode(MOUSE_ROTATE |
132 					 MOUSE_TRANSLATE |
133 					 MOUSE_ZOOM |
134 					 MOUSE_ROLL |
135 					 MOUSE_SCALE);
136     }
137 
138     /***
139      * Creates the "view" side of the scene graph.
140      *
141      * @param viewingPlatform The viewingPlatform to use to create
142      *  the "view" side of the scene graph.
143      * @param viewer The viewer object to use to create
144      *  the "view" side of the scene graph.
145      */
146     ManipulatableUniverse(ViewingPlatform viewingPlatform, Viewer viewer) {
147 		super(viewingPlatform, viewer);
148 		setMouseMode(MOUSE_ROTATE |
149 					 MOUSE_TRANSLATE |
150 					 MOUSE_ZOOM |
151 					 MOUSE_ROLL |
152 					 MOUSE_SCALE);
153     }
154 
155 	protected World createNewWorld(int numTransformGroup) {
156 		World world = super.createNewWorld(numTransformGroup);
157 
158 		// setup mouse manipulation
159 		setupMouseBehaviors(world);
160 		setMouseButton1Mode(MOUSE_ROTATE); // default
161 		return world;
162 	}
163 
164 	public void setMouseButton1Mode(int mouseMode) {
165 		if (this.mouseBehavior == null) {
166 			return;
167 		}
168 		this.mouseButton1Mode = mouseMode;
169 		Manipulator man = null;
170 		switch (mouseMode) {
171 		case MOUSE_ROTATE:
172 			man = this.rotate;
173 			break;
174 		case MOUSE_TRANSLATE:
175 			man = this.translate;
176 			break;
177 		case MOUSE_ZOOM:
178 			man = this.zoom;
179 			break;
180 		case MOUSE_ROLL:
181 			man = this.roll;
182 			break;
183 		case MOUSE_SCALE:
184 			man = this.scale;
185 			break;
186 		default:
187 			man = null;
188 			break;
189 		}
190 		this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK, man);
191 	}
192 
193 	public int getMouseButton1Mode() {
194 		return this.mouseButton1Mode;
195 	}
196 	
197 	protected int getMouseMode() {
198 		return this.mouseMode;
199 	}
200 	
201 	/***
202 	 * sets mouse behaviors
203 	 *
204 	 * @param mouseMode OR of MOUSE_ROTATE, MOUSE_TRANSLATE, MOUSE_ZOOM or MOUSE_SCALE.
205 	*/
206 	protected void setMouseMode(int mouseMode) {
207 		this.mouseMode = mouseMode;
208 		if (this.mouseBehavior == null) {
209 			return;
210 		}
211 		if (this.rotate != null) {
212 			if ((this.mouseMode & MOUSE_ROTATE) > 0) {
213 				this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK,
214 												  this.rotate);
215 			} else {
216 				this.mouseBehavior.removeDragManipulator(InputEvent.BUTTON1_MASK);
217 			}
218 		}
219 		if (this.translate != null) {
220 			if ((this.mouseMode & MOUSE_TRANSLATE) > 0) {
221 				this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
222 												  InputEvent.SHIFT_MASK,
223 												  this.translate);
224 			} else {
225 				this.mouseBehavior.removeDragManipulator(InputEvent.BUTTON1_MASK +
226 													 InputEvent.SHIFT_MASK);
227 			}
228 		}
229 		if (this.zoom != null) {
230 			if ((this.mouseMode & MOUSE_ZOOM) > 0) {
231 				this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
232 												  InputEvent.CTRL_MASK,
233 												  this.zoom);
234 			} else {
235 				this.mouseBehavior.removeDragManipulator(InputEvent.BUTTON1_MASK +
236 													 InputEvent.CTRL_MASK);
237 			}
238 		}
239 		if (this.roll != null) {
240 			if ((this.mouseMode & MOUSE_ROLL) > 0) {
241 				this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
242 													  InputEvent.SHIFT_MASK +
243 													  InputEvent.CTRL_MASK,
244 													  this.roll);
245 			} else {
246 				this.mouseBehavior.removeDragManipulator(InputEvent.BUTTON1_MASK +
247 														 InputEvent.SHIFT_MASK +
248 														 InputEvent.CTRL_MASK);
249 			}
250 		}
251 		if (this.scale != null) {
252 			if ((this.mouseMode & MOUSE_SCALE) > 0) {
253 				this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
254 												  InputEvent.CTRL_MASK +
255 												  InputEvent.ALT_MASK,	
256 												  this.scale);
257 			} else {
258 				this.mouseBehavior.removeDragManipulator(InputEvent.BUTTON1_MASK +
259 													 InputEvent.CTRL_MASK +
260 													 InputEvent.ALT_MASK);
261 			}
262 		}
263 	}
264 
265 	public void manipulate(int mode, Stimulus stimulus) {
266 		Manipulator manipulator = null;
267 		switch (mode) {
268 		case MOUSE_ROTATE:
269 			manipulator = this.rotate;
270 			break;
271 		case MOUSE_TRANSLATE:
272 			manipulator = this.translate;
273 			break;
274 		case MOUSE_ZOOM:
275 			manipulator = this.zoom;
276 			break;
277 		case MOUSE_ROLL:
278 			manipulator = this.roll;
279 			break;
280 		case MOUSE_SCALE:
281 			manipulator = this.scale;
282 			break;
283 		}
284 		if (manipulator != null) {
285 			manipulator.processStimulus(stimulus);
286 		}
287 	}
288 	
289 	protected void setupMouseBehaviors(World world) {
290 		this.rotate = new Rotate(this.currentTG);
291 		this.translate = new Translate(this.currentTG);
292 		this.zoom = new Zoom(this.currentTG);
293 		this.roll = new Roll(this.currentTG);		
294 		this.scale = new Scale(this.currentTG);
295 
296 		javax.media.j3d.TransformGroup tg = world.getWorldTransform();
297 		this.mouseBehavior = new MouseManipulatorBehavior(tg);
298 		this.mouseBehavior.setSchedulingBounds(J3DUtil.DEFAULT_BOUNDS);
299 		
300 		// register all manipulators.
301   		this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK,
302 											  this.rotate);
303 		this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
304 											  InputEvent.SHIFT_MASK,
305 											  this.translate);
306 		this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
307 											  InputEvent.CTRL_MASK,
308 											  this.zoom);
309   		this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
310 											  InputEvent.SHIFT_MASK +
311 											  InputEvent.CTRL_MASK,
312 											  this.roll);
313 		this.mouseBehavior.addDragManipulator(InputEvent.BUTTON1_MASK +
314 											  InputEvent.CTRL_MASK +
315 											  InputEvent.ALT_MASK,
316 											  this.scale);
317 		
318 		// the parent of the mouse behavior shold be world TransformGroup.
319   		world.addChild(this.mouseBehavior);	
320 	}		
321 
322 	private void updateTargetTG(javax.media.j3d.TransformGroup target, boolean useL2U, boolean invertMouseInput) {
323 		// only rotation needs to be reversed.
324 		this.rotate.setInvert(invertMouseInput);
325 
326 		this.rotate.setTransformGroup(target);		
327 		this.translate.setTransformGroup(target);
328 		this.zoom.setTransformGroup(target);
329 		this.roll.setTransformGroup(target);
330 		this.scale.setTransformGroup(target);		
331 
332 		this.rotate.useLocalToUniverseTransform(useL2U);
333 		this.translate.useLocalToUniverseTransform(useL2U);
334 		this.zoom.useLocalToUniverseTransform(useL2U);
335 		this.roll.useLocalToUniverseTransform(useL2U);
336 		this.scale.useLocalToUniverseTransform(useL2U);
337 	}
338 	
339 	protected void updateCenter(Point3d center) {
340 		this.rotate.setCenter(center);		
341 		this.translate.setCenter(center);
342 		this.zoom.setCenter(center);
343 		this.roll.setCenter(center);
344 		this.scale.setCenter(center);
345 	}
346 
347 	/***
348      * Invoked when an object is picked.
349 	* <PRE>
350 	* </PRE>
351 	* 
352 	* @param node the picked node
353 	* @return void
354 	*/
355 	/*
356 	* @param nodeType is the logical OR of one o or more of:
357 	* PickObject.SHAPE3D, PickObject.MORPH, PickObject.PRIMITIVE,
358 	* PickObject.LINK, PickObject.GROUP, PickObject.TRANSFORM_GROUP,
359 	* PickObject.BRANCH_GROUP, PickObject.SWITCH
360 	*/
361 	public void picked(PickMouseEvent event) {
362 		super.picked(event);	// process selectable operations.
363 		MouseEvent mevent = event.getMouseEvent();
364 		int clickCount = mevent.getClickCount();
365 		int cond = mevent.getModifiers();
366 
367 		if ((cond & InputEvent.BUTTON1_MASK) != 0) {
368 			if (clickCount > 1) { // 1st button double-clicked
369 				boolean useL2U = false;
370 				boolean invert = false;
371 				if (this.currentTG == this.viewingTG) {
372 					invert = true; // just for rotation
373 					if (DEBUG) {
374 						System.out.println("ManipulatableUniverse: target = viewer");
375 					}
376 				} else if (this.currentTG == this.worldTG) {
377 					if (DEBUG) {
378 						System.out.println("ManipulatableUniverse: target = world");
379 					}
380 				} else {
381 					useL2U = true;
382 					if (DEBUG) {
383 						System.out.println("ManipulatableUniverse: target = picked object");
384 					}
385 				}
386 				if (DEBUG) {
387 					System.out.println("ManipulatableUniverse:picked center = " + getCenter());
388 				}
389 				updateTargetTG(this.currentTG, useL2U, invert);
390 			}
391 		}
392 		updateCenter(getCenter());
393 	}
394 
395 	public void saveCurrentTransformGroup() {
396 		if (this.currentTG instanceof ResettableTransformGroup) {
397 			((ResettableTransformGroup) this.currentTG).saveTransform();
398 		}
399 	}
400 
401 	public void resetCurrentTransformGroup() {
402 		if (this.currentTG instanceof ResettableTransformGroup) {
403 			((ResettableTransformGroup) this.currentTG).resetTransform();
404 		}
405 	}
406 }