/*
//*****************************************************************************
/*
* @(#) Java3dTree.java
*
* Project: Java3dTree
* Client: Java 3D Community
*
* Project Information:
* dselman@tornadolabs.com
* http://www.tornadolabs.com
*
* @author Daniel Selman: dselman@tornadolabs.com
*/
//*****************************************************************************
// Authors:
// DCS - dselman@tornadolabs.com
// Change History (YYYY/MM/DD). Newest first.
// ==========================================
// [2000/01/04] - DCS - Added detailed reporting for Object (methods and fields)
// [2000/01/04] - DCS - Added detailed reporting for Transform3D
// [2000/01/04] - DCS - Added detailed reporting for Alpha
// [2000/01/04] - DCS - Added detailed reporting for Interpolator
// [1999/12/10] - DCS - Added detailed reporting for ColoringAttributes
// [1999/12/10] - DCS - Added detailed reporting for LineAttributes
// [1999/12/10] - DCS - Added detailed reporting for Material
// [1999/12/10] - DCS - Added detailed reporting for PointAttributes
// [1999/12/10] - DCS - Added detailed reporting for PolygonAttributes
// [1999/12/10] - DCS - Added detailed reporting for RenderingAttributes
// [1999/12/10] - DCS - Added detailed reporting for TexCoordGeneration
// [1999/12/10] - DCS - Added detailed reporting for Texture
// [1999/12/10] - DCS - Added detailed reporting for TransparencyAttributes
// [1999/11/17] - DCS - Added detailed reporting for Behavior.
// [1999/10/25] - DCS - Added detailed reporting for AmbientLight.
// [1999/10/25] - DCS - Added detailed reporting for DirectionalLight.
// [1999/10/25] - DCS - Added detailed reporting for PointLight.
// [1999/10/25] - DCS - Added detailed reporting for SpotLight.
// [1999/10/25] - DCS - Added detailed reporting for Light.
// [1999/10/23] - DCS - Added expansion of Link Nodes by following SharedGroups.
// [1999/10/23] - DCS - Added reporting of Nodes' parents for non-live scenegraphs.
// [1999/10/10] - DCS - Added detailed reporting for Background Node.
// [1999/10/10] - DCS - Added ability to call updateNodes multiple times.
// [1999/10/09] - DCS - Added check for compiled bit so we don't apply capability changes to compiled objects.
// [1999/10/07] - DCS - Fixed bug in Group so it reports CollisionBounds
package com.tornadolabs.j3dtree;
import java.applet.Applet;
import java.awt.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JFrame;
//*****************************************************************************
/**
* Java3dTree
*
* Display a Java 3D scenegraph in a Swing Tree control
*
* @author Daniel Selman
* @version 1.0
*/
//*****************************************************************************
public class Java3dTree extends JFrame implements TreeSelectionListener
{
private final String m_kszLineStyle = "Angled";
private JEditorPane m_TextPane = null;
private JSplitPane m_SplitPane = null;
private VirtualUniverse m_Universe = null;
private JTree m_Tree = null;
private final String m_kszPackageName = "com.tornadolabs.j3dtree.";
private Hashtable m_ObjectInfoTable = null;
public Java3dTree()
{
super( "Java 3D Scenegraph" );
buildObjectInfoTable();
}
private void buildObjectInfoTable()
{
m_ObjectInfoTable = new Hashtable( 100 );
addObjectInfoTableItem( "javax.media.j3d.Alpha" );
addObjectInfoTableItem( "javax.media.j3d.AmbientLight" );
addObjectInfoTableItem( "javax.media.j3d.Appearance" );
addObjectInfoTableItem( "javax.media.j3d.Background" );
addObjectInfoTableItem( "javax.media.j3d.Behavior" );
addObjectInfoTableItem( "javax.media.j3d.Bounds" );
addObjectInfoTableItem( "javax.media.j3d.BoundingLeaf" );
addObjectInfoTableItem( "javax.media.j3d.BranchGroup" );
addObjectInfoTableItem( "javax.media.j3d.ColoringAttributes" );
addObjectInfoTableItem( "javax.media.j3d.Clip" );
addObjectInfoTableItem( "javax.media.j3d.DirectionalLight" );
addObjectInfoTableItem( "javax.media.j3d.Fog" );
addObjectInfoTableItem( "javax.media.j3d.Group" );
addObjectInfoTableItem( "javax.media.j3d.Interpolator" );
addObjectInfoTableItem( "javax.media.j3d.Leaf" );
addObjectInfoTableItem( "javax.media.j3d.Light" );
addObjectInfoTableItem( "javax.media.j3d.LineAttributes" );
addObjectInfoTableItem( "javax.media.j3d.Link" );
addObjectInfoTableItem( "javax.media.j3d.Locale" );
addObjectInfoTableItem( "javax.media.j3d.Material" );
addObjectInfoTableItem( "javax.media.j3d.Morph" );
addObjectInfoTableItem( "javax.media.j3d.OrderedGroup" );
addObjectInfoTableItem( "javax.media.j3d.PointAttributes" );
addObjectInfoTableItem( "javax.media.j3d.PointLight" );
addObjectInfoTableItem( "javax.media.j3d.PolygonAttributes" );
addObjectInfoTableItem( "com.sun.j3d.utils.geometry.Primitive" );
addObjectInfoTableItem( "javax.media.j3d.RenderingAttributes" );
addObjectInfoTableItem( "javax.media.j3d.SceneGraphObject" );
addObjectInfoTableItem( "javax.media.j3d.Shape3D" );
addObjectInfoTableItem( "javax.media.j3d.SharedGroup" );
addObjectInfoTableItem( "com.sun.j3d.utils.universe.SimpleUniverse" );
addObjectInfoTableItem( "javax.media.j3d.Sound" );
addObjectInfoTableItem( "javax.media.j3d.Soundscape" );
addObjectInfoTableItem( "javax.media.j3d.SpotLight" );
addObjectInfoTableItem( "javax.media.j3d.Switch" );
addObjectInfoTableItem( "javax.media.j3d.TexCoordGeneration" );
addObjectInfoTableItem( "javax.media.j3d.Texture" );
addObjectInfoTableItem( "javax.media.j3d.TextureAttributes" );
addObjectInfoTableItem( "javax.media.j3d.Transform3D" );
addObjectInfoTableItem( "javax.media.j3d.TransformGroup" );
addObjectInfoTableItem( "javax.media.j3d.TransparencyAttributes" );
addObjectInfoTableItem( "com.sun.j3d.utils.universe.ViewingPlatform" );
addObjectInfoTableItem( "javax.media.j3d.ViewPlatform" );
addObjectInfoTableItem( "javax.media.j3d.VirtualUniverse" );
}
Class getClass( String szClass )
{
Class classObject = null;
try
{
classObject = Class.forName( szClass );
}
catch( Exception e )
{
try
{
classObject = Class.forName( m_kszPackageName + "ObjectInfo" );
}
catch( Exception e2 )
{
classObject = null;
}
}
return classObject;
}
public void recursiveApplyCapability( Object obj )
{
try
{
if( obj != null )
{
ObjectInfo objInfo = getObjectInfo( obj.getClass().getName() );
if( objInfo != null )
objInfo.setCapabilityBits( this, obj );
}
else
System.err.println( "Warning: ignored null object in recursiveApplyCapability." );
}
catch( Exception e )
{
System.err.println( "Warning: caught Exception applying capabilities: " + e.toString() );
}
}
public void recurseObject( Object obj, DefaultMutableTreeNode parent )
{
if( obj != null )
{
ObjectInfo objInfo = getObjectInfo( obj.getClass().getName() );
if( objInfo != null )
objInfo.addToTree( this, parent, obj );
}
else
System.err.println( "Warning: ignored null object in recurseObject." );
}
ObjectInfo getObjectInfo( String szClass )
{
// look it up, maybe we have a direct match...
// System.out.println( "Looking up: " + szClass );
ObjectInfo objReturn = (ObjectInfo) m_ObjectInfoTable.get( szClass );
// System.out.println( "Direct Match: " + szClass );
Class classObject = null;
try
{
classObject = Class.forName( szClass );
}
catch( Exception e )
{
}
Class parentClass = null;
if( classObject != null )
parentClass = classObject.getSuperclass();
while( objReturn == null && parentClass != null )
{
// if we did not get a match we should walk
// up the inheritance tree and look for a match on a base classe
objReturn = (ObjectInfo) m_ObjectInfoTable.get( parentClass.getName() );
parentClass = parentClass.getSuperclass();
// System.out.println( "Parent Class: " + parentClass );
}
// System.out.println( "Returning: " + objReturn );
return objReturn;
}
private void addObjectInfoTableItem( String szClass )
{
// strip the package name from szClass (everything before the final ".")
int nIndex = szClass.lastIndexOf( "." );
String szTrimedClass = szClass;
if( nIndex > -1 )
szTrimedClass = szClass.substring( nIndex+1, szClass.length() );
szTrimedClass = m_kszPackageName + szTrimedClass;
szTrimedClass += "_Info";
// System.out.println( szClass + "-->" + szTrimedClass );
Class classObject = getClass( szTrimedClass );
try
{
if( classObject != null )
{
m_ObjectInfoTable.put( szClass, classObject.newInstance() );
return;
}
}
catch( Exception e )
{
System.err.println( e.toString() );
}
System.err.println( "Unable to create a new instance of info class for: " + szClass );
}
public void valueChanged(TreeSelectionEvent e)
{
DefaultMutableTreeNode node = (DefaultMutableTreeNode) m_Tree.getLastSelectedPathComponent();
if (node == null)
return;
Object sceneGraphObject = node.getUserObject();
// get the _Info object for the node type
ObjectInfo objInfo = getObjectInfo( sceneGraphObject.getClass().getName() );
try
{
if( objInfo != null )
{
String szText = objInfo.getInfo( sceneGraphObject );
// System.out.println( szText );
displayText( szText );
}
else
displayText( "No Info Handler for:" + sceneGraphObject );
}
catch( Exception ex )
{
displayText( ex.toString() );
}
}
private void displayText( String szText )
{
m_TextPane.setText( szText );
}
public void updateNodes( VirtualUniverse universe )
{
m_Universe = universe;
//Create the top level parent node.
DefaultMutableTreeNode top = new DefaultMutableTreeNode( "Scenegraph" );
recurseObject( m_Universe, top );
//Create a tree that allows one selection at a time.
m_Tree = new JTree(top);
m_Tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
//Listen for when the selection changes.
m_Tree.addTreeSelectionListener( this );
//Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(m_Tree);
Dimension minimumSize = new Dimension(100, 50);
treeView.setMinimumSize(minimumSize);
//Add the scroll panes to a split pane.
if( m_SplitPane == null )
{
//Create the viewing pane.
m_TextPane = new JEditorPane();
m_TextPane.setEditable(false);
JScrollPane htmlView = new JScrollPane(m_TextPane);
m_SplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
m_SplitPane.setTopComponent(treeView);
m_SplitPane.setBottomComponent(htmlView);
htmlView.setMinimumSize(minimumSize);
m_SplitPane.setDividerLocation(100);
m_SplitPane.setPreferredSize(new Dimension(500, 300));
//Add the split pane to this frame.
getContentPane().add( m_SplitPane, BorderLayout.CENTER);
pack();
setVisible( true );
}
else
m_SplitPane.setTopComponent(treeView);
}
} |