package visad.util; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Arrays; import java.util.Enumeration; import javax.media.j3d.Bounds; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; import javax.media.j3d.Group; import javax.media.j3d.Node; import javax.media.j3d.OrderedGroup; import javax.media.j3d.Shape3D; import javax.media.j3d.Switch; import javax.media.j3d.Text3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JToggleButton; import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeSelectionModel; import visad.java3d.DisplayRendererJ3D; public class SceneGraphInspector extends JPanel implements TreeSelectionListener { /** * */ private static final long serialVersionUID = 1L; public static void show(DisplayRendererJ3D renderer) { JFrame frame = new JFrame("VisAD SceneGraph Inspector"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.add(new SceneGraphInspector(renderer)); frame.setSize(800, 480); frame.setVisible(true); } private static String makeName(Object obj) { String name = obj.getClass().getSimpleName(); if (obj instanceof Node) { Node node = (Node) obj; String nodeName = Util.getName(node); if (nodeName != null && nodeName.length() > 0) { name = nodeName; } } else if (obj instanceof String) { return (String) obj; } return name + "@" + obj.hashCode(); } class MyNode<T> extends DefaultMutableTreeNode { private static final long serialVersionUID = 1L; private T node; public MyNode(T node) { this.node = node; } public T getNode() { return node; } public String getName() { return makeName(node); } public String toString() { return getName(); } } private JTree tree; private JPanel cards; public SceneGraphInspector(DisplayRendererJ3D renderer) { cards = new JPanel(); cards.setLayout(new CardLayout()); MyNode<String> top = new MyNode<String>("ROOT"); View view = renderer.getView(); MyNode<View> viewNode = new MyNode<View>(view); createViewNodes(viewNode); top.add(viewNode); MyNode<Node> scene = new MyNode<Node>(renderer.getRoot()); createSceneNodes(scene); top.add(scene); tree = new JTree(top); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(this); Dimension minimumSize = new Dimension(300, 200); JScrollPane treeView = new JScrollPane(tree); treeView.setMinimumSize(minimumSize); JSplitPane split = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, treeView, cards ); setLayout(new BorderLayout()); add(split, BorderLayout.CENTER); for (int i = 0; i < tree.getRowCount(); i++) { tree.expandRow(i); } } private void createViewNodes(MyNode<View> viewNode) { cards.add(makeViewComponent(viewNode.getNode()), viewNode.getName()); Enumeration<Canvas3D> canvases = viewNode.getNode().getAllCanvas3Ds(); while (canvases.hasMoreElements()) { Canvas3D canvas = canvases.nextElement(); MyNode<Canvas3D> canvasNode = new MyNode<Canvas3D>(canvas); viewNode.add(canvasNode); cards.add(makeCanvasComponent(canvas), canvasNode.getName()); } } private void createSceneNodes(MyNode<Node> scene) { Node node = scene.getNode(); cards.add(makeNodeComponent(node), scene.getName()); if (node instanceof Group) { Group group = (Group) node; Enumeration<Node> children = group.getAllChildren(); while (children.hasMoreElements()) { MyNode<Node> tnode = new MyNode<Node>(children.nextElement()); scene.add(tnode); createSceneNodes(tnode); } } } private JPanel makeViewComponent(final View view) { JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(new JLabel("Class: " + view.getClass().getName())); panel.add(new JLabel("AntiAliasing: " + view.getSceneAntialiasingEnable())); int x = view.getViewPolicy(); panel.add(new JLabel("ViewPolicy: " + (x == View.HMD_VIEW ? "HMD_VIEW" : "SCREEN_VIEW"))); String visPolicy = ""; switch (view.getVisibilityPolicy()) { case View.VISIBILITY_DRAW_ALL: visPolicy = "VISIBILITY_DRAW_ALL"; break; case View.VISIBILITY_DRAW_INVISIBLE: visPolicy = "VISIBILITY_DRAW_INVISIBLE"; break; case View.VISIBILITY_DRAW_VISIBLE: visPolicy = "VISIBILITY_DRAW_VISIBLE"; break; } panel.add(new JLabel("VisibilityPolicy: " + visPolicy)); panel.add(new JLabel("FrameNumber: " + view.getFrameNumber())); panel.add(new JLabel("ViewRunning: " + view.isViewRunning())); panel.add(new JLabel("BehaviorSchedulerRunning: " + view.isBehaviorSchedulerRunning())); final JButton startView = new JButton("Start View"); startView.setEnabled(!view.isViewRunning()); final JButton stopView = new JButton("Stop View"); startView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { view.startView(); startView.setEnabled(!view.isViewRunning()); stopView.setEnabled(view.isViewRunning()); } }); stopView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { view.stopView(); startView.setEnabled(!view.isViewRunning()); stopView.setEnabled(view.isViewRunning()); } }); JPanel subPanel = new JPanel(); subPanel.add(startView); subPanel.add(stopView); panel.add(subPanel); final JButton startBehav = new JButton("Start BehaviorScheduler"); startView.setEnabled(!view.isViewRunning()); final JButton stopBehav = new JButton("Stop BehaviorScheduler"); startView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { view.startBehaviorScheduler(); stopBehav.setEnabled(!view.isViewRunning()); startBehav.setEnabled(view.isViewRunning()); } }); stopView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { view.stopBehaviorScheduler(); stopBehav.setEnabled(!view.isViewRunning()); startBehav.setEnabled(view.isViewRunning()); } }); subPanel = new JPanel(); subPanel.add(startView); subPanel.add(stopView); panel.add(subPanel); return panel; } private JPanel makeCanvasComponent(final Canvas3D canvas) { JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(new JLabel("Class: " + canvas.getClass().getName())); panel.add(new JLabel("Name: " + canvas.getName())); panel.add(new JLabel("DoubleBufferEnabled: " + canvas.getDoubleBufferEnable())); panel.add(new JLabel("Height: " + canvas.getHeight())); panel.add(new JLabel("Width: " + canvas.getWidth())); panel.add(new JLabel("IgnoreRepaint: " + canvas.getIgnoreRepaint())); panel.add(new JLabel("MousePosition: " + canvas.getMousePosition())); final JButton startRend = new JButton("Start Renderer"); startRend.setEnabled(!canvas.isRendererRunning()); final JButton stopRend = new JButton("Stop Renderer"); startRend.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { canvas.startRenderer(); startRend.setEnabled(!canvas.isRendererRunning()); stopRend.setEnabled(canvas.isRendererRunning()); } }); stopRend.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { canvas.stopRenderer(); startRend.setEnabled(!canvas.isRendererRunning()); stopRend.setEnabled(canvas.isRendererRunning()); } }); JPanel subPanel = new JPanel(); subPanel.add(startRend); subPanel.add(stopRend); panel.add(subPanel); return panel; } private JPanel makeNodeComponent(final Node node) { final Group parent = (Group) node.getParent(); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(new JLabel("Name: " + makeName(node))); panel.add(new JLabel("Class: " + node.getClass().getName())); panel.add(new JLabel("Live: " + node.isLive())); panel.add(new JLabel("Compiled: " + node.isCompiled())); panel.add(new JLabel("UserData: " + node.getUserData())); panel.add(new JLabel("Pickable: " + node.getPickable())); panel.add(new JLabel("BoundsAutoCompute: " + node.getBoundsAutoCompute())); Bounds bounds = node.getBounds(); if (bounds != null) { panel.add(new JLabel("Bounds.isEmpty: " + bounds.isEmpty())); } if (node instanceof Group) { Group group = (Group) node; panel.add(new JLabel("NumChildren: " + group.numChildren())); if ((node instanceof BranchGroup) && parent != null && group.getCapability(BranchGroup.ALLOW_DETACH)) { final JToggleButton button = new JToggleButton("Detach"); button.setSelected(true); button.addItemListener(new ItemListener(){ public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { parent.addChild(node); button.setText("Detach"); } else if (e.getStateChange() == ItemEvent.DESELECTED) { ((BranchGroup) node).detach(); button.setText("Attach"); } } }); panel.add(button); } else if (node instanceof OrderedGroup) { OrderedGroup ogroup = (OrderedGroup) node; panel.add(new JLabel("Order: " + Arrays.toString(ogroup.getChildIndexOrder()))); } else if (node instanceof TransformGroup) { TransformGroup tgroup = (TransformGroup) node; Transform3D trans = new Transform3D(); tgroup.getTransform(trans); panel.add(new JLabel("TransformMatrix: " + trans.toString())); } if (node instanceof Switch) { final Switch swich = (Switch) node; String[] indexes = new String[swich.numChildren() + 1]; indexes[0] = "None"; for (int i = 1; i < indexes.length; i++) { indexes[i] = "" + (i - 1); } JComboBox comboBox = new JComboBox(indexes); int selected = swich.getWhichChild(); if (selected == Switch.CHILD_NONE) { selected = 0; } comboBox.setSelectedIndex(swich.getWhichChild() + 1); comboBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JComboBox cBox = (JComboBox) e.getSource(); int selected = cBox.getSelectedIndex(); if (selected == 0) { selected = Switch.CHILD_NONE; } else { selected -= 1; } swich.setWhichChild(selected); } }); panel.add(comboBox); } } else { if (node instanceof Shape3D) { Shape3D shape = (Shape3D) node; Geometry geo = shape.getGeometry(); if (geo != null) { panel.add(new JLabel("Geometry: " + geo.getClass().getSimpleName())); if (geo instanceof GeometryArray) { GeometryArray arr = (GeometryArray) geo; panel.add(new JLabel("VertexCount: " + arr.getVertexCount())); } else if (geo instanceof Text3D) { Text3D txt = (Text3D) geo; panel.add(new JLabel("String: \"" + txt.getString()+ "\"")); } } } } return panel; } @Override public void valueChanged(TreeSelectionEvent evt) { MyNode tnode = (MyNode) evt.getPath().getLastPathComponent(); Object node = tnode.getNode(); CardLayout cl = (CardLayout) cards.getLayout(); cl.show(cards, tnode.getName()); } }