001: /*
002: * $Header: /cvs/j3dfly/J3dEditor/src/org/jdesktop/j3dedit/scenegrapheditor/visualtools/PointHighlightControl.java,v 1.1 2005/04/20 22:21:29 paulby Exp $
003: *
004: * Sun Public License Notice
005: *
006: * The contents of this file are subject to the Sun Public License Version
007: * 1.0 (the "License"). You may not use this file except in compliance with
008: * the License. A copy of the License is available at http://www.sun.com/
009: *
010: * The Original Code is the Java 3D(tm) Scene Graph Editor.
011: * The Initial Developer of the Original Code is Paul Byrne.
012: * Portions created by Paul Byrne are Copyright (C) 2002.
013: * All Rights Reserved.
014: *
015: * Contributor(s): Paul Byrne.
016: *
017: **/
018: package org.jdesktop.j3dedit.scenegrapheditor.visualtools;
019:
020: import java.util.ArrayList;
021:
022: import javax.vecmath.Point3f;
023: import javax.vecmath.Vector3f;
024: import javax.vecmath.Point3d;
025: import javax.media.j3d.BranchGroup;
026: import javax.media.j3d.TransformGroup;
027: import javax.media.j3d.Transform3D;
028: import javax.media.j3d.Appearance;
029: import javax.media.j3d.PolygonAttributes;
030: import javax.media.j3d.ColoringAttributes;
031: import javax.media.j3d.SharedGroup;
032: import javax.media.j3d.Link;
033: import javax.media.j3d.IndexedQuadArray;
034: import javax.media.j3d.Shape3D;
035: import javax.media.j3d.Switch;
036:
037: /**
038: * Provides a visual representation for a set of points in 3 space
039: * Default is a wire frame cube centered on the point
040: *
041: * The points can be manipulated in two ways, either through calling methods
042: * in PointHighlightControl, or by calling methods in the points themselves
043: * (PointHightlight). Calling the methods in PointHighlight will call the
044: * relevant PointSelectionListener methods. Calling PointHighlightControl
045: * methods will not notify the listener.
046: *
047: * @author Paul Byrne
048: * @version 1.11, 01/18/02
049: */
050: public class PointHighlightControl extends BranchGroup implements
051: org.jdesktop.j3dfly.event.FlyEventListener {
052:
053: private SharedGroup selectedPointGeom;
054: private SharedGroup pointGeom;
055: private TransformGroup pointScaleTG; // Scale applied to each point
056: private TransformGroup selectedPointScaleTG; // Scale applied to each point
057: private ArrayList points = new ArrayList();
058: private TransformGroup targetOffsetTG; // LocalToVworld for Interpolator
059: private BranchGroup pointsBG;
060:
061: private boolean joinPoints = true; // Join the points with a line
062: private int currentSelection = -1; // Currently Selected point
063: private PointSelectionListener listener;
064:
065: /** Creates new PointHighlight */
066: public PointHighlightControl(PointSelectionListener listener) {
067: super ();
068: this .listener = listener;
069:
070: pointsBG = new BranchGroup();
071: pointsBG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
072: pointsBG.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
073: pointsBG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
074:
075: targetOffsetTG = new TransformGroup();
076: targetOffsetTG
077: .setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
078: targetOffsetTG.addChild(pointsBG);
079: this .addChild(targetOffsetTG);
080:
081: IndexedQuadArray quads = new IndexedQuadArray(8,
082: IndexedQuadArray.COORDINATES, 24);
083: quads.setCoordinates(0, new float[] { 0.5f, 0.5f, 0.5f, -.5f,
084: 0.5f, 0.5f, -.5f, -.5f, 0.5f, 0.5f, -.5f, 0.5f,
085:
086: 0.5f, 0.5f, -.5f, -.5f, 0.5f, -.5f, -.5f, -.5f, -.5f,
087: 0.5f, -.5f, -.5f });
088:
089: quads.setCoordinateIndices(0, new int[] { 0, 1, 2, 3, 7, 6, 5,
090: 4, 4, 5, 1, 0, 6, 7, 3, 2, 4, 0, 3, 7, 1, 5, 6, 2 });
091: Appearance app = new Appearance();
092: //PolygonAttributes poly = new PolygonAttributes();
093: //poly.setPolygonMode( PolygonAttributes.POLYGON_LINE );
094: //poly.setCullFace( PolygonAttributes.CULL_NONE );
095: //app.setPolygonAttributes( poly );
096: ColoringAttributes colorAttr = new ColoringAttributes();
097: colorAttr.setColor(new javax.vecmath.Color3f(0.3f, 0.3f, 0.3f));
098: app.setColoringAttributes(colorAttr);
099: PointHighlightShape3D shape = new PointHighlightShape3D(quads,
100: app);
101:
102: pointGeom = new SharedGroup();
103: pointScaleTG = new TransformGroup();
104: pointScaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
105: pointScaleTG
106: .setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
107:
108: pointGeom.addChild(pointScaleTG);
109: pointScaleTG.addChild(shape);
110:
111: Appearance app2 = new Appearance();
112: ColoringAttributes colorAttr2 = new ColoringAttributes();
113: colorAttr2.setColor(new javax.vecmath.Color3f(1f, 0f, 0f));
114: app2.setColoringAttributes(colorAttr2);
115: PointHighlightShape3D selectedShape = new PointHighlightShape3D(
116: quads, app2);
117: selectedPointGeom = new SharedGroup();
118: selectedPointScaleTG = new TransformGroup();
119: selectedPointScaleTG
120: .setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
121: selectedPointScaleTG
122: .setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
123:
124: selectedPointGeom.addChild(selectedPointScaleTG);
125: selectedPointScaleTG.addChild(selectedShape);
126:
127: //com.sun.j3d.demos.j3dfly.event.EventProcessor.processor().addListener( this, PointScaleEvent.class );
128: }
129:
130: /**
131: * Set the point selection listener
132: */
133: public void setPointSelectionListener(
134: PointSelectionListener listener) {
135: this .listener = listener;
136: }
137:
138: /**
139: * Set the Target for this interpolator
140: *
141: * This is used to extract the LocalToVworld transform for the target
142: * so the points can be positioned correctly
143: */
144: public void setTarget(TransformGroup target) {
145: if (!target.isLive()) {
146: System.out
147: .println("PointHighlightControl target is not live");
148: return;
149: }
150:
151: Transform3D trans = new Transform3D();
152: target.getLocalToVworld(trans);
153: targetOffsetTG.setTransform(trans);
154: }
155:
156: /**
157: * Add a point to the set of points displayed
158: */
159: public void addPoint(Point3f point) {
160: PointHighlight p = new PointHighlight(point, pointGeom,
161: selectedPointGeom, points.size(), this );
162: points.add(p);
163: pointsBG.addChild(p);
164: }
165:
166: /**
167: * Insert a point into the set of points displayed
168: */
169: public void insertPoint(int index, Point3f point) {
170: //System.out.println("Insert "+index +" "+point );
171: if (currentSelection != -1)
172: ((PointHighlight) points.get(currentSelection))
173: .internalSetSelected(false);
174: PointHighlight p = new PointHighlight(point, pointGeom,
175: selectedPointGeom, index, this );
176: points.add(index, p);
177: // Reindex points
178: for (int i = index + 1; i < points.size(); i++)
179: ((PointHighlight) points.get(i)).setIndex(i);
180:
181: pointsBG.insertChild(p, index);
182:
183: if (currentSelection != -1)
184: ((PointHighlight) points.get(currentSelection))
185: .internalSetSelected(true);
186: }
187:
188: /**
189: * Change the position of the point with the specified index
190: */
191: public void movePoint(int index, Point3f newPos) {
192: //System.out.println("Move "+index +" "+newPos );
193: ((PointHighlight) points.get(index)).setPosition(newPos);
194: }
195:
196: /**
197: * Get the number of points
198: */
199: public int getPointCount() {
200: return points.size();
201: }
202:
203: public void selectPoint(int index) {
204: if (currentSelection != -1)
205: ((PointHighlight) points.get(currentSelection))
206: .internalSetSelected(false);
207:
208: ((PointHighlight) points.get(index)).internalSetSelected(true);
209: currentSelection = index;
210: }
211:
212: public void deselectPoint(int index) {
213: if (currentSelection == index)
214: ((PointHighlight) points.get(currentSelection))
215: .internalSetSelected(false);
216: else {
217: System.out.println("Error deselecting point " + index
218: + " it is not current selection");
219: Thread.dumpStack();
220: }
221: }
222:
223: /**
224: * Remove the point from the set of points displayed
225: *
226: * NOT IMPLEMENTED
227: */
228: public void removePoint(Point3f point) {
229: throw new RuntimeException("Not implemented");
230:
231: // MUST handle re-indexing pointIndex in all remaining pointHightlights
232: }
233:
234: /**
235: * Remove all points
236: */
237: public void clear() {
238: points.clear();
239: while (pointsBG.numChildren() != 0)
240: pointsBG.removeChild(0);
241: }
242:
243: /**
244: * Sets the size of the points
245: */
246: public void setPointSize(float size) {
247: Transform3D trans = new Transform3D();
248:
249: pointScaleTG.getTransform(trans);
250: System.out.println(trans);
251: trans.set(size);
252: pointScaleTG.setTransform(trans);
253:
254: selectedPointScaleTG.getTransform(trans);
255: trans.set(size);
256: selectedPointScaleTG.setTransform(trans);
257: }
258:
259: /**
260: * Scale the size of the points
261: */
262: private void scalePointSize(float size) {
263: Transform3D trans = new Transform3D();
264:
265: pointScaleTG.getTransform(trans);
266: double scale = trans.getScale();
267: scale *= size;
268: trans.set(scale);
269: pointScaleTG.setTransform(trans);
270:
271: selectedPointScaleTG.getTransform(trans);
272: trans.set(scale);
273: selectedPointScaleTG.setTransform(trans);
274: }
275:
276: public static PointScaleEvent newPointScaleEvent(float scale) {
277: return new PointScaleEvent(scale);
278: }
279:
280: // TODO - Remove this class once we have scale invariant OrientedShape3D
281: public static class PointScaleEvent extends
282: org.jdesktop.j3dfly.event.FlyEvent {
283: public float scale;
284:
285: public PointScaleEvent(float scale) {
286: this .scale = scale;
287: }
288: }
289:
290: /**
291: * Called by EventProcessor when an event occurs for which this
292: * listener has registered interest
293: *
294: * TODO remove once we have scale invariant OrientedShape3D
295: */
296: public void processFlyEvent(org.jdesktop.j3dfly.event.FlyEvent evt) {
297: scalePointSize(((PointScaleEvent) evt).scale);
298: }
299:
300: public final class PointHighlight extends BranchGroup {
301:
302: private boolean selected;
303: private Switch selectionSwitch;
304: private TransformGroup posTG;
305: private int pointIndex;
306: private Point3f location;
307: private PointHighlightControl control;
308:
309: public PointHighlight(Point3f point, SharedGroup defaultGeom,
310: SharedGroup selectedGeom, int index,
311: PointHighlightControl control) {
312: this .pointIndex = index;
313: this .control = control;
314: this .setCapability(BranchGroup.ALLOW_DETACH);
315: location = point;
316: Transform3D trans = new Transform3D();
317: trans.set(new Vector3f(point));
318: posTG = new TransformGroup(trans);
319: posTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
320:
321: selectionSwitch = new Switch();
322: selectionSwitch.setCapability(Switch.ALLOW_SWITCH_WRITE);
323: selectionSwitch.addChild(new Link(defaultGeom));
324: selectionSwitch.addChild(new Link(selectedGeom));
325:
326: posTG.addChild(selectionSwitch);
327: this .addChild(posTG);
328:
329: this .setCapability(BranchGroup.ENABLE_PICK_REPORTING);
330: selectionSwitch
331: .setCapability(BranchGroup.ALLOW_LOCAL_TO_VWORLD_READ);
332:
333: internalSetSelected(false);
334: }
335:
336: public void getPosition(Point3d location) {
337: location.x = (double) this .location.x;
338: location.y = (double) this .location.y;
339: location.z = (double) this .location.z;
340: }
341:
342: final void setPosition(Point3f newPos) {
343: location = newPos;
344: Transform3D trans = new Transform3D();
345: trans.set(new Vector3f(newPos));
346: posTG.setTransform(trans);
347: }
348:
349: /**
350: * Select this point. This method should only be called by
351: * PointHighlightCOntrol
352: */
353: final void internalSetSelected(boolean selected) {
354: this .selected = selected;
355: if (selected)
356: selectionSwitch.setWhichChild(1);
357: else
358: selectionSwitch.setWhichChild(0);
359: }
360:
361: public final boolean isSelected() {
362: return selected;
363: }
364:
365: public final int getIndex() {
366: return pointIndex;
367: }
368:
369: public final void setIndex(int index) {
370: pointIndex = index;
371: }
372:
373: /**
374: * Move this point
375: *
376: * This will notify the Listener
377: */
378: public void movePoint(javax.vecmath.Point3f newPos) {
379: setPosition(newPos);
380: listener.pointMoved(pointIndex, newPos);
381: }
382:
383: /**
384: * Select this point, if another point is currently selected it
385: * will be deselected.
386: *
387: * The PointSelectionListener will be notified
388: */
389: public final void setSelected(boolean selected) {
390: if (selected)
391: control.selectPoint(pointIndex);
392: else
393: control.deselectPoint(pointIndex);
394: listener.pointSelected(pointIndex, selected);
395: }
396:
397: public String toString() {
398: return new String(pointIndex + " " + location);
399: }
400: }
401:
402: }
|