001: /*
002: * $RCSfile: WheelControls.java,v $
003: *
004: * Copyright (c) 2007 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.2 $
041: * $Date: 2007/02/09 17:21:55 $
042: * $State: Exp $
043: */
044:
045: package org.jdesktop.j3d.examples.virtual_input_device;
046:
047: import java.awt.*;
048: import java.awt.geom.*;
049: import java.awt.event.*;
050:
051: public class WheelControls extends Canvas implements RotationControls,
052: MouseMotionListener, MouseListener {
053:
054: private final static int NONE = 0;
055: private final static int SLIDE_Y = 1;
056: private final static int SLIDE_X = 2;
057: private final static int SLIDE_Z = 3;
058:
059: private int mode = NONE;
060:
061: private Dimension size;
062: private int thickness;
063: private int diameter;
064: private int space;
065: private int pipSize;
066: private int pipOffset; // Amount pip is below wheel
067: private int margin; // Margin between edge of Canvas and
068: // controls
069:
070: private Polygon yPip;
071: private Rectangle yBackClip;
072:
073: private Polygon xPip;
074: private Rectangle xBackClip;
075:
076: private Polygon zPip;
077:
078: private Rectangle yArea;
079: private Rectangle xArea;
080: private Rectangle zArea;
081:
082: private Point oldMousePos = new Point();
083:
084: float yAngle = 0.0f;
085: float xAngle = 0.0f;
086: float zAngle = 0.0f;
087:
088: float yOrigAngle;
089: float xOrigAngle;
090: float zOrigAngle;
091:
092: float angleStep = (float) Math.PI / 30.0f;
093:
094: public WheelControls() {
095: this (0.0f, 0.0f, 0.0f);
096: }
097:
098: public WheelControls(float rotX, float rotY, float rotZ) {
099: size = new Dimension(200, 200);
100:
101: xAngle = constrainAngle(rotX);
102: yAngle = constrainAngle(rotY);
103: zAngle = constrainAngle(rotZ);
104:
105: yOrigAngle = yAngle;
106: xOrigAngle = xAngle;
107: zOrigAngle = zAngle;
108:
109: setSizes();
110:
111: yPip = new Polygon();
112: yPip.addPoint(0, 0);
113: yPip.addPoint(-pipSize / 2, pipSize);
114: yPip.addPoint(pipSize / 2, pipSize);
115:
116: xPip = new Polygon();
117: xPip.addPoint(0, 0);
118: xPip.addPoint(pipSize, -pipSize / 2);
119: xPip.addPoint(pipSize, pipSize / 2);
120:
121: zPip = new Polygon();
122: zPip.addPoint(diameter / 2, pipOffset);
123: zPip.addPoint(diameter / 2 - pipSize / 2, pipOffset - pipSize);
124: zPip.addPoint(diameter / 2 + pipSize / 2, pipOffset - pipSize);
125:
126: addMouseListener(this );
127: addMouseMotionListener(this );
128: }
129:
130: private void setSizes() {
131: margin = 10;
132: int width = size.width - margin * 2;
133: thickness = width * 7 / 100;
134: diameter = width * 70 / 100;
135: space = width * 10 / 100;
136: pipSize = width * 7 / 100;
137:
138: pipOffset = thickness / 2;
139:
140: }
141:
142: public void paint(Graphics g) {
143: Graphics2D g2 = (Graphics2D) g;
144:
145: g.drawOval(margin, margin, diameter, diameter);
146: zArea = new Rectangle(margin, margin, diameter, diameter);
147: drawZPip(g2, zAngle);
148:
149: g.drawRect(margin, margin + diameter + space, diameter,
150: thickness); // Y Wheel
151: yArea = new Rectangle(margin, margin + diameter + space, margin
152: + diameter, thickness + pipOffset);
153: yBackClip = new Rectangle(margin - thickness, margin + diameter
154: + space + thickness, margin + diameter + thickness * 2,
155: thickness);
156: drawYPip(g2, yAngle);
157:
158: g.drawRect(margin + diameter + space, margin, thickness,
159: diameter); // X Wheel
160: xArea = new Rectangle(margin + diameter + space, margin,
161: thickness + pipOffset, margin + diameter);
162: xBackClip = new Rectangle(
163: margin + diameter + space + thickness, margin
164: - thickness, thickness, margin + diameter
165: + thickness * 2);
166: drawXPip(g2, xAngle);
167:
168: }
169:
170: public float getXAngle() {
171: return xAngle;
172: }
173:
174: public float getYAngle() {
175: return yAngle;
176: }
177:
178: public float getZAngle() {
179: return zAngle;
180: }
181:
182: public void reset() {
183: // Overwrite the old pip
184: drawYPip((Graphics2D) (this .getGraphics()), yAngle);
185: yAngle = yOrigAngle;
186: // Draw the new Pip
187: drawYPip((Graphics2D) (this .getGraphics()), yAngle);
188:
189: // Overwrite the old pip
190: drawXPip((Graphics2D) (this .getGraphics()), xAngle);
191: xAngle = xOrigAngle;
192: // Draw the new Pip
193: drawXPip((Graphics2D) (this .getGraphics()), xAngle);
194:
195: drawZPip((Graphics2D) (this .getGraphics()), zAngle);
196:
197: zAngle = zOrigAngle;
198:
199: drawZPip((Graphics2D) (this .getGraphics()), zAngle);
200: oldMousePos.setLocation(0, 0);
201: }
202:
203: private void drawXPip(Graphics2D g2, float angle) {
204: AffineTransform trans = new AffineTransform();
205: int y;
206: int xOrig = margin + diameter + space;
207: int yOrig = margin;
208: Color origColor = g2.getColor();
209:
210: if (angle <= Math.PI) {
211: y = yOrig
212: + diameter
213: - (int) ((Math.abs(angle - Math.PI / 2) / (Math.PI / 2))
214: * diameter / 2);
215: } else
216: y = yOrig
217: + (int) ((Math.abs((angle - Math.PI * 1.5)) / (Math.PI / 2))
218: * diameter / 2);
219:
220: if (angle < Math.PI / 2 || angle > Math.PI * 1.5)
221: g2.setColor(Color.red); // Infront of wheel
222: else {
223: g2.setColor(Color.black); // Behind Wheel
224: g2.setClip(xBackClip);
225: }
226:
227: g2.setXORMode(getBackground());
228: trans.setToTranslation(xOrig + pipOffset, y);
229: g2.setTransform(trans);
230: g2.fillPolygon(xPip);
231:
232: // Reset graphics context
233: trans.setToIdentity();
234: g2.setTransform(trans);
235: g2.setColor(origColor);
236: g2.setPaintMode();
237: }
238:
239: private void drawYPip(Graphics2D g2, float angle) {
240: AffineTransform trans = new AffineTransform();
241: int x;
242: int xOrig = margin;
243: int yOrig = margin + diameter + space;
244: Color origColor = g2.getColor();
245:
246: if (angle <= Math.PI) {
247: x = xOrig
248: + diameter
249: - (int) ((Math.abs(angle - Math.PI / 2) / (Math.PI / 2))
250: * diameter / 2);
251: } else
252: x = xOrig
253: + (int) ((Math.abs((angle - Math.PI * 1.5)) / (Math.PI / 2))
254: * diameter / 2);
255:
256: if (angle < Math.PI / 2 || angle > Math.PI * 1.5)
257: g2.setColor(Color.red); // Infront on wheel
258: else {
259: g2.setColor(Color.black); // Behind Wheel
260: g2.setClip(yBackClip);
261: }
262:
263: g2.setXORMode(getBackground());
264: trans.setToTranslation(x, yOrig + pipOffset);
265: g2.setTransform(trans);
266: g2.fillPolygon(yPip);
267:
268: // Reset graphics context
269: trans.setToIdentity();
270: g2.setTransform(trans);
271: g2.setColor(origColor);
272: g2.setPaintMode();
273: }
274:
275: private void drawZPip(Graphics2D g2, float zAngle) {
276: AffineTransform trans = new AffineTransform();
277: Color origColor = g2.getColor();
278:
279: trans.translate(margin, margin);
280: trans.rotate(zAngle, diameter / 2, diameter / 2);
281:
282: g2.setXORMode(getBackground());
283: g2.setTransform(trans);
284: g2.setColor(Color.red);
285: g2.fillPolygon(zPip);
286:
287: // Reset graphics context
288: trans.setToIdentity();
289: g2.setTransform(trans);
290: g2.setColor(origColor);
291: g2.setPaintMode();
292: }
293:
294: public Dimension getPreferredSize() {
295: return size;
296: }
297:
298: public void setSize(Dimension d) {
299: // Set size to smallest dimension
300: if (d.width < d.height)
301: size.width = size.height = d.width;
302: else
303: size.width = size.height = d.height;
304: setSizes();
305: }
306:
307: public void mouseClicked(MouseEvent e) {
308: }
309:
310: public void mouseEntered(MouseEvent e) {
311: }
312:
313: public void mouseExited(MouseEvent e) {
314: }
315:
316: public void mousePressed(MouseEvent e) {
317: if (yArea.contains(e.getPoint())) {
318: mode = SLIDE_Y;
319: oldMousePos = e.getPoint();
320: } else if (xArea.contains(e.getPoint())) {
321: mode = SLIDE_X;
322: oldMousePos = e.getPoint();
323: } else if (zArea.contains(e.getPoint())) {
324: mode = SLIDE_Z;
325: oldMousePos = e.getPoint();
326: }
327: }
328:
329: public void mouseReleased(MouseEvent e) {
330: mode = NONE;
331: }
332:
333: public void mouseDragged(MouseEvent e) {
334: Point pos = e.getPoint();
335:
336: int diffX = pos.x - oldMousePos.x;
337: int diffY = pos.y - oldMousePos.y;
338:
339: switch (mode) {
340: case NONE:
341: break;
342: case SLIDE_Y:
343: // Overwrite the old pip
344: drawYPip((Graphics2D) ((Canvas) e.getSource())
345: .getGraphics(), yAngle);
346: if (diffX < 0)
347: yAngle -= angleStep;
348: else if (diffX > 0)
349: yAngle += angleStep;
350:
351: yAngle = constrainAngle(yAngle);
352:
353: // Draw the new Pip
354: drawYPip((Graphics2D) ((Canvas) e.getSource())
355: .getGraphics(), yAngle);
356: oldMousePos = pos;
357: break;
358: case SLIDE_X:
359: // Overwrite the old pip
360: drawXPip((Graphics2D) ((Canvas) e.getSource())
361: .getGraphics(), xAngle);
362: if (diffY < 0)
363: xAngle -= angleStep;
364: else if (diffY > 0)
365: xAngle += angleStep;
366:
367: xAngle = constrainAngle(xAngle);
368:
369: // Draw the new Pip
370: drawXPip((Graphics2D) ((Canvas) e.getSource())
371: .getGraphics(), xAngle);
372: oldMousePos = pos;
373: break;
374: case SLIDE_Z:
375: drawZPip((Graphics2D) ((Canvas) e.getSource())
376: .getGraphics(), zAngle);
377:
378: if (diffX < 0)
379: zAngle -= angleStep;
380: else if (diffX > 0)
381: zAngle += angleStep;
382:
383: zAngle = constrainAngle(zAngle);
384: drawZPip((Graphics2D) ((Canvas) e.getSource())
385: .getGraphics(), zAngle);
386: oldMousePos = pos;
387: break;
388: default:
389: throw (new RuntimeException("Internal Error"));
390: }
391: }
392:
393: public void mouseMoved(MouseEvent e) {
394: }
395:
396: /**
397: * Constrain angle to be 0<angle<2PI
398: */
399: private float constrainAngle(float angle) {
400: if (angle > (float) Math.PI * 2)
401: return angle - (float) Math.PI * 2;
402: if (angle < 0.0f)
403: return angle + (float) Math.PI * 2;
404: return angle;
405: }
406: }
|