/* Copyright 2006 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.portrayal3d.simple; import sim.portrayal.*; import sim.portrayal3d.*; import sim.display.*; import javax.media.j3d.*; import com.sun.j3d.utils.geometry.*; import sim.display3d.*; import java.awt.*; /** A wrapper for other Portrayal3Ds which also draws a big translucent sphere around them -- useful for distinguishing one object from other similar-looking objects. When you create this CirclePortrayal3D, you will pass in an underlying Portrayal3D which is supposed to draw the actual object; CirclePortrayal3D will then add on the sphere. If the object will draw itself (it's its own Portrayal3D), you can signify this by passing in null for the underlying Portrayal3D. <p>There are certain guidelines you can specify for when the sphere is to be drawn. At construction time you can state that the sphere should <i>only</i> be drawn when the object is selected. Additionally if you call the setCircleShowing(...) function, you can turn off or on sphere drawing entirely for this CirclePortrayal3D. <p>You may specify a color or appearance for the sphere (the default is 25%-opaque flat white). If you specify a color with some degree of alpha, the sphere will be drawn to that degree of transparency. You can also specify a scale -- equivalent to the diameter of the sphere. The default scale (2.0f) draws the sphere in the (-1,-1,-1) to (1,1,1) box. <p>Why's it not called a "SpheredPortrayal3D?" One, because there's no such word as "sphered", you big goof. More importantly, we thought it'd be useful to stay consistent with CircledPortrayal2D. */ public class CircledPortrayal3D extends SimplePortrayal3D { public final static Appearance DEFAULT_CIRCLED_APPEARANCE = appearanceForColor(new Color(255,255,255,63)); public final static double DEFAULT_SCALE = 2.0; double scale; Appearance appearance; SimplePortrayal3D child; public CircledPortrayal3D(SimplePortrayal3D child) { this(child, DEFAULT_SCALE); } public CircledPortrayal3D(SimplePortrayal3D child, double scale) { this(child,scale, false); } public CircledPortrayal3D(SimplePortrayal3D child, double scale, boolean onlyCircleWhenSelected) { this(child,DEFAULT_CIRCLED_APPEARANCE,scale, onlyCircleWhenSelected); } public CircledPortrayal3D(SimplePortrayal3D child, Color color) { this(child,color, DEFAULT_SCALE ,false); } public CircledPortrayal3D(SimplePortrayal3D child, Color color, double scale, boolean onlyCircleWhenSelected) { this(child,appearanceForColor(color),scale,onlyCircleWhenSelected); } public CircledPortrayal3D(SimplePortrayal3D child, Appearance appearance, double scale, boolean onlyCircleWhenSelected) { this.child = child; this.appearance = appearance; this.scale = scale; this.onlyCircleWhenSelected = onlyCircleWhenSelected; } public PolygonAttributes polygonAttributes() { return child.polygonAttributes(); } public Inspector getInspector(LocationWrapper wrapper, GUIState state) { return child.getInspector(wrapper,state); } public String getName(LocationWrapper wrapper) { return child.getName(wrapper); } /** Sets the current display both here and in the child. */ public void setCurrentDisplay(Display3D display) { super.setCurrentDisplay(display); child.setCurrentDisplay(display); } /** Sets the current field portrayal both here and in the child. */ public void setCurrentFieldPortrayal(FieldPortrayal3D p) { super.setCurrentFieldPortrayal(p); child.setCurrentFieldPortrayal(p); } public boolean setSelected(LocationWrapper wrapper, boolean selected) { if (child.setSelected(wrapper,selected)) return super.setSelected(wrapper, selected); else return false; // which will bypass the selection procedure entirely. } public SimplePortrayal3D getChild(Object object) { if (child!=null) return child; else { if (!(object instanceof SimplePortrayal3D)) throw new RuntimeException("Object provided to CircledPortrayal3D is not a SimplePortrayal3D: " + object); return (SimplePortrayal3D) object; } } /** Overrides all drawing. */ boolean showCircle = true; boolean onlyCircleWhenSelected; public void setOnlyCircleWhenSelected(boolean val) { onlyCircleWhenSelected = val; } public boolean getOnlyCircleWhenSelected() { return onlyCircleWhenSelected; } public boolean isCircleShowing() { return showCircle; } public void setCircleShowing(boolean val) { showCircle = val; } void updateSwitch(Switch jswitch, Object object) { if (showCircle && (isSelected(object) || !onlyCircleWhenSelected)) jswitch.setWhichChild( Switch.CHILD_ALL ); else jswitch.setWhichChild( Switch.CHILD_NONE ); } public TransformGroup getModel(Object obj, TransformGroup j3dModel) { if(j3dModel==null) { j3dModel = new TransformGroup(); j3dModel.setCapability(TransformGroup.ALLOW_CHILDREN_READ); j3dModel.clearCapabilityIsFrequent(TransformGroup.ALLOW_CHILDREN_READ); Switch jswitch = new Switch(); jswitch.setCapability(Switch.ALLOW_SWITCH_WRITE); // make a sphere Sphere sphere = new Sphere((float)(scale/2.0),appearance); // it's not pickable clearPickableFlags(sphere); // get the child Node n = getChild(obj).getModel(obj,null); j3dModel.addChild(n); // set at child 0 jswitch.addChild(sphere); j3dModel.addChild(jswitch); // set at child 1 updateSwitch(jswitch, obj); } else { TransformGroup t = (TransformGroup)(j3dModel.getChild(0)); getChild(obj).getModel(obj,t); updateSwitch((Switch)(j3dModel.getChild(1)), obj); } return j3dModel; } }