0001: /*
0002: * $RCSfile: Browser.java,v $
0003: *
0004: * @(#)Browser.java 1.168 99/03/24 15:31:16
0005: *
0006: * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
0007: *
0008: * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
0009: * modify and redistribute this software in source and binary code form,
0010: * provided that i) this copyright notice and license appear on all copies of
0011: * the software; and ii) Licensee does not utilize the software in a manner
0012: * which is disparaging to Sun.
0013: *
0014: * This software is provided "AS IS," without a warranty of any kind. ALL
0015: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
0016: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
0017: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
0018: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
0019: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
0020: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
0021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
0022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
0023: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0024: * POSSIBILITY OF SUCH DAMAGES.
0025: *
0026: * This software is not designed or intended for use in on-line control of
0027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
0028: * the design, construction, operation or maintenance of any nuclear
0029: * facility. Licensee represents and warrants that it will not use or
0030: * redistribute the Software for such purposes.
0031: *
0032: * $Revision: 1.3 $
0033: * $Date: 2006/03/30 08:19:29 $
0034: * $State: Exp $
0035: */
0036: /*
0037: *@Author: Rick Goldberg
0038: *@Author: Doug Gehringer
0039: *@author Nikolai V. Chr.
0040: */
0041: package org.jdesktop.j3d.loaders.vrml97.impl;
0042:
0043: import com.sun.j3d.audioengines.javasound.*;
0044: import java.applet.*;
0045:
0046: import java.awt.AWTEvent;
0047: import java.awt.Frame;
0048: import java.io.BufferedInputStream;
0049: import java.io.ByteArrayInputStream;
0050: import java.io.DataInputStream;
0051: import java.io.InputStream;
0052: import java.lang.System;
0053: import java.net.URL;
0054: import java.net.URLConnection;
0055: import java.util.Enumeration;
0056: import java.util.Hashtable;
0057: import java.util.Stack;
0058: import java.util.Vector;
0059:
0060: import javax.media.j3d.*;
0061: import javax.vecmath.*;
0062:
0063: /**
0064: * Browser J3D structure:
0065: * <p>
0066: * The browser has two kinds of J3D structures: permanent structures which
0067: * are changed the current scene and reset for each URL, and a scene
0068: * branchgraph which holds the J3D tree parsed from the current VRML url.
0069: *
0070: * <p>
0071: * The permanent BranchGroup is called browserRoot. It holds:
0072: * <UL>
0073: * <LI> the browser's behaviors (which control the VRML runtime) </LI>
0074: * <LI> a FogSlot and a BackgroundSlot which groups which hold the currently
0075: * active VRML Fog or Background </LI>
0076: * <LI> The default ViewPlatform, associated with the default Viewpoint </LI>
0077: * </UL>
0078: * <p>
0079: * Views:
0080: * <p>
0081: * There is one View, PhysicalBody and PhysicalEnvironment which are used
0082: * by the currently active Viewpoint and NavigationInfo.
0083: * <p>
0084: * Each file Viewpoint defines a new ViewPlaform, which get associated with
0085: * the view when the viewpoint is bound.
0086: * <p>
0087: * There are default Viewpoint, NavigationInfo, Fog and Background VRML nodes
0088: * which are used if the file does not define them
0089: * <p>
0090: * The initial VP, NI, Fog and BG are the value first seen from the file. This
0091: * value will be bound in loadFinalize().
0092: * <p>
0093: * The VP, NI, Fog and BG stacks are used after the file is loaded. When each
0094: * node is bound, if it is already on the stack, it removed itself from the
0095: * stack and then it pushes itself onto the stack. The top entry on the stack
0096: * is the currently active value.
0097: * <p>
0098: * The browser also has an ambient light and a directional light (the
0099: * headlight). These are added to the TransformGroup which holds the
0100: * ViewPlatform associated with the current Viewpoint.
0101: */
0102:
0103: public class Browser {
0104:
0105: // VRML data
0106: String name = "Java3D VRML'97 Browser";
0107: String version = "unknown";
0108: String description;
0109: float speed;
0110: float frameRate;
0111:
0112: // J3D stuff owned by the browser
0113: Canvas3D canvas;
0114: VirtualUniverse universe;
0115: Locale locale;
0116: PhysicalBody body;
0117: PhysicalEnvironment environment;
0118: View view;
0119: AudioDevice3D audioDevice;
0120:
0121: // the browser's permanent state
0122: BranchGroup browserRoot;
0123: javax.media.j3d.DirectionalLight browserDirLight;
0124: javax.media.j3d.AmbientLight browserAmbLight;
0125: Evagation evagation;// browser behaviors
0126: SimTicker simTicker;
0127: FrameCounter frameCount;
0128:
0129: BranchGroup browserSoundAtts;
0130: BranchGroup browserLightGroup;
0131: RGroup browserBackgroundSlot;
0132: RGroup browserFogSlot;
0133:
0134: // Bindable Node stacks
0135: Stack viewpointStack = null;
0136: Stack navigationInfoStack = null;
0137: Stack fogStack = null;
0138: Stack backgroundStack = null;
0139:
0140: // default VRML objects, used if file does not define these
0141: Viewpoint defViewpoint;
0142: NavigationInfo defNavInfo;
0143: SphereSensor sceneExaminer;
0144: Background defBackground;
0145: Fog defFog;
0146: WorldInfo defWorldInfo;
0147:
0148: // The loader which parses input files
0149: Loader loader;
0150:
0151: // Stuff loaded from the current URL
0152: BranchGroup curScene;// top level J3D nodes from the file
0153: SceneTransform curSceneT;
0154: BoundingSphere sceneBounds;
0155: Vector viewpointList;
0156: // list of SharedGroups to compile
0157: Vector sharedGroups;
0158: // lists of active sensors that the browser must pass events to
0159: Vector timeSensors;
0160: Vector visibilitySensors;
0161: Vector touchSensors;
0162: Vector audioClips;
0163: // the initial values specified by the current file. Null if not specified
0164: // by file
0165: Viewpoint initViewpoint;
0166: NavigationInfo initNavInfo;
0167: Background initBackground;
0168: Fog initFog;
0169: WorldInfo initWorldInfo;
0170:
0171: // the currently active values VRML
0172: NavigationInfo curNavInfo;
0173: Background curBackground;
0174: Fog curFog;
0175: Viewpoint curViewpoint;
0176: WorldInfo curWorldInfo;
0177:
0178: // these are all pieces of the current viewpoint
0179: TransformGroup curViewGroup;
0180: TransformGroup curImplGroup;// see Viewpoint
0181: BranchGroup curImplGroupBranch;
0182: ViewPlatform curViewPlatform;
0183:
0184: // used for batching tranform changes
0185: TransformBuf pendingTransforms = new TransformBuf();
0186:
0187: // state info for startup
0188: boolean simTickEnable = false;
0189: boolean resetOnNextFrame = false;
0190:
0191: // render state
0192: boolean stopped = false;
0193: boolean soundinited = false;
0194:
0195: // the time of the current event
0196: double eventTime;
0197:
0198: // utility stuff
0199: PickRay pickRay = new PickRay();
0200: SceneGraphPath[] stuffPicked;
0201: Transform3D identity = new Transform3D();
0202: RoutePrinter routePrinter = new RoutePrinter();
0203: TreePrinter treePrinter = new TreePrinter();
0204: static boolean printRoutes = false;
0205: int routeDepth = 0;
0206:
0207: // peformance stats
0208: int numTris = 0;
0209: NumFormat numFormat = new NumFormat();
0210: int numFrames = 0;
0211: int numSimTicks = 0;
0212: double renderTime = 0;
0213: double routeTime = 0;
0214: double frameStartTime = 0;
0215: double netStartTime = 0;
0216: double start;
0217: static long memUsage;
0218: static long memLowLimit = 800000;
0219: // debug mode
0220: static boolean debug;
0221: static boolean debug2;//fine grained
0222: boolean timing;
0223: boolean pickEcho;
0224: double attachTime;
0225: boolean checkDelay;
0226: double relTimeBase = 0.0;
0227: Vector debugVec = new Vector();
0228:
0229: // Browser awt info
0230: java.awt.Container container;
0231:
0232: // unclassified stuff
0233: BoundingLeaf defBoundingLeaf;
0234: static Browser instance;
0235: int vi = 0;
0236:
0237: /**
0238: *Constructor for the Browser object
0239: *
0240: *@param vc3d Description of the Parameter
0241: */
0242: public Browser(Canvas3D vc3d) {
0243: canvas = vc3d;
0244: browserInit();
0245: }
0246:
0247: /**Constructor for the Browser object */
0248: public Browser() {
0249: canvas = new Canvas3D(null);
0250: browserInit();
0251: }
0252:
0253: /** Description of the Method */
0254: void browserInit() {
0255: loader = new Loader(this );
0256: timing = loader.timing;
0257: printRoutes = loader.printRoutes;
0258: debug = loader.debug;
0259: initBrowserObjs();
0260: loadDefaults();
0261: }
0262:
0263: /** Description of the Method */
0264: void initBrowserObjs() {
0265: instance = this ;
0266: // set up the VRML objects
0267: loader = new Loader(this );
0268:
0269: fogStack = new Stack();
0270: viewpointStack = new Stack();
0271: backgroundStack = new Stack();
0272: navigationInfoStack = new Stack();
0273:
0274: defViewpoint = new Viewpoint(loader);
0275: defNavInfo = new NavigationInfo(loader);
0276: defBackground = new Background(loader);
0277: defWorldInfo = new WorldInfo(loader);
0278: // no need for default fog - remove after testing
0279: //defFog = new Fog(loader);
0280:
0281: // init the def objects
0282: defViewpoint.initImpl();
0283: defNavInfo.initImpl();
0284: defBackground.initImpl();
0285: //defFog.initImpl();
0286: defWorldInfo.initImpl();
0287:
0288: // initialize the J3D objects
0289: universe = new VirtualUniverse();
0290: locale = new Locale(universe);
0291:
0292: body = new PhysicalBody();
0293: environment = new PhysicalEnvironment();
0294: view = new View();
0295: view.addCanvas3D(canvas);
0296: view.setPhysicalBody(body);
0297: view.setPhysicalEnvironment(environment);
0298:
0299: // This branchgroup holds the browser's J3D state. The browser
0300: // behaviors, fog and background are attached here
0301: browserRoot = new RGroup();
0302: curSceneT = new SceneTransform(loader);
0303: curSceneT.initImpl();
0304:
0305: evagation = new Evagation(this );
0306: evagation
0307: .setSchedulingBoundingLeaf(loader.infiniteBoundingLeaf);
0308: browserRoot.addChild(evagation);
0309:
0310: simTicker = new SimTicker(this );
0311: simTicker
0312: .setSchedulingBoundingLeaf(loader.infiniteBoundingLeaf);
0313: browserRoot.addChild(simTicker);
0314:
0315: browserBackgroundSlot = new RGroup();
0316: browserBackgroundSlot.addChild(defBackground
0317: .getBackgroundImpl());
0318: browserRoot.addChild(browserBackgroundSlot);
0319: browserFogSlot = new RGroup();
0320: //browserFogSlot.addChild(defFog.getFogImpl());
0321: browserRoot.addChild(browserFogSlot);
0322:
0323: // the default Viewpoint is located here
0324: browserRoot.addChild(defViewpoint.getImplNode());
0325: locale.addBranchGraph(browserRoot);
0326:
0327: // The browserLightGroup is added to the Viewpoint's group after the
0328: // view platform (so that it moves with the VP)
0329: browserAmbLight = new javax.media.j3d.AmbientLight(true,
0330: new Color3f(0.2f, 0.2f, 0.2f));
0331: browserAmbLight
0332: .setCapability(javax.media.j3d.Light.ALLOW_STATE_WRITE);
0333: browserDirLight = new javax.media.j3d.DirectionalLight();
0334: browserDirLight.setColor(new Color3f(0.8f, 0.8f, 0.8f));
0335: browserDirLight
0336: .setCapability(javax.media.j3d.Light.ALLOW_STATE_WRITE);
0337: browserDirLight.setInfluencingBounds(loader.infiniteBounds);
0338:
0339: browserLightGroup = new RGroup();
0340: browserLightGroup.addChild(browserDirLight);
0341: browserLightGroup.addChild(browserAmbLight);
0342:
0343: AuralAttributes aa = new AuralAttributes();
0344: aa.setFrequencyScaleFactor(.1f);
0345: Soundscape sc = new Soundscape(loader.infiniteBoundingLeaf
0346: .getRegion(), aa);
0347: browserSoundAtts = new RGroup();
0348: browserSoundAtts.addChild(sc);
0349: browserRoot.addChild(browserSoundAtts);
0350: audioDevice = new JavaSoundMixer(environment);
0351: audioDevice.initialize();
0352: environment.setAudioDevice(audioDevice);
0353:
0354: }
0355:
0356: /** Description of the Method */
0357: void loadDefaults() {
0358: curViewpoint = defViewpoint;
0359: curNavInfo = defNavInfo;
0360: curBackground = defBackground;
0361: //curFog = defFog;
0362:
0363: initViewpoint = null;
0364: initNavInfo = null;
0365: initBackground = null;
0366: initFog = null;
0367:
0368: try {
0369: browserFogSlot.detach();
0370: while (browserFogSlot.numChildren() > 0) {
0371: browserFogSlot.removeChild(0);
0372: }
0373: } catch (Exception e) {
0374: e.printStackTrace();
0375: }
0376: browserFogSlot = new RGroup();
0377: browserRoot.addChild(browserFogSlot);
0378: //browserFogSlot.addChild(defFog.getFogImpl());
0379: browserBackgroundSlot.removeChild(0);
0380: browserBackgroundSlot.addChild(defBackground
0381: .getBackgroundImpl());
0382: updateView();
0383:
0384: }
0385:
0386: /**
0387: * Description of the Method
0388: *
0389: *@param urlString Description of the Parameter
0390: *@param parameter Description of the Parameter
0391: *@exception vrml.InvalidVRMLSyntaxException Description of the Exception
0392: *@exception java.io.IOException Description of the Exception
0393: *@exception java.net.MalformedURLException Description of the Exception
0394: */
0395: public synchronized void loadURL(String[] urlString,
0396: String[] parameter) throws vrml.InvalidVRMLSyntaxException,
0397: java.io.IOException, java.net.MalformedURLException {
0398:
0399: URL worldURL = null;
0400: URL cb = null;
0401:
0402: simTickEnable = false;
0403: simTicker.setEnable(false);
0404:
0405: System.gc();
0406:
0407: urlString[0] = urlString[0].replace((char) 0x5c, (char) 0x2f);
0408:
0409: try {
0410: worldURL = new URL(urlString[0]);
0411: } catch (java.net.MalformedURLException murle) {
0412: if (murle.getMessage().indexOf("no protocol") >= 0) {
0413: try {
0414: if (this .container instanceof Applet) {
0415: cb = ((Applet) (this .container)).getCodeBase();
0416: }
0417: worldURL = new URL(cb, urlString[0]);
0418: } catch (java.net.MalformedURLException murle2) {
0419: murle2.printStackTrace();
0420: }
0421: }
0422: }
0423:
0424: loader.setWorldURL(null, worldURL);
0425: ContentNegotiator cn = new ContentNegotiator(worldURL);
0426: try {
0427: ByteArrayInputStream bais = new ByteArrayInputStream(
0428: (byte[]) cn.getContent());
0429:
0430: doParse(bais);
0431: // cn already threw fnf
0432: } catch (NullPointerException npe) {
0433: java.io.IOException i = new java.io.IOException();
0434: i.initCause(npe);
0435: throw i;
0436: }
0437: loadFinalize();
0438: }
0439:
0440: /**
0441: * Description of the Method
0442: *
0443: *@param sourceVrml Description of the Parameter
0444: */
0445: public void loadStringAsVrml(String sourceVrml) {
0446: simTickEnable = false;
0447: simTicker.setEnable(false);
0448:
0449: //loader.setWorldURL(null, null);
0450:
0451: ByteArrayInputStream bais = new ByteArrayInputStream(sourceVrml
0452: .getBytes());
0453:
0454: doParse(bais);
0455: loadFinalize();
0456:
0457: }
0458:
0459: /**
0460: * Description of the Method
0461: *
0462: *@param is Description of the Parameter
0463: */
0464: void doParse(InputStream is) {
0465:
0466: clear();
0467:
0468: if (loader.debug) {
0469: System.out.println("locale before scene is added:");
0470: browserRoot.detach();
0471: treePrinter.print(browserRoot);
0472: locale.addBranchGraph(browserRoot);
0473: System.out.println();
0474: }
0475:
0476: curScene = new RGroup();
0477: curSceneT = new SceneTransform(loader);
0478: curSceneT.initImpl();
0479:
0480: sceneExaminer = new SphereSensor(loader);
0481: sceneExaminer.autoSpinFrameWait.setValue(1);
0482: // do the safe thing and use the vrml event
0483: MFNode curSceneNodes = (MFNode) curSceneT
0484: .getField("addChildren");
0485: curSceneNodes.addValue(sceneExaminer);
0486:
0487: curScene.addChild(curSceneT.impl);
0488:
0489: Scene scene = null;
0490: try {
0491: scene = loader.load(is);
0492: } catch (Exception e) {
0493: containerMessage(this .container, e.toString());
0494: clear();
0495: }
0496:
0497: // extract the stuff we need from the scene
0498:
0499: // first the top level nodes
0500: for (Enumeration e = scene.objects.elements(); e
0501: .hasMoreElements();) {
0502: BaseNode node = (BaseNode) e.nextElement();
0503: if (node != null) {
0504: if (debug) {
0505: System.out.println("Adding to browser "
0506: + node.toStringId());
0507: }
0508:
0509: node.updateParent(curSceneT.impl);
0510: javax.media.j3d.Node implNode = node.getImplNode();
0511: if (node instanceof GroupBase) {
0512: debugVec.addElement(node);
0513: }
0514:
0515: // bug, assume for now that Viewpoints are not nested within
0516: // any transforms, later we'll need to transform the viewpoint
0517: // by the inverse of what the parent would have been, since,
0518: // that factors out of the tree when we pull the Viewpoint up
0519: // to the top curScene.
0520:
0521: if (node instanceof Viewpoint && implNode != null) {
0522: curScene.addChild(implNode);
0523: } else if (implNode != null) {
0524: implNode
0525: .setCapability(javax.media.j3d.Node.ALLOW_BOUNDS_READ);
0526: implNode
0527: .setCapability(javax.media.j3d.Node.ALLOW_LOCAL_TO_VWORLD_READ);
0528: if (debug) {
0529: System.out.println("curScene: " + curScene);
0530: }
0531: if (debug) {
0532: System.out.println("Adding to scene "
0533: + implNode);
0534: }
0535: curSceneT.impl.addChild(implNode);
0536: if (node instanceof org.jdesktop.j3d.loaders.vrml97.impl.DirectionalLight) {
0537: javax.media.j3d.DirectionalLight dirLight = ((org.jdesktop.j3d.loaders.vrml97.impl.DirectionalLight) node).dirLight;
0538: dirLight.addScope(curSceneT.impl);
0539: }
0540: }
0541: }
0542: }
0543:
0544: // over zealous cleaning
0545: curSceneT.impl
0546: .setCapability(javax.media.j3d.Node.ALLOW_PICKABLE_WRITE);
0547: curSceneT.impl
0548: .setCapability(javax.media.j3d.Node.ENABLE_PICK_REPORTING);
0549: curSceneT.impl.setPickable(true);
0550: // could call
0551: // TreeCleaner.cleanSubgraph(curSceneT);
0552: // but that would be a no-op since ENABLE_PICK_REPORTING is set.
0553: // (it *would* clear the collidable flags, but compile() would still
0554: // not have any effect)
0555:
0556: // then the bindable nodes
0557: viewpointList = scene.viewpoints;
0558: if (scene.viewpoints.size() > 0) {
0559: initViewpoint = (Viewpoint) scene.viewpoints.elementAt(0);
0560: }
0561: if (scene.navInfos.size() > 0) {
0562: initNavInfo = (NavigationInfo) scene.navInfos.elementAt(0);
0563: }
0564: if (scene.backgrounds.size() > 0) {
0565: initBackground = (Background) scene.backgrounds
0566: .elementAt(0);
0567: }
0568: if (scene.fogs.size() > 0) {
0569: initFog = (Fog) scene.fogs.elementAt(0);
0570: }
0571: // and the other stuff we need from the scene
0572: timeSensors = scene.timeSensors;
0573: visibilitySensors = scene.visibilitySensors;
0574: touchSensors = scene.touchSensors;
0575: sharedGroups = scene.sharedGroups;
0576: audioClips = scene.audioClips;
0577: numTris = scene.numTris;
0578:
0579: // this used to be handled in the parser, and could
0580: // be cleaned up some.
0581: if (scene.worldInfo != null) {
0582: curWorldInfo = scene.worldInfo;
0583: } else {
0584: curWorldInfo = defWorldInfo;
0585: }
0586: name = curWorldInfo.title.getValue();
0587: // how much info fits on the titlebar? TBD, implement the
0588: // info popup in the player, but for now this gives us a titlebar.
0589: description = curWorldInfo.info.get1Value(0);
0590:
0591: if (debug) {
0592: System.out.println("Parsed scene makes J3D scene graph:");
0593: treePrinter.print(curScene);
0594: }
0595:
0596: /* Don't bother to compile() since the pickable flag is still on
0597: * for all the Shape3D's
0598: *if(!debug) {
0599: * curScene.compile();
0600: * Enumeration e = sharedGroups.elements();
0601: * while (e.hasMoreElements()) {
0602: * SharedGroup sg = (SharedGroup) e.nextElement();
0603: * sg.compile();
0604: * }
0605: *}
0606: */
0607: //attach the scene to the objRoot
0608: if (debug) {
0609: System.out.println("Locale already has "
0610: + locale.numBranchGraphs());
0611:
0612: browserRoot.detach();
0613: treePrinter.print(browserRoot);
0614: locale.addBranchGraph(browserRoot);
0615: }
0616: locale.addBranchGraph(curScene);
0617:
0618: cleanUp();
0619: if (debug || timing) {
0620: System.out.println("Scene contains " + numTris
0621: + " triangles");
0622: }
0623: if (debug) {
0624: System.out.println("Load completed");
0625: }
0626: }
0627:
0628: /** Description of the Method */
0629: protected void clear() {
0630: int n;
0631:
0632: if (debug) {
0633: System.out.println("Browser:clear()");
0634: }
0635:
0636: if (curScene != null) {
0637: curScene.detach();
0638: }
0639:
0640: curScene = null;
0641:
0642: // load up the defaults. This will move the browserLightGroup to
0643: // the defViewpoint
0644: loadDefaults();
0645:
0646: numTris = 0;
0647: loader.clear();
0648: disableSounds();
0649:
0650: viewpointList = null;
0651: timeSensors = null;
0652: visibilitySensors = null;
0653: touchSensors = null;
0654: audioClips = null;
0655:
0656: viewpointStack.removeAllElements();
0657: navigationInfoStack.removeAllElements();
0658: fogStack.removeAllElements();
0659: backgroundStack.removeAllElements();
0660:
0661: evagation.resetViewpoint();
0662: debugVec = new Vector();
0663: cleanUp();
0664:
0665: audioDevice = new JavaSoundMixer(environment);
0666: audioDevice.initialize();
0667: environment.setAudioDevice(audioDevice);
0668:
0669: }
0670:
0671: /** Description of the Method */
0672: void loadFinalize() {
0673: SFBool set_bind;
0674:
0675: // finalize the TimeSensors
0676: for (int i = 0; i < timeSensors.size(); i++) {
0677: ((TimeSensor) (timeSensors.elementAt(i))).doneParse();
0678: }
0679:
0680: if (printRoutes) {
0681: for (int i = 0; i < touchSensors.size(); i++) {
0682: // print the routes attached to touch sensors
0683: routePrinter.printRoutes((TouchSensor) touchSensors
0684: .elementAt(i));
0685: }
0686: }
0687:
0688: // bind the initial bindables, these will make cur = init
0689: if (initFog != null) {
0690: set_bind = (SFBool) initFog.getEventIn("bind");
0691: set_bind.setValue(true);
0692: }
0693: if (initBackground != null) {
0694: set_bind = (SFBool) initBackground.getEventIn("bind");
0695: set_bind.setValue(true);
0696: }
0697: if (initNavInfo != null) {
0698: set_bind = (SFBool) initNavInfo.getEventIn("bind");
0699: set_bind.setValue(true);
0700: }
0701: // do this last, since it depends on NavInfo
0702: if (initViewpoint != null) {
0703: set_bind = (SFBool) initViewpoint.getEventIn("bind");
0704: set_bind.setValue(true);
0705: }
0706: // binding the VP will reset the View
0707:
0708: // all set
0709: simTickEnable = true;
0710: simTicker.setEnable(true);
0711:
0712: sceneBounds = (BoundingSphere) (((TransformGroup) curSceneT.impl)
0713: .getBounds());
0714: if (sceneBounds.getRadius() == 0.0) {
0715: sceneBounds.setRadius(1.0);
0716: curScene.setBounds(sceneBounds);
0717: }
0718:
0719: curSceneT.setSceneBounds(sceneBounds);
0720:
0721: // arbitrary formula here:
0722: // set the spinKick (ammount to amplify
0723: // mouse angle delta) depending on relative
0724: // size of object.
0725:
0726: sceneExaminer.spinKick.setValue(((float) (sceneBounds
0727: .getRadius())) / 2.0f);
0728:
0729: if (viewpointList.size() == 0) {
0730: curViewpoint.frameObject(sceneBounds);
0731: }
0732:
0733: // do the sounds after all else
0734: querySounds();
0735:
0736: // bug: see javasound duration bug
0737: frameCountAdd();
0738:
0739: initTiming();
0740: resetViewpoint();
0741:
0742: }
0743:
0744: /** Description of the Method */
0745: synchronized void querySounds() {
0746: // sounds should be live, scene should be
0747: // ready; can now initialize the clips with the known
0748: // duration needed to calculate event responses.
0749: for (int i = 0; i < audioClips.size(); i++) {
0750: AudioClip cl = (AudioClip) (audioClips.elementAt(i));
0751: javax.media.j3d.Sound s = cl.sound.soundImpl;
0752: javax.media.j3d.MediaContainer mc = cl.impl;
0753: // need to prepare the sound now if we want to know
0754: // how long it is in duration time.
0755: s.setSoundData(mc);
0756: cl.setDuration(s.getDuration() / 1000.0);
0757: }
0758:
0759: int numChannels = audioDevice.getTotalChannels();
0760: if (debug) {
0761: System.out.println("audioDevice has " + numChannels
0762: + "channels");
0763: }
0764: }
0765:
0766: /** Description of the Method */
0767: void frameCountAdd() {
0768:
0769: // JavaSoundMixer will not report the size of the sound
0770: // until after the scene is live and into a couple of frames.
0771: // this is a temporary workaround which should dissappear
0772: // remove the old frame count
0773: if (browserRoot != null) {
0774: Enumeration e = browserRoot.getAllChildren();
0775: int ind = 0;
0776: try {
0777: while (e.hasMoreElements()) {
0778: if (e.nextElement() != frameCount.rHandle) {
0779: ind++;
0780: } else {
0781: break;
0782: }
0783: }
0784: // double check it was found
0785: if (browserRoot.getChild(ind) == frameCount.rHandle) {
0786: browserRoot.removeChild(ind);
0787: }
0788: } catch (NullPointerException npe) {
0789: ;// first time through, frameCount hasn't been init'd
0790: }
0791:
0792: frameCount = new FrameCounter(this , 4, "soundSync");
0793: //frameCount = new FrameCounter(this,1,"soundSync");
0794: frameCount
0795: .setSchedulingBoundingLeaf(loader.infiniteBoundingLeaf);
0796: browserRoot.addChild(frameCount.rHandle);
0797: }
0798:
0799: }
0800:
0801: /**
0802: * Description of the Method
0803: *
0804: *@param b Description of the Parameter
0805: */
0806: void frameCountCallback(FrameCounter b) {
0807: if (b.name.equals("soundSync")) {
0808: querySounds();
0809: }
0810: }
0811:
0812: // This does two things: keeps track of the initial viewpoint, which
0813: // is bound in loadFinalize() and makes a list of all the viewpoints.
0814: /**
0815: * Adds a feature to the Viewpoint attribute of the Browser object
0816: *
0817: *@param viewpoint The feature to be added to the Viewpoint attribute
0818: */
0819: protected void addViewpoint(Viewpoint viewpoint) {
0820: if (initViewpoint == null) {
0821: // this is the first one we have seen
0822: initViewpoint = viewpoint;
0823: }
0824: viewpointList.addElement(viewpoint);
0825: }
0826:
0827: /** Description of the Method */
0828: void updateView() {
0829: if (debug) {
0830: System.out.println("updateView");
0831: }
0832:
0833: // clear the behavior so as to remove "jump"
0834: evagation.resetViewpoint();
0835:
0836: curImplGroupBranch = (BranchGroup) curViewpoint.impl;
0837: curImplGroup = (TransformGroup) curViewpoint.implOrient;
0838: curViewGroup = (TransformGroup) curViewpoint.implBrowser;
0839: curViewPlatform = (ViewPlatform) curViewpoint.implViewPlatform;
0840:
0841: // re-init the browserGroup transform
0842: // this is the one that "moves"
0843: curViewGroup.setTransform(identity);
0844:
0845: curViewPlatform.setActivationRadius(2112.0f);
0846:
0847: view.setFieldOfView(curViewpoint.fieldOfView.value);
0848: double frontClip;
0849: if (curNavInfo.avatarSize.mfloat.length > 0) {
0850: frontClip = curNavInfo.avatarSize.mfloat[0] / 2.0d;
0851: } else {
0852: // default value
0853: frontClip = 0.25 / 2.0d;
0854: }
0855:
0856: view.setFrontClipDistance(frontClip);
0857: double backClip;
0858: if (curNavInfo.visibilityLimit.value > 0.0) {
0859: backClip = curNavInfo.visibilityLimit.value;
0860: } else {
0861: backClip = frontClip * 2999.0;// no greater than 3000 or loss of
0862: // zbuff resolution
0863: }
0864: view.setBackClipDistance(backClip);
0865:
0866: browserDirLight.setEnable(curNavInfo.headlight.value);
0867: browserAmbLight.setEnable(curNavInfo.headlight.value);
0868:
0869: browserLightGroup.detach();
0870: curViewGroup.addChild(browserLightGroup);
0871:
0872: view.attachViewPlatform(curViewPlatform);
0873: view.setPhysicalBody(body);
0874: view.setPhysicalEnvironment(environment);
0875:
0876: if (timing) {
0877: start = Time.getNow();
0878: }
0879:
0880: evagation.setViewGroup(curViewGroup);
0881:
0882: // cant scale above the viewPlatform, so scale inversly above the scene
0883: // 1.6 meters is avatar's default height
0884:
0885: try {
0886: float s = 1.6f / curNavInfo.avatarSize.mfloat[1];
0887: curSceneT.scale.setValue(s, s, s);
0888: } catch (NullPointerException npe) {
0889: ;//expected 1st time
0890:
0891: } catch (ArrayIndexOutOfBoundsException aioobe) {
0892: ;
0893: }
0894:
0895: cleanUp();
0896: }
0897:
0898: /** Description of the Method */
0899: void updateBackground() {
0900: browserBackgroundSlot.removeChild(0);
0901: browserBackgroundSlot.addChild(curBackground
0902: .getBackgroundImpl());
0903: }
0904:
0905: // the reason why this is special cased so, is that there is not
0906: // "default fog" which kind of inverts the logic
0907: /** Description of the Method */
0908: void updateFog() {
0909: try {
0910: browserFogSlot.detach();
0911: while (browserFogSlot.numChildren() > 0) {
0912: browserFogSlot.removeChild(0);
0913: }
0914: } catch (Exception e) {
0915: e.printStackTrace();
0916: }
0917: browserFogSlot = new RGroup();
0918: browserRoot.addChild(browserFogSlot);
0919: browserFogSlot.addChild(curFog.getFogImpl());
0920: }
0921:
0922: // rename fovChanged ?
0923: /**
0924: * Description of the Method
0925: *
0926: *@param changedView Description of the Parameter
0927: */
0928: void viewChanged(Viewpoint changedView) {
0929: if (changedView == curViewpoint) {
0930: view.setFieldOfView(curViewpoint.fieldOfView.value);
0931: // TODO: handle description
0932: }
0933: }
0934:
0935: /**
0936: * Sets the viewpoint attribute of the Browser object
0937: *
0938: *@param vi The new viewpoint value
0939: */
0940: public void setViewpoint(int vi) {
0941: if (viewpointList.size() > 0) {
0942: // this causes bindableChanged with this view stack
0943: Viewpoint viewpoint = (Viewpoint) viewpointList
0944: .elementAt(vi);
0945: SFBool set_bind = (SFBool) viewpoint.getEventIn("bind");
0946: set_bind.setValue(true);
0947: }
0948: }
0949:
0950: /** Description of the Method */
0951: public void resetViewpoint() {
0952: updateView();// this will clean out any changes
0953: }
0954:
0955: /**
0956: * Gets the viewpointDescriptions attribute of the Browser object
0957: *
0958: *@return The viewpointDescriptions value
0959: */
0960: public String[] getViewpointDescriptions() {
0961: String[] vd = new String[viewpointList.size()];
0962: for (int i = 0; i < viewpointList.size(); i++) {
0963: Viewpoint cur = (Viewpoint) viewpointList.elementAt(i);
0964: if ((cur.description.string == null)
0965: || cur.description.string.equals("")) {
0966: vd[i] = "Viewpoint " + i;
0967: } else {
0968: vd[i] = cur.description.string;
0969: }
0970: }
0971: return vd;
0972: }
0973:
0974: /**
0975: * Description of the Method
0976: *
0977: *@param changedStack Description of the Parameter
0978: */
0979: void bindableChanged(Stack changedStack) {
0980: if (debug) {
0981: System.out.println(this + "bindableChanged()"
0982: + changedStack);
0983: }
0984: if (changedStack == viewpointStack) {
0985: Viewpoint newViewpoint = (Viewpoint) viewpointStack.peek();
0986: if (newViewpoint != null && newViewpoint != curViewpoint) {
0987: if (debug) {
0988: System.out.println(newViewpoint + " bound");
0989: }
0990: curViewpoint = newViewpoint;
0991: updateView();
0992: }
0993: } else if (changedStack == navigationInfoStack) {
0994: NavigationInfo newNavInfo = (NavigationInfo) navigationInfoStack
0995: .peek();
0996: if (newNavInfo != curNavInfo && newNavInfo != null) {
0997: curNavInfo = newNavInfo;
0998: updateView();// view uses NavInfo for some info
0999: // TODO: add updateNavInfo to change browser mode (walk,
1000: // examine) when implemented
1001:
1002: }
1003: } else if (changedStack == backgroundStack) {
1004: Background newBackground = (Background) backgroundStack
1005: .peek();
1006: if (newBackground != curBackground && newBackground != null) {
1007: curBackground = newBackground;
1008: updateBackground();
1009: }
1010: } else if (changedStack == fogStack) {
1011: Fog newFog = (Fog) fogStack.peek();
1012: if (newFog != curFog && newFog != null) {
1013: curFog = newFog;
1014: updateFog();
1015: }
1016: }
1017: }
1018:
1019: /** Description of the Method */
1020: void preRender() {
1021: if (timing) {
1022: frameStartTime = Time.getNow();
1023: if (checkDelay) {
1024: double delay = frameStartTime - attachTime;
1025: System.out.println("Attach to render delay = "
1026: + numFormat.format(delay, 2) + " seconds");
1027: }
1028: }
1029: try {
1030: simTick();
1031: } catch (Exception e0) {
1032: e0.printStackTrace();
1033: }
1034: }
1035:
1036: /** Description of the Method */
1037: void postRender() {
1038: if (timing) {
1039: double now = Time.getNow();
1040: double elapsed = now - frameStartTime;
1041: renderTime += elapsed;
1042: if (elapsed < 0.0) {
1043: System.out.println("Negative elaspsed time for frame: "
1044: + numFormat.format(elapsed, 2) + " seconds");
1045: renderTime = -1;
1046: }
1047: if (checkDelay) {
1048: System.out.println("Time to render first frame = "
1049: + numFormat.format(elapsed, 2) + " seconds");
1050: checkDelay = false;
1051: }
1052: }
1053: numFrames++;
1054: if (timing && ((numFrames % 10) == 0)) {
1055: outputTiming();
1056: }
1057: //try {
1058: //simTick();
1059: //} catch (Exception e0 ) { e0.printStackTrace(); }
1060: // Reset here to that if previous output was between pre and post
1061: // render we don't include output time in timing
1062: if (resetOnNextFrame) {
1063: resetTiming();
1064: resetOnNextFrame = false;
1065: }
1066: }
1067:
1068: /** Description of the Method */
1069: void initTiming() {
1070: Time.setSystemInitTime();
1071: resetTiming();
1072: }
1073:
1074: /** Description of the Method */
1075: void resetTiming() {
1076: double now = Time.getNow();
1077: netStartTime = now;
1078: renderTime = 0.0;
1079: routeTime = 0.0;
1080: numFrames = 0;
1081: numSimTicks = 0;
1082: }
1083:
1084: /**
1085: * Description of the Method
1086: *
1087: *@param timeVal Description of the Parameter
1088: *@return Description of the Return Value
1089: */
1090: double relativeTime(double timeVal) {
1091: if (relTimeBase == 0.0) {
1092: relTimeBase = timeVal;
1093: }
1094: return timeVal - relTimeBase;
1095: }
1096:
1097: /**
1098: * Description of the Method
1099: *
1100: *@return Description of the Return Value
1101: */
1102: double beginRoute() {
1103: if (routeDepth++ == 0) {
1104: eventTime = Time.getNow();
1105: //if(debug2)System.out.println("beginRoute() base eventTime = " +
1106: //relativeTime(eventTime));
1107: }
1108: return eventTime;
1109: }
1110:
1111: /**
1112: * Description of the Method
1113: *
1114: *@param now Description of the Parameter
1115: */
1116: void beginRoute(double now) {
1117: if (routeDepth++ == 0) {
1118: eventTime = now;
1119: //if(debug2)System.out.println("beginRoute(now) base eventTime = " +
1120: //relativeTime(eventTime));
1121: }
1122: }
1123:
1124: /**
1125: * Description of the Method
1126: *
1127: *@return Description of the Return Value
1128: */
1129: double eventTime() {
1130: //if(debug2)System.out.println("EventTime = " + relativeTime(eventTime));
1131: return eventTime;
1132: }
1133:
1134: /** Description of the Method */
1135: void endRoute() {
1136: routeDepth--;
1137: }
1138:
1139: /** Description of the Method */
1140: void simTick() {
1141:
1142: if (true) {
1143: double now = Time.getNow();
1144:
1145: numSimTicks++;
1146:
1147: // any other things that would be better to batch like this?
1148: // mpeg frames to Textures.
1149: pendingTransforms.startBatchLoading();
1150:
1151: beginRoute(now);// set the event time for all events
1152:
1153: if (timeSensors != null) {
1154: for (Enumeration e = timeSensors.elements(); e
1155: .hasMoreElements();) {
1156: TimeSensor ts = (TimeSensor) e.nextElement();
1157: if (ts.enabled.value == true) {
1158: ts.simTick(Time.getNow());
1159: }
1160: }
1161: }
1162:
1163: if (audioClips != null) {
1164: for (Enumeration e = audioClips.elements(); e
1165: .hasMoreElements();) {
1166: AudioClip clip = (AudioClip) e.nextElement();
1167: if (clip.sound != null) {
1168: clip.simTick(now);
1169: }
1170: }
1171: }
1172:
1173: evagation.simTick(now);
1174:
1175: // update the pending transforms
1176: // if any of the previous behaviors had resulted in setValue()
1177: // to any Transforms during this simTick()
1178:
1179: pendingTransforms.stopBatchLoading();
1180:
1181: for (int i = 0; i < pendingTransforms.size; i++) {
1182: pendingTransforms.array[i].updateTransform();
1183: //// just over write and keeping size as a TransforBufMark
1184: pendingTransforms.array[i] = null;// to allow GC
1185: }
1186:
1187: pendingTransforms.size = 0;
1188:
1189: endRoute();
1190:
1191: routeTime += (Time.getNow() - now);
1192:
1193: // hard to track during runtime stuff can be added to the generic
1194: // debug
1195: if (false) {
1196: for (Enumeration e = debugVec.elements(); e
1197: .hasMoreElements();) {
1198: Object o = e.nextElement();
1199: Transform3D t = new Transform3D();
1200: try {
1201: ((Node) o).implNode.getLocalToVworld(t);
1202: } catch (Exception ex) {
1203: ex.printStackTrace();
1204: }
1205: System.out.println(t);
1206: System.out.println("+++++++++++++++++++++++++");
1207: }
1208: }
1209: }
1210: }
1211:
1212: /** Description of the Method */
1213: public void outputTiming() {
1214: if ((numFrames > 0) && timing) {
1215: double now = Time.getNow();
1216: double elapsed = now - netStartTime;
1217: double netTrisPerSec = numTris * numFrames
1218: / (1000 * elapsed);
1219: double trisPerSec = numTris * numFrames
1220: / (1000 * renderTime);
1221:
1222: System.out
1223: .print(numFormat.format(elapsed, 1) + " seconds "
1224: + numFrames + " frames " + "overall: "
1225: + numFormat.format(netTrisPerSec, 1)
1226: + "K tris/sec");
1227: if (renderTime > 0.0) {
1228: System.out.println(" render: "
1229: + numFormat.format(trisPerSec, 1)
1230: + "K tris/sec");
1231: } else {
1232: System.out.println(" render: ???");
1233: }
1234: if (routeTime > 0.0) {
1235: System.out.println(numFormat.format(routeTime, 2)
1236: + " seconds updating nodes ("
1237: + numFormat.format(routeTime * 100.0 / elapsed,
1238: 1)
1239: + "%) "
1240: + numSimTicks
1241: + " ticks "
1242: + numFormat.format(routeTime * 1000.0
1243: / numSimTicks, 1) + "ms/tick");
1244: }
1245: }
1246: resetOnNextFrame = true;
1247: }
1248:
1249: /** Description of the Method */
1250: void disableSounds() {
1251: if (audioClips != null) {
1252: for (Enumeration e = audioClips.elements(); e
1253: .hasMoreElements();) {
1254: AudioClip clip = (AudioClip) e.nextElement();
1255: if (clip.sound != null) {
1256: clip.sound.setEnable(false);
1257: }
1258: }
1259: }
1260: }
1261:
1262: /** Description of the Method */
1263: void enableSounds() {
1264: if (audioClips != null) {
1265: for (Enumeration e = audioClips.elements(); e
1266: .hasMoreElements();) {
1267: AudioClip clip = (AudioClip) e.nextElement();
1268: if (clip.sound != null) {
1269: clip.sound.setEnable(true);
1270: }
1271: }
1272: }
1273: }
1274:
1275: /** Description of the Method */
1276: public void shutDown() {
1277: outputTiming();
1278: disableSounds();
1279: System.exit(0);
1280: }
1281:
1282: /**
1283: * Gets the canvas3D attribute of the Browser object
1284: *
1285: *@return The canvas3D value
1286: */
1287: public Canvas3D getCanvas3D() {
1288: return canvas;
1289: }
1290:
1291: /**
1292: * Description of the Method
1293: *
1294: *@param url Description of the Parameter
1295: *@param node Description of the Parameter
1296: *@param event Description of the Parameter
1297: *@exception vrml.InvalidVRMLSyntaxException Description of the Exception
1298: */
1299: public void createVrmlFromURL(String[] url, BaseNode node,
1300: String event) throws vrml.InvalidVRMLSyntaxException {
1301: ;
1302: }
1303:
1304: /**
1305: * Gets the name attribute of the Browser object
1306: *
1307: *@return The name value
1308: */
1309: public String getName() {
1310: return name;
1311: }
1312:
1313: /**
1314: * Gets the version attribute of the Browser object
1315: *
1316: *@return The version value
1317: */
1318: public String getVersion() {
1319: return version;
1320: }
1321:
1322: /**
1323: * Gets the currentSpeed attribute of the Browser object
1324: *
1325: *@return The currentSpeed value
1326: */
1327: public float getCurrentSpeed() {
1328: return speed;
1329: }
1330:
1331: /**
1332: * Gets the currentFrameRate attribute of the Browser object
1333: *
1334: *@return The currentFrameRate value
1335: */
1336: public float getCurrentFrameRate() {
1337: return frameRate;
1338: }
1339:
1340: /**
1341: * Gets the worldURL attribute of the Browser object
1342: *
1343: *@return The worldURL value
1344: */
1345: public String getWorldURL() {
1346: if (loader.worldURL != null) {
1347: return loader.worldURL.toString();
1348: } else {
1349: return new String("NULL worldURL");
1350: }
1351: }
1352:
1353: /**
1354: * Description of the Method
1355: *
1356: *@param nodes Description of the Parameter
1357: */
1358: public void replaceWorld(BaseNode[] nodes) {
1359: // TODO: implement
1360: }
1361:
1362: /**
1363: * Description of the Method
1364: *
1365: *@param vrmlSyntax Description of the Parameter
1366: *@return Description of the Return Value
1367: *@exception vrml.InvalidVRMLSyntaxException Description of the Exception
1368: */
1369: public BaseNode[] createVrmlFromString(String vrmlSyntax)
1370: throws vrml.InvalidVRMLSyntaxException {
1371: // todo: VRML2parser(String);
1372: //Node node[] = (new VRML2Parser(vrmlSyntax)).returnScene();
1373: return null;
1374: }
1375:
1376: /**
1377: * Sets the defTable attribute of the Browser object
1378: *
1379: *@param t The new defTable value
1380: */
1381: protected void setDefTable(Hashtable t) {
1382: // currently not used, but could be saved for use by EAI
1383: // TODO: memory optimization: set children=null on DEF'd group nodes
1384: // without routes that can change the children and on DEF'd Index
1385: // Face Sets which have child nodes that can't change, etc.
1386: }
1387:
1388: /**
1389: * Sets the description attribute of the Browser object
1390: *
1391: *@param description The new description value
1392: */
1393: public void setDescription(String description) {
1394: this .description = description;
1395: }
1396:
1397: /**
1398: * Gets the description attribute of the Browser object
1399: *
1400: *@return The description value
1401: */
1402: public String getDescription() {
1403: return description;
1404: }
1405:
1406: /**
1407: * Adds a feature to the Route attribute of the Browser object
1408: *
1409: *@param fromNode The feature to be added to the Route attribute
1410: *@param fromEventOut The feature to be added to the Route attribute
1411: *@param toNode The feature to be added to the Route attribute
1412: *@param toEventIn The feature to be added to the Route attribute
1413: */
1414: public void addRoute(BaseNode fromNode, String fromEventOut,
1415: BaseNode toNode, String toEventIn) {
1416: fromEventOut = Field.baseName(fromEventOut);
1417: toEventIn = Field.baseName(toEventIn);
1418: loader.connect(fromNode, fromEventOut, toNode, toEventIn, true);
1419: }
1420:
1421: /**
1422: * Description of the Method
1423: *
1424: *@param fromNode Description of the Parameter
1425: *@param fromEventOut Description of the Parameter
1426: *@param toNode Description of the Parameter
1427: *@param toEventIn Description of the Parameter
1428: */
1429: public void deleteRoute(BaseNode fromNode, String fromEventOut,
1430: BaseNode toNode, String toEventIn) {
1431:
1432: fromEventOut = Field.baseName(fromEventOut);
1433: toEventIn = Field.baseName(toEventIn);
1434:
1435: Field fromField;
1436: Field toField;
1437: if (fromNode instanceof Script) {
1438: fromField = ((Script) fromNode).getField(fromEventOut);
1439: } else {
1440: fromField = ((Node) fromNode).getField(fromEventOut);
1441: }
1442: if (!fromField.isEventOut()) {
1443: throw new vrml.InvalidEventOutException();
1444: }
1445:
1446: if (toNode instanceof Script) {
1447: toField = ((Script) toNode).getField(toEventIn);
1448: } else {
1449: toField = ((Node) toNode).getField(toEventIn);
1450: }
1451: if (!toField.isEventIn()) {
1452: throw new vrml.InvalidEventInException();
1453: }
1454:
1455: fromField.deleteConnection(toField);
1456: // TODO: someday have a "unroute_" method?
1457:
1458: }
1459:
1460: // we may have defined several evagations that the
1461: // canvas didn't know about. ie, walk, fly
1462: /**
1463: * Description of the Method
1464: *
1465: *@param evt Description of the Parameter
1466: */
1467: public void processEvent(AWTEvent evt) {
1468: evagation.processEvent(evt);
1469: }
1470:
1471: /** Description of the Method */
1472: public void startRender() {
1473: // only call this if a stop render has been called
1474: if (stopped) {
1475: canvas.startRenderer();
1476: enableSounds();
1477: }
1478: stopped = false;
1479:
1480: }
1481:
1482: /** Description of the Method */
1483: public void stopRender() {
1484: if (!stopped) {
1485: canvas.stopRenderer();
1486: disableSounds();
1487: }
1488: stopped = true;
1489: }
1490:
1491: /** Description of the Method */
1492: public void cleanUp() {
1493: long mem = Runtime.getRuntime().freeMemory();
1494: long tot = Runtime.getRuntime().totalMemory();
1495: if (mem < memLowLimit) {
1496: if (debug) {
1497: System.out.println("Memory usage: " + mem + " of "
1498: + tot + " left");
1499: }
1500: if (debug) {
1501: System.out.println("Taking out trash...");
1502: }
1503: System.gc();
1504: memUsage = Runtime.getRuntime().freeMemory() - mem;
1505: if (debug) {
1506: System.out.println("Reclaimed " + memUsage + " bytes.");
1507: }
1508: memLowLimit -= 1000000;
1509: if (memLowLimit < 500000) {
1510: memLowLimit = 500000;
1511: }
1512: }
1513: }
1514:
1515: /**
1516: * Gets the uRL attribute of the Browser object
1517: *
1518: *@return The uRL value
1519: */
1520: public URL getURL() {
1521: return loader.worldURL;
1522: }
1523:
1524: /**
1525: * Gets the bytes attribute of the Browser object
1526: *
1527: *@param URLstring Description of the Parameter
1528: *@return The bytes value
1529: */
1530: byte[] getBytes(String URLstring) {
1531:
1532: ContentNegotiator cn;
1533: URL fu;
1534: byte[] buf = new byte[1];
1535: try {
1536: fu = new URL(URLstring);
1537: cn = new ContentNegotiator(fu);
1538: buf = (byte[]) cn.getContent();
1539: } catch (Exception e) {
1540: System.out.println(e);
1541: }
1542: //if(debug)System.out.println(new String(buf));
1543: return buf;
1544: }
1545:
1546: /**
1547: * Gets the relBytes attribute of the Browser object
1548: *
1549: *@param relURL Description of the Parameter
1550: *@return The relBytes value
1551: */
1552: byte[] getRelBytes(String relURL) {
1553: String fullURL = loader.worldURLBaseName + relURL;
1554: byte[] buf = getBytes(fullURL);
1555: return buf;
1556: }
1557:
1558: /**
1559: * Description of the Method
1560: *
1561: *@param e Description of the Parameter
1562: *@return Description of the Return Value
1563: */
1564: int count(Enumeration e) {
1565: int c = 0;
1566: while (e.hasMoreElements()) {
1567: c++;
1568: e.nextElement();
1569: }
1570: return c;
1571: }
1572:
1573: /**
1574: * Description of the Method
1575: *
1576: *@param can Description of the Parameter
1577: */
1578: public void removeCanvas3D(Canvas3D can) {
1579: view.removeCanvas3D(can);
1580: }
1581:
1582: /**
1583: * Adds a feature to the Canvas3D attribute of the Browser object
1584: *
1585: *@param can The feature to be added to the Canvas3D attribute
1586: */
1587: public void addCanvas3D(Canvas3D can) {
1588: view.addCanvas3D(can);
1589: }
1590:
1591: /**
1592: * Sets the aWTContainer attribute of the Browser object
1593: *
1594: *@param container The new aWTContainer value
1595: */
1596: public void setAWTContainer(java.awt.Container container) {
1597: this .container = container;
1598: }
1599:
1600: /**
1601: * Description of the Method
1602: *
1603: *@param c Description of the Parameter
1604: *@param mesg Description of the Parameter
1605: */
1606: void containerMessage(java.awt.Container c, String mesg) {
1607: if (c instanceof Applet) {
1608: ((Applet) (c)).showStatus(mesg);
1609: } else if (c instanceof Frame) {
1610: ((Frame) (c)).setTitle(mesg);
1611: }
1612: }
1613:
1614: /**
1615: * Gets the browser attribute of the Browser class
1616: *
1617: *@return The browser value
1618: */
1619: static Browser getBrowser() {
1620: return instance;
1621: }
1622:
1623: /**
1624: * Sets the autoSmooth attribute of the Browser object
1625: *
1626: *@param s The new autoSmooth value
1627: */
1628: public void setAutoSmooth(boolean s) {
1629: loader.autoSmooth = s;
1630: }
1631:
1632: }
|