View Javadoc

1   package nl.tudelft.goal.ut2004.visualizer.timeline.map;
2   
3   import java.awt.Point;
4   import java.awt.event.InputEvent;
5   import java.awt.event.MouseEvent;
6   import java.awt.event.MouseListener;
7   import java.awt.event.MouseMotionListener;
8   
9   import javax.swing.event.MouseInputAdapter;
10  
11  import nl.tudelft.goal.ut2004.visualizer.map.MapGLPanel;
12  
13  
14  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
15  import cz.cuni.amis.pogamut.unreal.communication.worldview.map.Box;
16  
17  /**
18   * Class for controling viewport in map.
19   * <p>
20   * The view of map is specified in {@link MapViewpoint}, it consists from
21   * <ul>
22   *  <li>center point - the point in worldspace at which the eye is looking at</li>
23   *  <li>eye point - the worldspace point from which is player looking at the center point</li>
24   *  <li>up vector - determines which direction is up, in worldspace</li>
25   * </ul>
26   * These three components are always orthogonal (the angle between them is 90 degrees).
27   * <p>
28   * The user is controlling the view by dragging the mouse while pressing the buttons:
29   * <ul>
30   *  <li>Left button - deltaX will move your view angle to left or right,
31   *      deltaY will move you forward or backward (no change in height)</li>
32   *  <li>Right button - freely change the direction at which you are looking. </li>
33   *  <li>Left and right button - change position while maintaining the view vector.
34   *      deltaX - left or right, deltaY up or down.</li>
35   *  <li>Triple click anywhere will turn your view to the origin (0,0,0), where map usually is</li>
36   * </ul>
37   * X axis is green,
38   * Y axis is red
39   * Z axis is up/down (up direction is negative)
40   *
41   * @author Honza
42   */
43  public class MapController extends MouseInputAdapter implements MouseListener, MouseMotionListener {
44  
45      final private MapGLPanel panel;
46      final private MapViewpoint viewpoint;
47      private Point last;
48  	private Box bounds;
49      private Location center;
50  
51      public MapController(MapGLPanel panel, MapViewpoint mapViewpoint, Box bounds) {
52          this.panel = panel;
53          this.viewpoint = mapViewpoint;
54          this.center = new Location(bounds.getCenterX(), bounds.getCenterY(), bounds.getCenterZ());
55          this.bounds = bounds;
56      }
57  
58      public void registerListeners() {
59          panel.addMouseListener(this);
60          panel.addMouseMotionListener(this);
61          panel.addMouseWheelListener(this);
62      }
63  
64      public void unregisterListeners() {
65          panel.removeMouseListener(this);
66          panel.removeMouseMotionListener(this);
67          panel.removeMouseWheelListener(this);
68      }
69  
70      @Override
71      public void mouseClicked(MouseEvent e) {
72         
73      	//Resets the view.
74          if(e.getButton() == MouseEvent.BUTTON2){
75          	viewpoint.setFromViewedBox(bounds);
76          }
77          
78      }
79  
80      
81  
82      @Override
83      public void mousePressed(MouseEvent e) {
84          updateMode(e);
85          last = e.getLocationOnScreen();
86      }
87  
88      @Override
89      public void mouseReleased(MouseEvent e) {
90          updateMode(e);
91          last = e.getLocationOnScreen();
92      }
93  
94      private ModificationStatus updateMode(MouseEvent e) {
95          boolean leftDown = (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK;
96          boolean rightDown = (e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK;
97  
98          if (leftDown && rightDown) {
99              operationMode = ModificationStatus.MOVE_CENTER;
100         } else if (leftDown && !rightDown) {
101             operationMode = ModificationStatus.MOVE_AHEAD;
102         } else if (!leftDown && rightDown) {
103             operationMode = ModificationStatus.ROTATE_EYE;
104         } else {
105             operationMode = ModificationStatus.NONE;
106         }
107         System.out.println("ModificationMode: " + operationMode);
108         return operationMode;
109     }
110 
111     private void changeViewpoint(double deltaX, double deltaY) {
112         // how many pixels are necessary to move one degree
113         double pixelsPerDegree = 5;
114         // how many ut units is one pixel
115         double unitsPerPixel = 10;
116         switch (operationMode) {
117             case ROTATE_EYE:
118                 rotateEye((deltaX) / pixelsPerDegree, (deltaY) / pixelsPerDegree);
119                 break;
120             case MOVE_CENTER:
121                 moveCenter(deltaX * unitsPerPixel, (deltaY) * unitsPerPixel);
122                 break;
123             case MOVE_AHEAD:
124                 moveAhead(deltaY * unitsPerPixel, deltaX / pixelsPerDegree);
125                 break;
126         }
127     }
128 
129     private void moveAhead(double distance, double angle) {
130         Location forward = viewpoint.getEye2Center().getNormalized().scale(-distance);
131         forward = forward.setZ(0);
132         viewpoint.move(forward);
133         viewpoint.rotateCenter(new Location(0, 0, 1), angle);
134     }
135 
136     @Override
137     public void mouseDragged(MouseEvent e) {
138         Point current = e.getLocationOnScreen();
139 
140         int deltaX = current.x - last.x;
141         int deltaY = current.y - last.y;
142 
143         changeViewpoint(deltaX, deltaY);
144 
145         //unregisterListeners();
146         //robot.mouseMove(last.x, last.y);
147         //registerListeners();
148 
149         last = current;
150     }
151 
152     /**
153      * Rotate eye according to the delta move by mouse or other pointer.
154      * <p>
155      * @param leftRightAngle how many degrees should I turn to left or right
156      * @param upDownAngle how many degrees should I move my "viewangle" up or down
157      */
158     private void rotateEye(double leftRightAngle, double upDownAngle) {
159         // rotate up/down
160         viewpoint.rotateCenter(viewpoint.getRightVector(), upDownAngle);
161 
162         // rotate left/right
163         viewpoint.rotateCenter(new Location(0, 0, 1), leftRightAngle);
164     }
165 
166     private void moveCenter(double deltaX, double deltaY) {
167         // horizontal movement
168         Location right = viewpoint.getRightVector().getNormalized().scale(-deltaX);
169         viewpoint.move(right);
170 
171         // vertical movement
172         Location up = new Location(0, 0, deltaY);
173         System.out.println("MoveCenter up " + up);
174         viewpoint.move(up);
175     }
176 
177     private enum ModificationStatus {
178 
179         NONE,
180         /** look around, only 180 degrees */
181         ROTATE_EYE,
182         /** move center up/down and left/right     */
183         MOVE_CENTER,
184         /** move ahead and turn */
185         MOVE_AHEAD,
186     }
187     private ModificationStatus operationMode = ModificationStatus.NONE;
188 }