/***************************************************************************** * Web3d.org Copyright (c) 2001 * Java Source * * This source is licensed under the GNU LGPL v2.1 * Please read http://www.gnu.org/copyleft/lgpl.html for more information * * This software comes with the standard NO WARRANTY disclaimer for any * purpose. Use it at your own risk. If there's a problem you get to fix it. * ****************************************************************************/ // Standard library imports import org.j3d.ui.navigation.*; import java.awt.BorderLayout; import java.awt.Container; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.swing.JPanel; import javax.swing.JPopupMenu; import org.ietf.uri.*; import java.net.URL; // Application specific imports import org.web3d.vrml.sav.*; import org.web3d.vrml.nodes.*; import org.web3d.vrml.nodes.runtime.*; import org.web3d.vrml.nodes.loader.*; import org.web3d.vrml.renderer.j3d.input.*; import org.web3d.browser.BrowserCore; import org.web3d.vrml.lang.VRMLException; import org.web3d.vrml.lang.TypeConstants; import org.web3d.vrml.parser.VRMLParserFactory; import org.web3d.vrml.parser.FactoryConfigurationError; import org.web3d.vrml.renderer.common.input.LinkSelectionListener; import org.web3d.vrml.renderer.common.input.NavigationStateListener; import org.web3d.vrml.renderer.j3d.J3DSceneBuilderFactory; import org.web3d.vrml.renderer.j3d.browser.OverlayHandler; import org.web3d.vrml.renderer.j3d.browser.VRMLUniverse; import org.web3d.vrml.renderer.j3d.nodes.J3DVRMLNode; import org.web3d.vrml.renderer.j3d.nodes.J3DViewpointNodeType; import org.web3d.vrml.scripting.ScriptEngine; import org.web3d.vrml.scripting.jsai.VRML97ScriptEngine; import org.web3d.vrml.scripting.ecmascript.ECMAScriptEngine; /** * A demonstration application that shows how to put together all of the * Xj3D toolkit into a browser application. *
* This is by no means a fully complete browser, it is just a demonstration * of what can be done. We expect that you will take this code and rip it * apart and put it into your own application. * * @author Justin Couch * @version $Revision: 1.1.1.1 $ */ public class DIYBrowser extends DemoFrame implements ViewpointSelectionListener, LinkSelectionListener, OverlayHandler { // Constants for the URN setup /** Set this to the install directory that UMEL uses */ private static final String UMEL_INSTALL_DIR = null; /** Set this to the install directory that GEOVRML uses */ // private static final String GEOVRML_INSTALL_DIR = null; /** NSS prefix used by UMEL */ private static final String UMEL_PREFIX = "umel"; /** NSS prefix used by GeoVRML */ // private static final String GEOVRML_PREFIX = "geovrml"; /** The universe to place our scene into */ private VRMLUniverse universe; /** The toolbar holding viewpoint information */ private ViewpointToolbar vpToolbar; /** The toolbar holding navigation information */ private NavigationToolbar navToolbar; /** Flag to indicate we are in the setup of the scene currently */ private boolean inSetup; /** Mapping of def'd Viewpoints to their real implementation */ private HashMap viewpointDefMap; /** The current viewpoint model */ private VRMLViewpointNodeType currentViewpoint; /** Place for error messages to go */ private ConsoleWindow console; /** Global clock */ private VRMLClock clock; /** World load manager to help us load files */ private WorldLoaderManager worldLoader; /** The global canvas for rendering */ private Canvas3D canvas; /** * Create an instance of the demo class. */ public DIYBrowser() { super("DIY VRML Browser"); JPopupMenu.setDefaultLightWeightPopupEnabled(false); viewpointDefMap = new HashMap(); J3DSceneBuilderFactory builder_fac = new J3DSceneBuilderFactory(false, true, true, true, true, true, true); VRMLParserFactory parser_fac = null; try { parser_fac = VRMLParserFactory.newVRMLParserFactory(); } catch(FactoryConfigurationError fce) { throw new RuntimeException("Failed to load factory"); } Container content_pane = getContentPane(); JPanel p1 = new JPanel(new BorderLayout()); content_pane.add(p1, BorderLayout.CENTER); console = new ConsoleWindow(); // We also need a canvas to display stuff with and a universe to set // the content in. canvas = new Canvas3D(gfxConfig); View view = new View(); //Alan: Removed till 1.3.1 fixes setCoordinate interaction //view.setMinimumFrameCycleTime(30); view.addCanvas3D(canvas); /* Uncomment this section and comment out the line below if you want to use Event handling coming directly from the canvas rather than using the Java3D behaviour to do so. AWTListenerEventBuffer i_buf = new AWTListenerEventBuffer(); canvas.addMouseListener(i_buf); canvas.addMouseMotionListener(i_buf); canvas.addKeyListener(i_buf); */ UserInputBehavior i_buf = new UserInputBehavior(); // ExternalLoadManager lm = new SimpleLoadManager(); ExternalLoadManager load_manager = new MemCacheLoadManager(); ScriptLoader script_loader = new DefaultScriptLoader(); ScriptManager script_manager = new DefaultScriptManager(); script_manager.setScriptLoader(script_loader); FrameStateManager state_manager = new GeneralisedFrameStateManager(); J3DSensorManager sensor_manager = new DefaultSensorManager(); sensor_manager.setInputBuffer(i_buf); RouteManager route_manager = new DefaultRouteManager(); // route_manager.setRouterFactory(new SimpleRouterFactory()); route_manager.setRouterFactory(new ListsRouterFactory()); worldLoader = new DefaultWorldLoaderManager(state_manager); worldLoader.setErrorReporter(console); worldLoader.registerBuilderFactory(BrowserCore.JAVA3D_RENDERER, builder_fac); worldLoader.registerParserFactory(BrowserCore.JAVA3D_RENDERER, parser_fac); EventModelEvaluator event_model = new GeneralisedEventModelEvaluator(); event_model.initialize(script_manager, route_manager, sensor_manager, state_manager, load_manager); event_model.setErrorReporter(console); universe = new VRMLUniverse(event_model, this); universe.setPrimaryView(view); universe.setLinkSelectionListener(this); // If using the canvas AWTEventListener handler then comment out // these lines. BranchGroup extra_behaviors = new BranchGroup(); extra_behaviors.addChild(i_buf); universe.addSceneGraphExtras(extra_behaviors); clock = universe.getVRMLClock(); ScriptEngine jsai = new VRML97ScriptEngine(universe, route_manager, worldLoader); jsai.setErrorReporter(console); ScriptEngine ecma = new ECMAScriptEngine(universe, route_manager, worldLoader); ecma.setErrorReporter(console); script_loader.registerScriptingEngine(jsai); script_loader.registerScriptingEngine(ecma); p1.add(canvas, BorderLayout.CENTER); JPanel p2 = new JPanel(new BorderLayout()); p1.add(p2, BorderLayout.SOUTH); navToolbar = new NavigationToolbar(); p2.add(navToolbar, BorderLayout.WEST); vpToolbar = new ViewpointToolbar(); vpToolbar.setEnabled(false); vpToolbar.setViewpointSelectionListener(this); p2.add(vpToolbar, BorderLayout.CENTER); // universe.setNavigationStateListener(navToolbar); universe.setLinkSelectionListener(this); setupProperties(universe, worldLoader); console.setVisible(true); DownloadProgressListener dl_list = new DownloadProgressListener(statusLabel, console); ResourceConnection.addGlobalProgressListener(dl_list); } //---------------------------------------------------------- // Methods required by the OverlayHandler interface. //---------------------------------------------------------- /** * Fetch the canvas that will be responsible for having the overlays * composited on them. * * @return The canvas instance to use */ public Canvas3D getPrimaryCanvas() { return canvas; } //---------------------------------------------------------- // Methods required by the LinkSelectionListener interface. //---------------------------------------------------------- /** * Invoked when a link node has been activated. This is the node that has * been selected. * * @param node The selected node */ public void linkSelected(VRMLLinkNodeType node) { String[] url_list = node.getUrl(); boolean success = false; for(int i = 0; i < url_list.length; i++) { if(url_list[i].charAt(0) == '#') { // move to the viewpoint. String def_name = url_list[i].substring(1); VRMLViewpointNodeType vp = (VRMLViewpointNodeType)viewpointDefMap.get(def_name); if(vp != null) { double time = clock.getTime(); if(currentViewpoint != null) currentViewpoint.setBind(false, true, time); vp.setBind(true, true, time); currentViewpoint = vp; success = true; } else { statusLabel.setText("Unknown Viewpoint " + def_name); console.warningReport("Unknown Viewpoint " + def_name, null); } } else { // load the world. try { URL url = new URL(url_list[i]); InputSource is = new InputSource(url); if(success = load(is)) break; } catch(MalformedURLException mue) { statusLabel.setText("Invalid URL"); console.warningReport("Invalid URL: " + url_list[i], mue); } } } if(!success) console.errorReport("No valid URLs were found", null); } //---------------------------------------------------------- // Methods required by the ViewpointSelectionListener interface. //---------------------------------------------------------- /** * A new viewpoint has been selected and this is it. Move to this viewpoint * location according to the requested means. * * @param vp The new viewpoint to use */ public void viewpointSelected(ViewpointData vp) { if(inSetup) return; double time = clock.getTime(); if(currentViewpoint != null) currentViewpoint.setBind(false, true, time); VRMLViewpointNodeType vp_node = (VRMLViewpointNodeType)vp.userData; vp_node.setBind(true, true, time); currentViewpoint = vp_node; } //---------------------------------------------------------- // Implmentation of base class abstract methods //---------------------------------------------------------- /** * Go to the named URL location. No checking is done other than to make * sure it is a valid URL. * * @param url The URL to open */ public void gotoLocation(URL url) { InputSource is = new InputSource(url); load(is); } /** * Load the named file. The file is checked to make sure that it exists * before calling this method. * * @param file The file to load */ public void gotoLocation(File file) { InputSource is = new InputSource(file); load(is); } protected void setWarning(String msg) { statusLabel.setText(msg); console.warningReport(msg, null); } protected void setError(String msg) { statusLabel.setText(msg); console.errorReport(msg, null); } //---------------------------------------------------------- // Local convenience methods //---------------------------------------------------------- /** * Do all the parsing work. Convenience method for all to call internally * * @param is The inputsource for this reader * @return true if the world loaded correctly */ private boolean load(InputSource is) { inSetup = true; boolean ret_val = false; WorldLoader loader = worldLoader.fetchLoader(); VRMLScene parsed_scene = null; try { parsed_scene = loader.loadNow(universe, is); } catch(Exception e) { console.errorReport("Failed to load ", e); worldLoader.releaseLoader(loader); return false; } worldLoader.releaseLoader(loader); universe.setScene(parsed_scene); ret_val = true; // Grab the list of viewpoints and place them into the toolbar. ArrayList vp_list = parsed_scene.getByPrimaryType(TypeConstants.ViewpointNodeType); if(vp_list.size() == 0) { vpToolbar.setEnabled(false); return ret_val; } else { vpToolbar.setEnabled(true); } VRMLViewpointNodeType active_vp = universe.getViewpoint(); currentViewpoint = active_vp; ViewpointData active_data = null; J3DVRMLNode node; ViewpointData[] data = new ViewpointData[vp_list.size()]; int count = 0; String desc; TransformGroup tg; int size = vp_list.size(); for(int i = 0; i < size; i++) { node = (J3DVRMLNode)vp_list.get(i); if(node.getPrimaryType() == TypeConstants.ProtoInstance) node = (J3DVRMLNode)((VRMLProtoInstance)node).getImplementationNode(); desc = ((VRMLViewpointNodeType)node).getDescription(); if((desc == null) || (desc.length() == 0)) { desc = "Viewpoint " + count; } tg = ((J3DViewpointNodeType)node).getPlatformGroup(); data[count] = new ViewpointData(desc, count, tg); data[count].userData = node; if(node == active_vp) active_data = data[count]; count++; } vpToolbar.setViewpoints(data); if(active_data != null) vpToolbar.selectViewpoint(active_data); // Finally set up the viewpoint def name list. Have to start from // the list of DEF names as the Viewpoint nodes don't store the DEF // name locally. viewpointDefMap.clear(); Map def_map = parsed_scene.getDEFNodes(); Iterator itr = def_map.keySet().iterator(); while(itr.hasNext()) { String key = (String)itr.next(); Object vp = def_map.get(key); if(vp instanceof VRMLViewpointNodeType) viewpointDefMap.put(key, vp); } inSetup = false; return ret_val; } /** * Create an instance of this class and run it. The single argument, if * supplied is the name of the file to load initially. If not supplied it * will start with a blank document. * * @param argv The list of arguments for this application. */ public static void main(String[] argv) { DIYBrowser browser = new DIYBrowser(); browser.show(); } }