001    /*
002     * $RCSfile: MouseTranslate.java,v $
003     *
004     * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved.
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions
008     * are met:
009     *
010     * - Redistribution of source code must retain the above copyright
011     *   notice, this list of conditions and the following disclaimer.
012     *
013     * - Redistribution in binary form must reproduce the above copyright
014     *   notice, this list of conditions and the following disclaimer in
015     *   the documentation and/or other materials provided with the
016     *   distribution.
017     *
018     * Neither the name of Sun Microsystems, Inc. or the names of
019     * contributors may be used to endorse or promote products derived
020     * from this software without specific prior written permission.
021     *
022     * This software is provided "AS IS," without a warranty of any
023     * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024     * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025     * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026     * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027     * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028     * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029     * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030     * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031     * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032     * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033     * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034     * POSSIBILITY OF SUCH DAMAGES.
035     *
036     * You acknowledge that this software is not designed, licensed or
037     * intended for use in the design, construction, operation or
038     * maintenance of any nuclear facility.
039     *
040     * $Revision: 1.1 $
041     * $Date: 2004/06/09 04:10:25 $
042     * $State: Exp $
043     */
044    
045    package com.appearance3Dchooser;
046    
047    import java.awt.*;
048    import java.awt.event.*;
049    import java.util.*;
050    
051    import com.sun.j3d.utils.behaviors.mouse.*;
052    import javax.media.j3d.*;
053    import javax.vecmath.*;
054    
055    /**
056     * MouseTranslate is a Java3D behavior object that lets users control the
057     * translation (X, Y) of an object via a mouse drag motion with the third
058     * mouse button (alt-click on PC). See MouseRotate for similar usage info.
059     */
060    
061    public class CustomMouseTranslate extends MouseTranslate {
062    
063        double x_factor = .02;
064        double y_factor = .02;
065        Vector3d translation = new Vector3d();
066    
067        private MouseBehaviorCallback callback = null;
068    
069        private Canvas3D haut, droite, gauche, face, big = null;
070    
071        /**
072         * Creates a mouse translate behavior given the transform group.
073         * @param transformGroup The transformGroup to operate on.
074         */
075        public CustomMouseTranslate(TransformGroup transformGroup,
076                                    Canvas3D haut, Canvas3D droite,
077                                    Canvas3D gauche, Canvas3D face, 
078                                    Canvas3D big) {
079          super(transformGroup);
080          this.haut   = haut;
081          this.droite = droite;
082          this.gauche = gauche;
083          this.face   =  face;
084          this.big = big;
085        }
086    
087        /**
088         * Creates a default translate behavior.
089         */
090        public CustomMouseTranslate(){
091          super(0);
092        }
093    
094        /**
095         * Creates a translate behavior.
096         * Note that this behavior still needs a transform
097         * group to work on (use setTransformGroup(tg)) and
098         * the transform group must add this behavior.
099         * @param flags
100         */
101        public CustomMouseTranslate(int flags) {
102          super(flags);
103        }
104    
105        /**
106         * Creates a translate behavior that uses AWT listeners and behavior
107         * posts rather than WakeupOnAWTEvent.  The behavior is added to the
108         * specified Component. A null component can be passed to specify
109         * the behavior should use listeners.  Components can then be added
110         * to the behavior with the addListener(Component c) method.
111         * @param c The Component to add the MouseListener
112         * and MouseMotionListener to.
113         * @since Java 3D 1.2.1
114         */
115        public CustomMouseTranslate(Component c) {
116            super(c, 0);
117        }
118    
119        /**
120         * Creates a translate behavior that uses AWT listeners and behavior
121         * posts rather than WakeupOnAWTEvent.  The behaviors is added to
122         * the specified Component and works on the given TransformGroup.
123         * A null component can be passed to specify the behavior should use
124         * listeners.  Components can then be added to the behavior with the
125         * addListener(Component c) method.
126         * @param c The Component to add the MouseListener and
127         * MouseMotionListener to.
128         * @param transformGroup The TransformGroup to operate on.
129         * @since Java 3D 1.2.1
130         */
131        public CustomMouseTranslate(Component c, TransformGroup transformGroup) {
132            super(c, transformGroup);
133        }
134    
135        /**
136         * Creates a translate behavior that uses AWT listeners and behavior
137         * posts rather than WakeupOnAWTEvent.  The behavior is added to the
138         * specified Component.  A null component can be passed to specify
139         * the behavior should use listeners.  Components can then be added to
140         * the behavior with the addListener(Component c) method.
141         * Note that this behavior still needs a transform
142         * group to work on (use setTransformGroup(tg)) and the transform
143         * group must add this behavior.
144         * @param flags interesting flags (wakeup conditions).
145         * @since Java 3D 1.2.1
146         */
147        public CustomMouseTranslate(Component c, int flags) {
148            super(c, flags);
149        }
150    
151        public void initialize() {
152            super.initialize();
153            if ((flags & INVERT_INPUT) == INVERT_INPUT) {
154                invert = true;
155                x_factor *= -1;
156                y_factor *= -1;
157            }
158        }
159    
160        /**
161         * Return the x-axis movement multipler.
162         **/
163        public double getXFactor() {
164            return x_factor;
165        }
166    
167        /**
168         * Return the y-axis movement multipler.
169         **/
170        public double getYFactor() {
171            return y_factor;
172        }
173    
174        /**
175         * Set the x-axis amd y-axis movement multipler with factor.
176         **/
177        public void setFactor( double factor) {
178            x_factor = y_factor = factor;
179        }
180    
181        /**
182         * Set the x-axis amd y-axis movement multipler with xFactor and yFactor
183         * respectively.
184         **/
185        public void setFactor( double xFactor, double yFactor) {
186            x_factor = xFactor;
187            y_factor = yFactor;
188        }
189    
190        public void processStimulus (Enumeration criteria) {
191            WakeupCriterion wakeup;
192            AWTEvent[] events;
193            MouseEvent evt;
194    //      int id;
195    //      int dx, dy;
196    
197            while (criteria.hasMoreElements()) {
198                wakeup = (WakeupCriterion) criteria.nextElement();
199    
200                if (wakeup instanceof WakeupOnAWTEvent) {
201                    events = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
202                    if (events.length > 0) {
203                        evt = (MouseEvent) events[events.length-1];
204                        doProcess(evt);
205                    }
206                }
207    
208                else if (wakeup instanceof WakeupOnBehaviorPost) {
209                    while (true) {
210                        // access to the queue must be synchronized
211                        synchronized (mouseq) {
212                            if (mouseq.isEmpty()) break;
213                            evt = (MouseEvent)mouseq.remove(0);
214                            // consolodate MOUSE_DRAG events
215                            while ((evt.getID() == MouseEvent.MOUSE_DRAGGED) &&
216                                   !mouseq.isEmpty() &&
217                                   (((MouseEvent)mouseq.get(0)).getID() ==
218                                    MouseEvent.MOUSE_DRAGGED)) {
219                                evt = (MouseEvent)mouseq.remove(0);
220                            }
221                        }
222                        doProcess(evt);
223                    }
224                }
225    
226            }
227            wakeupOn(mouseCriterion);
228        }
229    
230        void doProcess(MouseEvent evt) {
231            int id;
232            int dx, dy;
233    
234            processMouseEvent(evt);
235    
236            if (((buttonPress)&&((flags & MANUAL_WAKEUP) == 0)) ||
237                ((wakeUp)&&((flags & MANUAL_WAKEUP) != 0))){
238                id = evt.getID();
239                if ((id == MouseEvent.MOUSE_DRAGGED) &&
240                    !evt.isAltDown() && evt.isMetaDown()) {
241    
242                    x = evt.getX();
243                    y = evt.getY();
244    
245                    dx = x - x_last;
246                    dy = y - y_last;
247    
248                    if ((!reset) && ((Math.abs(dy) < 50) && (Math.abs(dx) < 50))) {
249                      //System.out.println("dx " + dx + " dy " + dy);
250                      transformGroup.getTransform(currXform);
251    
252                      // Transformations specifiques a chaque canvas 3D
253                      if (evt.getSource().equals(haut)) {
254                        translation.x = dx*x_factor;
255                        translation.y = 0;
256                        translation.z = dy*y_factor;
257                      }
258                      else if (evt.getSource().equals(droite)) {
259                        translation.x = 0;
260                        translation.y = -dy*y_factor;
261                        translation.z = -dx*x_factor;
262                      }
263                      else if (evt.getSource().equals(gauche)) {
264                        translation.x = 0;
265                        translation.y = -dy*y_factor;
266                        translation.z = dx*x_factor;
267                      }
268                      else if (evt.getSource().equals(face)) {
269                        translation.x = dx*x_factor;
270                        translation.y = -dy*y_factor;
271                        translation.z = 0;
272                      }
273                      else if (evt.getSource().equals(big)) {
274                          translation.x = dx*x_factor;
275                          translation.y = -dy*y_factor;
276                          translation.z = 0;
277                      }
278    
279                      transformX.set(translation);
280    
281                     if (invert) {
282                       currXform.mul(currXform, transformX);
283                     } else {
284                       currXform.mul(transformX, currXform);
285                     }
286    
287                        transformGroup.setTransform(currXform);
288    
289                        transformChanged( currXform );
290    
291                        if (callback!=null)
292                            callback.transformChanged( MouseBehaviorCallback.TRANSLATE,
293                                                       currXform );
294    
295                    }
296                    else {
297                        reset = false;
298                    }
299                    x_last = x;
300                    y_last = y;
301                }
302                else if (id == MouseEvent.MOUSE_PRESSED) {
303                    x_last = evt.getX();
304                    y_last = evt.getY();
305                }
306            }
307        }
308    
309        /**
310         * Users can overload this method  which is called every time
311         * the Behavior updates the transform
312         *
313         * Default implementation does nothing
314         */
315        public void transformChanged( Transform3D transform ) {
316        }
317    
318        /**
319         * The transformChanged method in the callback class will
320         * be called every time the transform is updated
321         */
322        public void setupCallback( MouseBehaviorCallback callback ) {
323            this.callback = callback;
324        }
325    }
326