0001: /*
0002: * $RCSfile: VirtualUniverse.java,v $
0003: *
0004: * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006: *
0007: * This code is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU General Public License version 2 only, as
0009: * published by the Free Software Foundation. Sun designates this
0010: * particular file as subject to the "Classpath" exception as provided
0011: * by Sun in the LICENSE file that accompanied this code.
0012: *
0013: * This code is distributed in the hope that it will be useful, but WITHOUT
0014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: * version 2 for more details (a copy is included in the LICENSE file that
0017: * accompanied this code).
0018: *
0019: * You should have received a copy of the GNU General Public License version
0020: * 2 along with this work; if not, write to the Free Software Foundation,
0021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022: *
0023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024: * CA 95054 USA or visit www.sun.com if you need additional information or
0025: * have any questions.
0026: *
0027: * $Revision: 1.17 $
0028: * $Date: 2008/02/28 20:17:33 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import java.util.Vector;
0035: import java.util.ArrayList;
0036: import java.util.Enumeration;
0037: import java.util.HashSet;
0038: import java.util.Iterator;
0039: import java.util.Map;
0040: import java.util.logging.Level;
0041: import java.util.logging.Logger;
0042:
0043: /**
0044: * A VirtualUniverse object is the top-level container for all scene
0045: * graphs. A virtual universe consists of a set of Locale objects,
0046: * each of which has a high-resolution position within the virtual
0047: * universe. An application or applet may have more than one
0048: * VirtualUniverse objects, but many applications will need only one.
0049: * Virtual universes are separate entities in that no node object may
0050: * exist in more than one virtual universe at any one time. Likewise,
0051: * the objects in one virtual universe are not visible in, nor do they
0052: * interact with objects in, any other virtual universe.
0053: * <p>
0054: * A VirtualUniverse object defines methods to enumerate its Locale
0055: * objects and to remove them from the virtual universe.
0056: *
0057: * <p>
0058: * For more information, see the
0059: * <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and
0060: * <a href="doc-files/VirtualUniverse.html">Scene Graph Superstructure</a>
0061: * documents.
0062: *
0063: * @see Locale
0064: */
0065:
0066: public class VirtualUniverse extends Object {
0067: // NOTE TO DEVELOPERS:
0068: //
0069: // Developers who modify Java 3D in any way should modify
0070: // the auxiliary implementation vendor string in VersionInfo.java.
0071: // See that file for instructions.
0072:
0073: // The global MasterControl object. There is only one of these
0074: // for all of Java 3D.
0075: static MasterControl mc = null;
0076:
0077: // The lock to acquire before traversing the scene graph
0078: Object sceneGraphLock = new Object();
0079: Object behaviorLock = new Object();
0080:
0081: // A list of locales that are contained within this universe
0082: Vector listOfLocales = new Vector();
0083:
0084: // The list of view platforms.
0085: ArrayList viewPlatforms = new ArrayList();
0086:
0087: // The cached list of vp's
0088: Object[] viewPlatformList = null;
0089:
0090: // A flag that indicates that the list of view platforms has changed
0091: boolean vpChanged = false;
0092:
0093: // The list of backgrounds
0094: Vector backgrounds = new Vector();
0095:
0096: // The list of clips
0097: Vector clips = new Vector();
0098:
0099: // The list of sounds
0100: Vector sounds = new Vector();
0101:
0102: // The list of soundscapes
0103: Vector soundscapes = new Vector();
0104:
0105: // The Behavior Scheduler Thread for this Virtual Universe.
0106: BehaviorScheduler behaviorScheduler = null;
0107:
0108: // The geometry structure for this Universe
0109: GeometryStructure geometryStructure = null;
0110:
0111: // The transform structure for this Universe
0112: TransformStructure transformStructure = null;
0113:
0114: // The behavior structure for this Universe
0115: BehaviorStructure behaviorStructure = null;
0116:
0117: // The sound structure for this Universe
0118: SoundStructure soundStructure = null;
0119:
0120: // The rendering attributes structure for this Universe
0121: RenderingEnvironmentStructure renderingEnvironmentStructure = null;
0122:
0123: // Reference count of users of the RenderingEnvironmentStructure
0124: int renderingEnvironmentStructureRefCount = 0;
0125:
0126: // This is a global counter for node id's.
0127: long nodeIdCount = 0;
0128:
0129: // This is a global counter for view id's.
0130: int viewIdCount = 0;
0131:
0132: // This is a vector of free nodeid's
0133: Vector nodeIdFreeList = new Vector();
0134:
0135: // This is a vector of free viewid's
0136: ArrayList viewIdFreeList = new ArrayList();
0137:
0138: // The number of nodes in this universe
0139: int numNodes = 0;
0140:
0141: // The State object used when branch graphs are added
0142: SetLiveState setLiveState;
0143:
0144: // This is an array of references to objects that need their mirror
0145: // copies updated. It is updated by the traverser and emptied by
0146: // the view thread.
0147: ObjectUpdate[] updateObjects = new ObjectUpdate[16];
0148:
0149: // The number of valid entries in updateObjects
0150: int updateObjectsLen = 0;
0151:
0152: // A list of all mirror geometry object that are dirty
0153: ArrayList dirtyGeomList = new ArrayList();
0154:
0155: // The current primary view for this universe
0156: View currentView;
0157:
0158: // A flag to indicate that we are in a behavior routine
0159: boolean inBehavior = false;
0160:
0161: // Flags to indicate if events need to be delivered
0162: boolean enableComponent = false;
0163: boolean enableFocus = false;
0164: boolean enableKey = false;
0165: boolean enableMouse = false;
0166: boolean enableMouseMotion = false;
0167: boolean enableMouseWheel = false;
0168:
0169: // Keep track of how many active View use this universe
0170: int activeViewCount = 0;
0171:
0172: // Root ThreadGroup for creating Java 3D threads
0173: static ThreadGroup rootThreadGroup;
0174:
0175: // Properties object for getProperties
0176: private static J3dQueryProps properties = null;
0177:
0178: // Flag to indicate that user thread has to
0179: // stop until MC completely register/unregister View.
0180: View regViewWaiting = null;
0181: View unRegViewWaiting = null;
0182: boolean isSceneGraphLock = false;
0183:
0184: private Object waitLock = new Object();
0185:
0186: // Set of scene graph structure change listeners
0187: private HashSet<GraphStructureChangeListener> structureChangeListenerSet = null;
0188:
0189: // Set of shader error listeners
0190: private HashSet<ShaderErrorListener> shaderErrorListenerSet = null;
0191: private ShaderErrorListener defaultShaderErrorListener = ShaderProgram
0192: .getDefaultErrorListener();
0193:
0194: // Set of rendering error listeners
0195: private static HashSet<RenderingErrorListener> renderingErrorListenerSet = null;
0196: private static RenderingErrorListener defaultRenderingErrorListener = Renderer
0197: .getDefaultErrorListener();
0198:
0199: /**
0200: * Constructs a new VirtualUniverse.
0201: */
0202: public VirtualUniverse() {
0203: setLiveState = new SetLiveState(this );
0204: initMCStructure();
0205: }
0206:
0207: void initMCStructure() {
0208: if (geometryStructure != null) {
0209: geometryStructure.cleanup();
0210: }
0211: geometryStructure = new GeometryStructure(this );
0212: if (transformStructure != null) {
0213: transformStructure.cleanup();
0214: }
0215: transformStructure = new TransformStructure(this );
0216: if (behaviorStructure != null) {
0217: behaviorStructure.cleanup();
0218: }
0219: behaviorStructure = new BehaviorStructure(this );
0220: if (soundStructure != null) {
0221: soundStructure.cleanup();
0222: }
0223: soundStructure = new SoundStructure(this );
0224: if (renderingEnvironmentStructure != null) {
0225: renderingEnvironmentStructure.cleanup();
0226: }
0227: renderingEnvironmentStructure = new RenderingEnvironmentStructure(
0228: this );
0229:
0230: }
0231:
0232: /**
0233: * Initialize the native interface and anything else that needs
0234: * to be initialized.
0235: */
0236: static void loadLibraries() {
0237: // No need to do anything. The act of calling any method in this
0238: // class is sufficient to cause the static MasterControl object
0239: // to be created which, in turn, loads the native libraries.
0240: }
0241:
0242: static {
0243: boolean isLoggableConfig = MasterControl
0244: .isCoreLoggable(Level.CONFIG);
0245: Logger logger = MasterControl.getCoreLogger();
0246:
0247: // Print out version information unless this is a
0248: // non-debuggable, release (fcs) build
0249: if (isLoggableConfig || J3dDebug.devPhase
0250: || VersionInfo.isDebug) {
0251: StringBuffer strBuf = new StringBuffer("3D ");
0252: if (J3dDebug.devPhase) {
0253: strBuf.append("[dev] ");
0254: }
0255: strBuf.append(VersionInfo.getVersion());
0256: String str = strBuf.toString();
0257: if (isLoggableConfig) {
0258: logger.config(str);
0259: } else {
0260: System.err.println(str);
0261: System.err.println();
0262: }
0263: }
0264:
0265: // Print out debugging information for debug builds
0266: if (isLoggableConfig || VersionInfo.isDebug) {
0267: StringBuffer strBuf = new StringBuffer();
0268: strBuf.append("Initializing 3D runtime system:\n").append(
0269: " version = ").append(VersionInfo.getVersion())
0270: .append("\n").append(" vendor = ").append(
0271: VersionInfo.getVendor()).append("\n")
0272: .append(" specification.version = ").append(
0273: VersionInfo.getSpecificationVersion())
0274: .append("\n").append(" specification.vendor = ")
0275: .append(VersionInfo.getSpecificationVendor());
0276: String str = strBuf.toString();
0277: if (isLoggableConfig) {
0278: logger.config(str);
0279: } else {
0280: System.err.println(str);
0281: System.err.println();
0282: }
0283: }
0284:
0285: // Java 3D cannot run in headless mode, so we will throw a
0286: // HeadlessException if isHeadless() is true. This avoids a
0287: // cryptic error message from MasterControl.loadLibraries().
0288: if (java.awt.GraphicsEnvironment.isHeadless()) {
0289: throw new java.awt.HeadlessException();
0290: }
0291:
0292: // Load the native libraries and create the static
0293: // MasterControl object
0294: MasterControl.loadLibraries();
0295: mc = new MasterControl();
0296:
0297: // Print out debugging information for debug builds
0298: if (isLoggableConfig || VersionInfo.isDebug) {
0299: StringBuffer strBuf = new StringBuffer();
0300: strBuf.append("3D system initialized\n").append(
0301: " rendering pipeline = ").append(
0302: Pipeline.getPipeline().getPipelineName());
0303: String str = strBuf.toString();
0304: if (isLoggableConfig) {
0305: logger.config(str);
0306: } else {
0307: System.err.println(str);
0308: System.err.println();
0309: }
0310: }
0311: }
0312:
0313: /**
0314: * Adds a locale at the end of list of locales
0315: * @param locale the locale to be added
0316: */
0317: void addLocale(Locale locale) {
0318: listOfLocales.addElement(locale);
0319: }
0320:
0321: /**
0322: * Removes a Locale and its associates branch graphs from this
0323: * universe. All branch graphs within the specified Locale are
0324: * detached, regardless of whether their ALLOW_DETACH capability
0325: * bits are set. The Locale is then marked as being dead: no
0326: * branch graphs may subsequently be attached.
0327: *
0328: * @param locale the Locale to be removed.
0329: *
0330: * @exception IllegalArgumentException if the specified Locale is not
0331: * attached to this VirtualUniverse.
0332: *
0333: * @since Java 3D 1.2
0334: */
0335: public void removeLocale(Locale locale) {
0336: if (locale.getVirtualUniverse() != this ) {
0337: throw new IllegalArgumentException(J3dI18N
0338: .getString("VirtualUniverse0"));
0339: }
0340:
0341: listOfLocales.removeElement(locale);
0342: locale.removeFromUniverse();
0343: if (isEmpty()) {
0344: VirtualUniverse.mc.postRequest(
0345: MasterControl.EMPTY_UNIVERSE, this );
0346: }
0347: setLiveState.reset(null);
0348: }
0349:
0350: /**
0351: * Removes all Locales and their associates branch graphs from
0352: * this universe. All branch graphs within each Locale are
0353: * detached, regardless of whether their ALLOW_DETACH capability
0354: * bits are set. Each Locale is then marked as being dead: no
0355: * branch graphs may subsequently be attached. This method
0356: * should be called by applications and applets to allow
0357: * Java 3D to cleanup its resources.
0358: *
0359: * @since Java 3D 1.2
0360: */
0361: public void removeAllLocales() {
0362: // NOTE: this is safe because Locale.removeFromUniverse does not
0363: // remove the Locale from the listOfLocales
0364: int i;
0365:
0366: for (i = listOfLocales.size() - 1; i > 0; i--) {
0367: ((Locale) listOfLocales.get(i)).removeFromUniverse();
0368: }
0369:
0370: if (i >= 0) {
0371: // We have to clear() the listOfLocales first before
0372: // invoke the last removeFromUniverse() so that isEmpty()
0373: // (call from View.deactivate() ) will return true and
0374: // threads can destroy from MC.
0375: Locale loc = (Locale) listOfLocales.get(0);
0376: listOfLocales.clear();
0377: loc.removeFromUniverse();
0378: }
0379: VirtualUniverse.mc.postRequest(MasterControl.EMPTY_UNIVERSE,
0380: this );
0381:
0382: setLiveState.reset(null);
0383: }
0384:
0385: /**
0386: * Returns the enumeration object of all locales in this virtual universe.
0387: * @return the enumeration object
0388: */
0389: public Enumeration getAllLocales() {
0390: return this .listOfLocales.elements();
0391: }
0392:
0393: /**
0394: * Returns the number of locales.
0395: * @return the count of locales
0396: */
0397: public int numLocales() {
0398: return this .listOfLocales.size();
0399: }
0400:
0401: /**
0402: * Sets the priority of all Java 3D threads to the specified
0403: * value. The default value is the priority of the thread that
0404: * started Java 3D.
0405: *
0406: * @param priority the new thread priority
0407: *
0408: * @exception IllegalArgumentException if the priority is not in
0409: * the range MIN_PRIORITY to MAX_PRIORITY
0410: *
0411: * @exception SecurityException if the priority is greater than
0412: * that of the calling thread
0413: *
0414: * @since Java 3D 1.2
0415: */
0416: public static void setJ3DThreadPriority(int priority) {
0417: if (priority > Thread.MAX_PRIORITY) {
0418: priority = Thread.MAX_PRIORITY;
0419: } else if (priority < Thread.MIN_PRIORITY) {
0420: priority = Thread.MIN_PRIORITY;
0421: }
0422: VirtualUniverse.mc.setThreadPriority(priority);
0423: }
0424:
0425: /**
0426: * Retrieves that priority of Java 3D's threads.
0427: *
0428: * @return the current priority of Java 3D's threads
0429: *
0430: * @since Java 3D 1.2
0431: */
0432: public static int getJ3DThreadPriority() {
0433: return VirtualUniverse.mc.getThreadPriority();
0434: }
0435:
0436: /**
0437: * Returns a read-only Map object containing key-value pairs that
0438: * define various global properties for Java 3D. All of the keys
0439: * are String objects. The values are key-specific, but most will
0440: * be String objects.
0441: *
0442: * <p>
0443: * The set of global Java 3D properties always includes values for
0444: * the following keys:
0445: *
0446: * <p>
0447: * <ul>
0448: * <table BORDER=1 CELLSPACING=1 CELLPADDING=1>
0449: * <tr>
0450: * <td><b>Key (String)</b></td>
0451: * <td><b>Value Type</b></td>
0452: * </tr>
0453: * <tr>
0454: * <td><code>j3d.version</code></td>
0455: * <td>String</td>
0456: * </tr>
0457: * <tr>
0458: * <td><code>j3d.vendor</code></td>
0459: * <td>String</td>
0460: * </tr>
0461: * <tr>
0462: * <td><code>j3d.specification.version</code></td>
0463: * <td>String</td>
0464: * </tr>
0465: * <tr>
0466: * <td><code>j3d.specification.vendor</code></td>
0467: * <td>String</td>
0468: * </tr>
0469: * <tr>
0470: * <td><code>j3d.pipeline</code></td>
0471: * <td>String</td>
0472: * </tr>
0473: * <tr>
0474: * <td><code>j3d.renderer</code></td>
0475: * <td>String</td>
0476: * </tr>
0477: * </table>
0478: * </ul>
0479: *
0480: * <p>
0481: * The descriptions of the values returned for each key are as follows:
0482: *
0483: * <p>
0484: * <ul>
0485: *
0486: * <li>
0487: * <code>j3d.version</code>
0488: * <ul>
0489: * A String that defines the Java 3D implementation version.
0490: * The portion of the implementation version string before the first
0491: * space must adhere to one of the the following three formats
0492: * (anything after the first space is an optional free-form addendum
0493: * to the version):
0494: * <ul>
0495: * <i>x</i>.<i>y</i>.<i>z</i><br>
0496: * <i>x</i>.<i>y</i>.<i>z</i>_<i>p</i><br>
0497: * <i>x</i>.<i>y</i>.<i>z</i>-<i>ssss</i><br>
0498: * </ul>
0499: * where:
0500: * <ul>
0501: * <i>x</i> is the major version number<br>
0502: * <i>y</i> is the minor version number<br>
0503: * <i>z</i> is the sub-minor version number<br>
0504: * <i>p</i> is the patch revision number <br>
0505: * <i>ssss</i> is a string, identifying a non-release build
0506: * (e.g., beta1, build47, rc1, etc.). It may only
0507: * contain letters, numbers, periods, dashes, or
0508: * underscores.
0509: * </ul>
0510: * </ul>
0511: * </li>
0512: * <p>
0513: *
0514: * <li>
0515: * <code>j3d.vendor</code>
0516: * <ul>
0517: * String that specifies the Java 3D implementation vendor.
0518: * </ul>
0519: * </li>
0520: * <p>
0521: *
0522: * <li>
0523: * <code>j3d.specification.version</code>
0524: * <ul>
0525: * A String that defines the Java 3D specification version.
0526: * This string must be of the following form:
0527: * <ul>
0528: * <i>x</i>.<i>y</i>
0529: * </ul>
0530: * where:
0531: * <ul>
0532: * <i>x</i> is the major version number<br>
0533: * <i>y</i> is the minor version number<br>
0534: * </ul>
0535: * No other characters are allowed in the specification version string.
0536: * </ul>
0537: * </li>
0538: * <p>
0539: *
0540: * <li>
0541: * <code>j3d.specification.vendor</code>
0542: * <ul>
0543: * String that specifies the Java 3D specification vendor.
0544: * </ul>
0545: * </li>
0546: * <p>
0547: *
0548: * <li>
0549: * <code>j3d.pipeline</code>
0550: * <ul>
0551: * String that specifies the Java 3D rendering pipeline. This could
0552: * be one of: "NATIVE_OGL", "NATIVE_D3D", or "JOGL". Others could be
0553: * added in the future.
0554: * </ul>
0555: * </li>
0556: * <p>
0557: *
0558: * <li>
0559: * <code>j3d.renderer</code>
0560: * <ul>
0561: * String that specifies the underlying rendering library. This could
0562: * be one of: "OpenGL" or "DirectX". Others could be added in the future.
0563: * </ul>
0564: * </li>
0565: * <p>
0566: *
0567: * </ul>
0568: *
0569: * @return the global Java 3D properties
0570: *
0571: * @since Java 3D 1.3
0572: */
0573: public static final Map getProperties() {
0574: if (properties == null) {
0575: // Create lists of keys and values
0576: ArrayList keys = new ArrayList();
0577: ArrayList values = new ArrayList();
0578:
0579: // Implementation version string is obtained from the
0580: // ImplementationVersion class.
0581: keys.add("j3d.version");
0582: values.add(VersionInfo.getVersion());
0583:
0584: keys.add("j3d.vendor");
0585: values.add(VersionInfo.getVendor());
0586:
0587: keys.add("j3d.specification.version");
0588: values.add(VersionInfo.getSpecificationVersion());
0589:
0590: keys.add("j3d.specification.vendor");
0591: values.add(VersionInfo.getSpecificationVendor());
0592:
0593: keys.add("j3d.renderer");
0594: values.add(Pipeline.getPipeline().getRendererName());
0595:
0596: keys.add("j3d.pipeline");
0597: values.add(Pipeline.getPipeline().getPipelineName());
0598:
0599: // Now Create read-only properties object
0600: properties = new J3dQueryProps((String[]) keys
0601: .toArray(new String[0]), values.toArray());
0602: }
0603: return properties;
0604: }
0605:
0606: /**
0607: * This returns the next available nodeId as a string.
0608: */
0609: // XXXX: reuse of id's imply a slight collision problem in the
0610: // render queue's.
0611: // BUG 4181362
0612: String getNodeId() {
0613: String str;
0614:
0615: if (nodeIdFreeList.size() == 0) {
0616: str = Long.toString(nodeIdCount);
0617: nodeIdCount++;
0618: } else {
0619: // Issue 496: Remove last object using index to avoid performance
0620: // hit of a needless linear search.
0621: int idx = nodeIdFreeList.size() - 1;
0622: str = (String) nodeIdFreeList.remove(idx);
0623: }
0624: return (str);
0625: }
0626:
0627: /**
0628: * This returns the next available viewId
0629: */
0630: Integer getViewId() {
0631: Integer id;
0632: int size;
0633:
0634: synchronized (viewIdFreeList) {
0635: size = viewIdFreeList.size();
0636: if (size == 0) {
0637: id = new Integer(viewIdCount++);
0638: } else {
0639: id = (Integer) viewIdFreeList.remove(size - 1);
0640: }
0641: }
0642: return (id);
0643: }
0644:
0645: /**
0646: * This returns a viewId to the freelist
0647: */
0648: void addViewIdToFreeList(Integer viewId) {
0649: synchronized (viewIdFreeList) {
0650: viewIdFreeList.add(viewId);
0651: }
0652: }
0653:
0654: void addViewPlatform(ViewPlatformRetained vp) {
0655: vpChanged = true;
0656: viewPlatforms.add(vp);
0657: }
0658:
0659: void removeViewPlatform(ViewPlatformRetained vp) {
0660: vpChanged = true;
0661: viewPlatforms.remove(viewPlatforms.indexOf(vp));
0662: }
0663:
0664: synchronized Object[] getViewPlatformList() {
0665: if (vpChanged) {
0666: viewPlatformList = viewPlatforms.toArray();
0667: vpChanged = false;
0668: }
0669: return viewPlatformList;
0670: }
0671:
0672: void checkForEnableEvents() {
0673: enableComponentEvents();
0674: if (enableFocus) {
0675: enableFocusEvents();
0676: }
0677: if (enableKey) {
0678: enableKeyEvents();
0679: }
0680: if (enableMouse) {
0681: enableMouseEvents();
0682: }
0683: if (enableMouseMotion) {
0684: enableMouseMotionEvents();
0685: }
0686: if (enableMouseWheel) {
0687: enableMouseWheelEvents();
0688: }
0689:
0690: }
0691:
0692: void enableComponentEvents() {
0693: // Issue 458 - This method is now a noop
0694: /*
0695: Enumeration cvs;
0696: Canvas3D cv;
0697: ViewPlatformRetained vp;
0698: View views[];
0699: Object[] vps = getViewPlatformList();
0700:
0701: if (vps != null) {
0702: for (int i=0; i<vps.length; i++) {
0703: vp =(ViewPlatformRetained)vps[i];
0704: views = vp.getViewList();
0705: for (int j=views.length-1; j>=0; j--) {
0706: cvs = views[j].getAllCanvas3Ds();
0707: while(cvs.hasMoreElements()) {
0708: cv = (Canvas3D) cvs.nextElement();
0709: // offscreen canvas does not have event catcher
0710: if (cv.eventCatcher != null) {
0711: cv.eventCatcher.enableComponentEvents();
0712: }
0713: }
0714: }
0715: }
0716: }
0717: */
0718: }
0719:
0720: void disableFocusEvents() {
0721: Enumeration cvs;
0722: Canvas3D cv;
0723: ViewPlatformRetained vp;
0724: View views[];
0725: Object[] vps = getViewPlatformList();
0726: enableFocus = false;
0727:
0728: if (vps != null) {
0729: for (int i = 0; i < vps.length; i++) {
0730: vp = (ViewPlatformRetained) vps[i];
0731: views = vp.getViewList();
0732: for (int j = views.length - 1; j >= 0; j--) {
0733: cvs = views[j].getAllCanvas3Ds();
0734: while (cvs.hasMoreElements()) {
0735: cv = (Canvas3D) cvs.nextElement();
0736: // offscreen canvas does not have event catcher
0737: if (cv.eventCatcher != null)
0738: cv.eventCatcher.disableFocusEvents();
0739: }
0740: }
0741: }
0742: }
0743:
0744: }
0745:
0746: void enableFocusEvents() {
0747: Enumeration cvs;
0748: Canvas3D cv;
0749: ViewPlatformRetained vp;
0750: View views[];
0751: Object[] vps = getViewPlatformList();
0752: enableFocus = true;
0753:
0754: if (vps != null) {
0755: for (int i = 0; i < vps.length; i++) {
0756: vp = (ViewPlatformRetained) vps[i];
0757: views = vp.getViewList();
0758: for (int j = views.length - 1; j >= 0; j--) {
0759: cvs = views[j].getAllCanvas3Ds();
0760: while (cvs.hasMoreElements()) {
0761: cv = (Canvas3D) cvs.nextElement();
0762: // offscreen canvas does not have event catcher
0763: if (cv.eventCatcher != null)
0764: cv.eventCatcher.enableFocusEvents();
0765: }
0766: }
0767: }
0768: }
0769: }
0770:
0771: void disableKeyEvents() {
0772: Enumeration cvs;
0773: Canvas3D cv;
0774: ViewPlatformRetained vp;
0775: Object[] vps = getViewPlatformList();
0776: View views[];
0777:
0778: enableKey = false;
0779:
0780: if (vps != null) {
0781: for (int i = 0; i < vps.length; i++) {
0782: vp = (ViewPlatformRetained) vps[i];
0783: views = vp.getViewList();
0784: for (int j = views.length - 1; j >= 0; j--) {
0785: cvs = views[j].getAllCanvas3Ds();
0786: while (cvs.hasMoreElements()) {
0787: cv = (Canvas3D) cvs.nextElement();
0788: // offscreen canvas does not have event catcher
0789: if (cv.eventCatcher != null)
0790: cv.eventCatcher.disableKeyEvents();
0791: }
0792: }
0793: }
0794: }
0795: }
0796:
0797: void enableKeyEvents() {
0798: Enumeration cvs;
0799: Canvas3D cv;
0800: ViewPlatformRetained vp;
0801: Object[] vps = getViewPlatformList();
0802: View views[];
0803:
0804: enableKey = true;
0805:
0806: if (vps != null) {
0807: for (int i = 0; i < vps.length; i++) {
0808: vp = (ViewPlatformRetained) vps[i];
0809: views = vp.getViewList();
0810: for (int j = views.length - 1; j >= 0; j--) {
0811: cvs = views[j].getAllCanvas3Ds();
0812: while (cvs.hasMoreElements()) {
0813: cv = (Canvas3D) cvs.nextElement();
0814: // offscreen canvas does not have event catcher
0815: if (cv.eventCatcher != null)
0816: cv.eventCatcher.enableKeyEvents();
0817: }
0818: }
0819: }
0820: }
0821: }
0822:
0823: void disableMouseEvents() {
0824: Enumeration cvs;
0825: Canvas3D cv;
0826: View views[];
0827: ViewPlatformRetained vp;
0828: Object[] vps = getViewPlatformList();
0829:
0830: enableMouse = false;
0831:
0832: if (vps != null) {
0833: for (int i = 0; i < vps.length; i++) {
0834: vp = (ViewPlatformRetained) vps[i];
0835: views = vp.getViewList();
0836: for (int j = views.length - 1; j >= 0; j--) {
0837: cvs = views[j].getAllCanvas3Ds();
0838: while (cvs.hasMoreElements()) {
0839: cv = (Canvas3D) cvs.nextElement();
0840: // offscreen canvas does not have event catcher
0841: if (cv.eventCatcher != null)
0842: cv.eventCatcher.disableMouseEvents();
0843: }
0844: }
0845: }
0846: }
0847: }
0848:
0849: void enableMouseEvents() {
0850: Enumeration cvs;
0851: Canvas3D cv;
0852: View views[];
0853: ViewPlatformRetained vp;
0854: Object[] vps = getViewPlatformList();
0855:
0856: enableMouse = true;
0857:
0858: if (vps != null) {
0859: for (int i = 0; i < vps.length; i++) {
0860: vp = (ViewPlatformRetained) vps[i];
0861: views = vp.getViewList();
0862: for (int j = views.length - 1; j >= 0; j--) {
0863: cvs = views[j].getAllCanvas3Ds();
0864: while (cvs.hasMoreElements()) {
0865: cv = (Canvas3D) cvs.nextElement();
0866: // offscreen canvas does not have event catcher
0867: if (cv.eventCatcher != null)
0868: cv.eventCatcher.enableMouseEvents();
0869: }
0870: }
0871: }
0872: }
0873: }
0874:
0875: void disableMouseMotionEvents() {
0876: Enumeration cvs;
0877: Canvas3D cv;
0878: View views[];
0879: ViewPlatformRetained vp;
0880: Object[] vps = getViewPlatformList();
0881:
0882: enableMouseMotion = false;
0883:
0884: if (vps != null) {
0885: for (int i = 0; i < vps.length; i++) {
0886: vp = (ViewPlatformRetained) vps[i];
0887: views = vp.getViewList();
0888: for (int j = views.length - 1; j >= 0; j--) {
0889: cvs = views[j].getAllCanvas3Ds();
0890: while (cvs.hasMoreElements()) {
0891: cv = (Canvas3D) cvs.nextElement();
0892: // offscreen canvas does not have event catcher
0893: if (cv.eventCatcher != null)
0894: cv.eventCatcher.disableMouseMotionEvents();
0895: }
0896: }
0897: }
0898: }
0899: }
0900:
0901: void enableMouseMotionEvents() {
0902: Enumeration cvs;
0903: Canvas3D cv;
0904: View views[];
0905: ViewPlatformRetained vp;
0906: Object[] vps = getViewPlatformList();
0907:
0908: enableMouseMotion = true;
0909:
0910: if (vps != null) {
0911: for (int i = 0; i < vps.length; i++) {
0912: vp = (ViewPlatformRetained) vps[i];
0913: views = vp.getViewList();
0914: for (int j = views.length - 1; j >= 0; j--) {
0915: cvs = views[j].getAllCanvas3Ds();
0916: while (cvs.hasMoreElements()) {
0917: cv = (Canvas3D) cvs.nextElement();
0918: // offscreen canvas does not have event catcher
0919: if (cv.eventCatcher != null)
0920: cv.eventCatcher.enableMouseMotionEvents();
0921: }
0922: }
0923: }
0924: }
0925: }
0926:
0927: void disableMouseWheelEvents() {
0928: Enumeration cvs;
0929: Canvas3D cv;
0930: View views[];
0931: ViewPlatformRetained vp;
0932: Object[] vps = getViewPlatformList();
0933:
0934: enableMouseWheel = false;
0935:
0936: if (vps != null) {
0937: for (int i = 0; i < vps.length; i++) {
0938: vp = (ViewPlatformRetained) vps[i];
0939: views = vp.getViewList();
0940: for (int j = views.length - 1; j >= 0; j--) {
0941: cvs = views[j].getAllCanvas3Ds();
0942: while (cvs.hasMoreElements()) {
0943: cv = (Canvas3D) cvs.nextElement();
0944: // offscreen canvas does not have event catcher
0945: if (cv.eventCatcher != null)
0946: cv.eventCatcher.disableMouseWheelEvents();
0947: }
0948: }
0949: }
0950: }
0951: }
0952:
0953: void enableMouseWheelEvents() {
0954: Enumeration cvs;
0955: Canvas3D cv;
0956: View views[];
0957: ViewPlatformRetained vp;
0958: Object[] vps = getViewPlatformList();
0959:
0960: enableMouseWheel = true;
0961:
0962: if (vps != null) {
0963: for (int i = 0; i < vps.length; i++) {
0964: vp = (ViewPlatformRetained) vps[i];
0965: views = vp.getViewList();
0966: for (int j = views.length - 1; j >= 0; j--) {
0967: cvs = views[j].getAllCanvas3Ds();
0968: while (cvs.hasMoreElements()) {
0969: cv = (Canvas3D) cvs.nextElement();
0970: // offscreen canvas does not have event catcher
0971: if (cv.eventCatcher != null)
0972: cv.eventCatcher.enableMouseWheelEvents();
0973: }
0974: }
0975: }
0976: }
0977: }
0978:
0979: /**
0980: * Sets the "current" view (during view activation) for this virtual
0981: * universe.
0982: * @param last activated view
0983: */
0984: final void setCurrentView(View view) {
0985: this .currentView = view;
0986: }
0987:
0988: /**
0989: * Returns the "current" view (the last view activated for this virtual
0990: * universe.
0991: * @return last activated view
0992: */
0993: final View getCurrentView() {
0994: return this .currentView;
0995: }
0996:
0997: /**
0998: * Method to return the root thread group. This must be called from
0999: * within a doPrivileged block.
1000: */
1001: static ThreadGroup getRootThreadGroup() {
1002: return rootThreadGroup;
1003: }
1004:
1005: /**
1006: * return true if all Locales under it don't have branchGroup
1007: * attach to it.
1008: */
1009: boolean isEmpty() {
1010: Enumeration elm = listOfLocales.elements();
1011:
1012: while (elm.hasMoreElements()) {
1013: Locale loc = (Locale) elm.nextElement();
1014: if (!loc.branchGroups.isEmpty()) {
1015: return false;
1016: }
1017: }
1018: return true;
1019: }
1020:
1021: void resetWaitMCFlag() {
1022: synchronized (waitLock) {
1023: regViewWaiting = null;
1024: unRegViewWaiting = null;
1025: isSceneGraphLock = true;
1026: }
1027: }
1028:
1029: void waitForMC() {
1030: synchronized (waitLock) {
1031: if (unRegViewWaiting != null) {
1032: if ((regViewWaiting == null)
1033: || (regViewWaiting != unRegViewWaiting)) {
1034: while (!unRegViewWaiting.doneUnregister) {
1035: MasterControl.threadYield();
1036: }
1037: unRegViewWaiting.doneUnregister = false;
1038: unRegViewWaiting = null;
1039: }
1040: }
1041:
1042: if (regViewWaiting != null) {
1043: while (!VirtualUniverse.mc.isRegistered(regViewWaiting)) {
1044: MasterControl.threadYield();
1045: }
1046: regViewWaiting = null;
1047: }
1048: isSceneGraphLock = false;
1049: }
1050: }
1051:
1052: /**
1053: * Adds the specified GraphStructureChangeListener to the set of listeners
1054: * that will be notified when the graph structure is changed on a live
1055: * scene graph. If the specifed listener is null no action is taken and no
1056: * exception is thrown.
1057: *
1058: * @param listener the listener to add to the set.
1059: *
1060: * @since Java 3D 1.4
1061: */
1062: public void addGraphStructureChangeListener(
1063: GraphStructureChangeListener listener) {
1064: if (listener == null) {
1065: return;
1066: }
1067:
1068: if (structureChangeListenerSet == null) {
1069: structureChangeListenerSet = new HashSet();
1070: }
1071:
1072: synchronized (structureChangeListenerSet) {
1073: structureChangeListenerSet.add(listener);
1074: }
1075: }
1076:
1077: /**
1078: * Removes the specified GraphStructureChangeListener from the set of listeners. This
1079: * method performs no function, nor does it throw an exception if the specified listener
1080: * is not currently in the set or is null.
1081: *
1082: * @param listener the listener to remove from the set.
1083: *
1084: * @since Java 3D 1.4
1085: */
1086: public void removeGraphStructureChangeListener(
1087: GraphStructureChangeListener listener) {
1088: if (structureChangeListenerSet == null) {
1089: return;
1090: }
1091:
1092: synchronized (structureChangeListenerSet) {
1093: structureChangeListenerSet.remove(listener);
1094: }
1095: }
1096:
1097: /**
1098: * Processes all live BranchGroup add and removes and notifies
1099: * any registered listeners. Used for add and remove
1100: */
1101: void notifyStructureChangeListeners(boolean add, Object parent,
1102: BranchGroup child) {
1103: if (structureChangeListenerSet == null) {
1104: return;
1105: }
1106:
1107: synchronized (structureChangeListenerSet) {
1108: Iterator<GraphStructureChangeListener> it = structureChangeListenerSet
1109: .iterator();
1110: while (it.hasNext()) {
1111: GraphStructureChangeListener listener = it.next();
1112: try {
1113: if (add) {
1114: listener.branchGroupAdded(parent, child);
1115: } else {
1116: listener.branchGroupRemoved(parent, child);
1117: }
1118: } catch (RuntimeException e) {
1119: System.err
1120: .println("Exception occurred in GraphStructureChangeListener:");
1121: e.printStackTrace();
1122: } catch (Error e) {
1123: // Issue 264 - catch Error
1124: System.err
1125: .println("Error occurred in GraphStructureChangeListener:");
1126: e.printStackTrace();
1127: }
1128: }
1129: }
1130: }
1131:
1132: /**
1133: * Processes all live BranchGroup moves and notifies
1134: * any registered listeners. Used for moveTo
1135: */
1136: void notifyStructureChangeListeners(Object oldParent,
1137: Object newParent, BranchGroup child) {
1138: if (structureChangeListenerSet == null) {
1139: return;
1140: }
1141:
1142: synchronized (structureChangeListenerSet) {
1143: Iterator<GraphStructureChangeListener> it = structureChangeListenerSet
1144: .iterator();
1145: while (it.hasNext()) {
1146: GraphStructureChangeListener listener = it.next();
1147: try {
1148: listener.branchGroupMoved(oldParent, newParent,
1149: child);
1150: } catch (RuntimeException e) {
1151: System.err
1152: .println("Exception occurred in GraphStructureChangeListener:");
1153: e.printStackTrace();
1154: } catch (Error e) {
1155: // Issue 264 - catch Error
1156: System.err
1157: .println("Error occurred in GraphStructureChangeListener:");
1158: e.printStackTrace();
1159: }
1160: }
1161: }
1162: }
1163:
1164: /**
1165: * Adds the specified ShaderErrorListener to the set of listeners
1166: * that will be notified when a programmable shader error is
1167: * detected on a live scene graph. If the specifed listener is
1168: * null no action is taken and no exception is thrown.
1169: * If a shader error occurs, the listeners will be called
1170: * asynchronously from a separate notification thread. The Java 3D
1171: * renderer and behavior scheduler will continue to run as if the
1172: * error had not occurred, except that shading will be disabled
1173: * for the objects in error. If applications desire to detach or
1174: * modify the scene graph as a result of the error, they should
1175: * use a behavior post if they want that change to be
1176: * synchronous with the renderer.
1177: *
1178: * @param listener the listener to add to the set.
1179: *
1180: * @since Java 3D 1.4
1181: */
1182: public void addShaderErrorListener(ShaderErrorListener listener) {
1183: if (listener == null) {
1184: return;
1185: }
1186:
1187: if (shaderErrorListenerSet == null) {
1188: shaderErrorListenerSet = new HashSet();
1189: }
1190:
1191: synchronized (shaderErrorListenerSet) {
1192: shaderErrorListenerSet.add(listener);
1193: }
1194: }
1195:
1196: /**
1197: * Removes the specified ShaderErrorListener from the set of
1198: * listeners. This method performs no function, nor does it throw
1199: * an exception if the specified listener is not currently in the
1200: * set or is null.
1201: *
1202: * @param listener the listener to remove from the set.
1203: *
1204: * @since Java 3D 1.4
1205: */
1206: public void removeShaderErrorListener(ShaderErrorListener listener) {
1207: if (shaderErrorListenerSet == null) {
1208: return;
1209: }
1210:
1211: synchronized (shaderErrorListenerSet) {
1212: shaderErrorListenerSet.remove(listener);
1213: }
1214: }
1215:
1216: /**
1217: * Notifies all listeners of a shader error. If no listeners exist, a default
1218: * listener is notified.
1219: */
1220: void notifyShaderErrorListeners(ShaderError error) {
1221: boolean errorReported = false;
1222:
1223: // Notify all error listeners in the set
1224: if (shaderErrorListenerSet != null) {
1225: synchronized (shaderErrorListenerSet) {
1226: Iterator<ShaderErrorListener> it = shaderErrorListenerSet
1227: .iterator();
1228: while (it.hasNext()) {
1229: ShaderErrorListener listener = it.next();
1230: try {
1231: listener.errorOccurred(error);
1232: } catch (RuntimeException e) {
1233: System.err
1234: .println("Exception occurred in ShaderErrorListener:");
1235: e.printStackTrace();
1236: } catch (Error e) {
1237: // Issue 264 - catch Error
1238: System.err
1239: .println("Error occurred in ShaderErrorListener:");
1240: e.printStackTrace();
1241: }
1242: errorReported = true;
1243: }
1244: }
1245: }
1246:
1247: // Notify the default error listener if the set is null or empty
1248: if (!errorReported) {
1249: defaultShaderErrorListener.errorOccurred(error);
1250: }
1251: }
1252:
1253: // Issue 260 : rendering error listeners.
1254:
1255: /**
1256: * Adds the specified RenderingErrorListener to the set of listeners
1257: * that will be notified when a rendering error is detected.
1258: * If the specifed listener is null no action is taken and no exception
1259: * is thrown.
1260: * If a rendering error occurs, the listeners will be called
1261: * asynchronously from a separate notification thread. If the set
1262: * of listeners is empty, a default listener is notified. The
1263: * default listener prints the error information to System.err and
1264: * then calls System.exit().
1265: *
1266: * @param listener the listener to add to the set.
1267: *
1268: * @since Java 3D 1.5
1269: */
1270: public static void addRenderingErrorListener(
1271: RenderingErrorListener listener) {
1272: if (listener == null) {
1273: return;
1274: }
1275:
1276: if (renderingErrorListenerSet == null) {
1277: renderingErrorListenerSet = new HashSet();
1278: }
1279:
1280: synchronized (renderingErrorListenerSet) {
1281: renderingErrorListenerSet.add(listener);
1282: }
1283: }
1284:
1285: /**
1286: * Removes the specified RenderingErrorListener from the set of
1287: * listeners. This method performs no function, nor does it throw
1288: * an exception if the specified listener is not currently in the
1289: * set or is null.
1290: *
1291: * @param listener the listener to remove from the set.
1292: *
1293: * @since Java 3D 1.5
1294: */
1295: public static void removeRenderingErrorListener(
1296: RenderingErrorListener listener) {
1297: if (renderingErrorListenerSet == null) {
1298: return;
1299: }
1300:
1301: synchronized (renderingErrorListenerSet) {
1302: renderingErrorListenerSet.remove(listener);
1303: }
1304: }
1305:
1306: /**
1307: * Notifies all listeners of a rendering error. If no listeners exist,
1308: * a default listener is notified.
1309: */
1310: static void notifyRenderingErrorListeners(RenderingError error) {
1311: boolean errorReported = false;
1312:
1313: // Notify all error listeners in the set
1314: if (renderingErrorListenerSet != null) {
1315: synchronized (renderingErrorListenerSet) {
1316: Iterator<RenderingErrorListener> it = renderingErrorListenerSet
1317: .iterator();
1318: while (it.hasNext()) {
1319: RenderingErrorListener listener = it.next();
1320: try {
1321: listener.errorOccurred(error);
1322: } catch (RuntimeException e) {
1323: System.err
1324: .println("Exception occurred in RenderingErrorListener:");
1325: e.printStackTrace();
1326: } catch (Error e) {
1327: // Issue 264 - catch Error
1328: System.err
1329: .println("Error occurred in RenderingErrorListener:");
1330: e.printStackTrace();
1331: }
1332: errorReported = true;
1333: }
1334: }
1335: }
1336:
1337: // Notify the default error listener if the set is null or empty
1338: if (!errorReported) {
1339: defaultRenderingErrorListener.errorOccurred(error);
1340: }
1341: }
1342:
1343: }
|