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 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 top = new MyNode("ROOT");

    View view = renderer.getView();
    MyNode viewNode = new MyNode(view);
    createViewNodes(viewNode);
    top.add(viewNode);
    
    MyNode scene = new MyNode(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 viewNode) {
    
    cards.add(makeViewComponent(viewNode.getNode()), viewNode.getName());
    Enumeration canvases = viewNode.getNode().getAllCanvas3Ds();
    while (canvases.hasMoreElements()) {
      Canvas3D canvas = canvases.nextElement();
      MyNode canvasNode = new MyNode(canvas);
      viewNode.add(canvasNode);
      cards.add(makeCanvasComponent(canvas), canvasNode.getName());
    }
  }
  
  private void createSceneNodes(MyNode scene) {
    
    Node node = scene.getNode();
    cards.add(makeNodeComponent(node), scene.getName());
    if (node instanceof Group) {
      Group group = (Group) node;
      Enumeration children = group.getAllChildren();
      while (children.hasMoreElements()) {
        MyNode tnode = new MyNode(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());
  }
  
}

 

Ads help maintain this website.