aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/VirtualUniverse.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/media/j3d/VirtualUniverse.java')
-rw-r--r--src/javax/media/j3d/VirtualUniverse.java1220
1 files changed, 1220 insertions, 0 deletions
diff --git a/src/javax/media/j3d/VirtualUniverse.java b/src/javax/media/j3d/VirtualUniverse.java
new file mode 100644
index 0000000..624bccb
--- /dev/null
+++ b/src/javax/media/j3d/VirtualUniverse.java
@@ -0,0 +1,1220 @@
+/*
+ * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package javax.media.j3d;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A VirtualUniverse object is the top-level container for all scene
+ * graphs. A virtual universe consists of a set of Locale objects,
+ * each of which has a high-resolution position within the virtual
+ * universe. An application or applet may have more than one
+ * VirtualUniverse objects, but many applications will need only one.
+ * Virtual universes are separate entities in that no node object may
+ * exist in more than one virtual universe at any one time. Likewise,
+ * the objects in one virtual universe are not visible in, nor do they
+ * interact with objects in, any other virtual universe.
+ * <p>
+ * A VirtualUniverse object defines methods to enumerate its Locale
+ * objects and to remove them from the virtual universe.
+ *
+ * <p>
+ * For more information, see the
+ * <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and
+ * <a href="doc-files/VirtualUniverse.html">Scene Graph Superstructure</a>
+ * documents.
+ *
+ * @see Locale
+ */
+
+public class VirtualUniverse extends Object {
+ // NOTE TO DEVELOPERS:
+ //
+ // Developers who modify Java 3D in any way should modify
+ // the auxiliary implementation vendor string in VersionInfo.java.
+ // See that file for instructions.
+
+ // The global MasterControl object. There is only one of these
+ // for all of Java 3D.
+ static MasterControl mc = null;
+
+ // The lock to acquire before traversing the scene graph
+ Object sceneGraphLock = new Object();
+ Object behaviorLock = new Object();
+
+// A list of locales that are contained within this universe
+Vector<Locale> listOfLocales = new Vector<Locale>();
+
+// The list of view platforms, a changed flag and a cached array
+private ArrayList<ViewPlatformRetained> viewPlatforms = new ArrayList<ViewPlatformRetained>();
+private boolean vpChanged = false;
+private ViewPlatformRetained[] viewPlatformList = new ViewPlatformRetained[0];
+
+ // The Behavior Scheduler Thread for this Virtual Universe.
+ BehaviorScheduler behaviorScheduler = null;
+
+
+ // The geometry structure for this Universe
+ GeometryStructure geometryStructure = null;
+
+ // The transform structure for this Universe
+ TransformStructure transformStructure = null;
+
+ // The behavior structure for this Universe
+ BehaviorStructure behaviorStructure = null;
+
+ // The sound structure for this Universe
+ SoundStructure soundStructure = null;
+
+ // The rendering attributes structure for this Universe
+ RenderingEnvironmentStructure renderingEnvironmentStructure = null;
+
+ // Reference count of users of the RenderingEnvironmentStructure
+ int renderingEnvironmentStructureRefCount = 0;
+
+ // This is a global counter for node id's.
+ long nodeIdCount = 0;
+
+ // This is a global counter for view id's.
+ int viewIdCount = 0;
+
+// This is a vector of free nodeid's
+Vector<String> nodeIdFreeList = new Vector<String>();
+
+// This is a vector of free viewid's
+ArrayList<Integer> viewIdFreeList = new ArrayList<Integer>();
+
+ // The number of nodes in this universe
+ int numNodes = 0;
+
+ // The State object used when branch graphs are added
+ SetLiveState setLiveState;
+
+ // This is an array of references to objects that need their mirror
+ // copies updated. It is updated by the traverser and emptied by
+ // the view thread.
+ ObjectUpdate[] updateObjects = new ObjectUpdate[16];
+
+ // The number of valid entries in updateObjects
+ int updateObjectsLen = 0;
+
+ // The current primary view for this universe
+ View currentView;
+
+ // A flag to indicate that we are in a behavior routine
+ boolean inBehavior = false;
+
+ // Flags to indicate if events need to be delivered
+ boolean enableComponent = false;
+ boolean enableFocus = false;
+ boolean enableKey = false;
+ boolean enableMouse = false;
+ boolean enableMouseMotion = false;
+ boolean enableMouseWheel = false;
+
+ // Keep track of how many active View use this universe
+ int activeViewCount = 0;
+
+ // Root ThreadGroup for creating Java 3D threads
+ static ThreadGroup rootThreadGroup;
+
+ // Properties object for getProperties
+ private static J3dQueryProps properties = null;
+
+ // Flag to indicate that user thread has to
+ // stop until MC completely register/unregister View.
+ View regViewWaiting = null;
+ View unRegViewWaiting = null;
+ boolean isSceneGraphLock = false;
+
+ private Object waitLock = new Object();
+
+ // Set of scene graph structure change listeners
+ private HashSet<GraphStructureChangeListener> structureChangeListenerSet = null;
+
+ // Set of shader error listeners
+ private HashSet<ShaderErrorListener> shaderErrorListenerSet = null;
+ private ShaderErrorListener defaultShaderErrorListener =
+ ShaderProgram.getDefaultErrorListener();
+
+ // Set of rendering error listeners
+ private static HashSet<RenderingErrorListener> renderingErrorListenerSet = null;
+ private static RenderingErrorListener defaultRenderingErrorListener =
+ Renderer.getDefaultErrorListener();
+
+ /**
+ * Constructs a new VirtualUniverse.
+ */
+ public VirtualUniverse() {
+ setLiveState = new SetLiveState(this);
+ initMCStructure();
+ }
+
+
+ void initMCStructure() {
+ if (geometryStructure != null) {
+ geometryStructure.cleanup();
+ }
+ geometryStructure = new GeometryStructure(this);
+ if (transformStructure != null) {
+ transformStructure.cleanup();
+ }
+ transformStructure = new TransformStructure(this);
+ if (behaviorStructure != null) {
+ behaviorStructure.cleanup();
+ }
+ behaviorStructure = new BehaviorStructure(this);
+ if (soundStructure != null) {
+ soundStructure.cleanup();
+ }
+ soundStructure = new SoundStructure(this);
+ if (renderingEnvironmentStructure != null) {
+ renderingEnvironmentStructure.cleanup();
+ }
+ renderingEnvironmentStructure = new
+ RenderingEnvironmentStructure(this);
+
+ }
+
+ /**
+ * Initialize the native interface and anything else that needs
+ * to be initialized.
+ */
+ static void loadLibraries() {
+ // No need to do anything. The act of calling any method in this
+ // class is sufficient to cause the static MasterControl object
+ // to be created which, in turn, loads the native libraries.
+ }
+
+ static {
+ boolean isLoggableConfig = MasterControl.isCoreLoggable(Level.CONFIG);
+ Logger logger = MasterControl.getCoreLogger();
+
+ // Print out version information unless this is a
+ // non-debuggable, release (fcs) build
+ if (isLoggableConfig || J3dDebug.devPhase || VersionInfo.isDebug) {
+ StringBuffer strBuf = new StringBuffer("3D ");
+ if (J3dDebug.devPhase) {
+ strBuf.append("[dev] ");
+ }
+ strBuf.append(VersionInfo.getVersion());
+ String str = strBuf.toString();
+ if (isLoggableConfig) {
+ logger.config(str);
+ } else {
+ System.err.println(str);
+ System.err.println();
+ }
+ }
+
+ // Print out debugging information for debug builds
+ if (isLoggableConfig || VersionInfo.isDebug) {
+ StringBuffer strBuf = new StringBuffer();
+ strBuf.append("Initializing 3D runtime system:\n").
+ append(" version = ").
+ append(VersionInfo.getVersion()).
+ append("\n").
+ append(" vendor = ").
+ append(VersionInfo.getVendor()).
+ append("\n").
+ append(" specification.version = ").
+ append(VersionInfo.getSpecificationVersion()).
+ append("\n").
+ append(" specification.vendor = ").
+ append(VersionInfo.getSpecificationVendor());
+ String str = strBuf.toString();
+ if (isLoggableConfig) {
+ logger.config(str);
+ } else {
+ System.err.println(str);
+ System.err.println();
+ }
+ }
+
+ // Java 3D cannot run in headless mode, so we will throw a
+ // HeadlessException if isHeadless() is true. This avoids a
+ // cryptic error message from MasterControl.loadLibraries().
+ if (java.awt.GraphicsEnvironment.isHeadless()) {
+ throw new java.awt.HeadlessException();
+ }
+
+ // Load the native libraries and create the static
+ // MasterControl object
+ MasterControl.loadLibraries();
+ mc = new MasterControl();
+
+ // Print out debugging information for debug builds
+ if (isLoggableConfig || VersionInfo.isDebug) {
+ StringBuffer strBuf = new StringBuffer();
+ strBuf.append("3D system initialized\n").
+ append(" rendering pipeline = ").
+ append(Pipeline.getPipeline().getPipelineName());
+ String str = strBuf.toString();
+ if (isLoggableConfig) {
+ logger.config(str);
+ } else {
+ System.err.println(str);
+ System.err.println();
+ }
+ }
+ }
+
+ /**
+ * Adds a locale at the end of list of locales
+ * @param locale the locale to be added
+ */
+ void addLocale(Locale locale) {
+ listOfLocales.addElement(locale);
+ }
+
+ /**
+ * Removes a Locale and its associates branch graphs from this
+ * universe. All branch graphs within the specified Locale are
+ * detached, regardless of whether their ALLOW_DETACH capability
+ * bits are set. The Locale is then marked as being dead: no
+ * branch graphs may subsequently be attached.
+ *
+ * @param locale the Locale to be removed.
+ *
+ * @exception IllegalArgumentException if the specified Locale is not
+ * attached to this VirtualUniverse.
+ *
+ * @since Java 3D 1.2
+ */
+ public void removeLocale(Locale locale) {
+ if (locale.getVirtualUniverse() != this) {
+ throw new IllegalArgumentException(J3dI18N.getString("VirtualUniverse0"));
+ }
+
+ listOfLocales.removeElement(locale);
+ locale.removeFromUniverse();
+ if (isEmpty()) {
+ VirtualUniverse.mc.postRequest(MasterControl.EMPTY_UNIVERSE,
+ this);
+ }
+ setLiveState.reset(null);
+ }
+
+
+ /**
+ * Removes all Locales and their associates branch graphs from
+ * this universe. All branch graphs within each Locale are
+ * detached, regardless of whether their ALLOW_DETACH capability
+ * bits are set. Each Locale is then marked as being dead: no
+ * branch graphs may subsequently be attached. This method
+ * should be called by applications and applets to allow
+ * Java 3D to cleanup its resources.
+ *
+ * @since Java 3D 1.2
+ */
+ public void removeAllLocales() {
+ // NOTE: this is safe because Locale.removeFromUniverse does not
+ // remove the Locale from the listOfLocales
+ int i;
+
+
+ for (i = listOfLocales.size() - 1; i > 0; i--) {
+ listOfLocales.get(i).removeFromUniverse();
+ }
+
+ if (i >= 0) {
+ // We have to clear() the listOfLocales first before
+ // invoke the last removeFromUniverse() so that isEmpty()
+ // (call from View.deactivate() ) will return true and
+ // threads can destroy from MC.
+ Locale loc = listOfLocales.get(0);
+ listOfLocales.clear();
+ loc.removeFromUniverse();
+ }
+ VirtualUniverse.mc.postRequest(MasterControl.EMPTY_UNIVERSE,
+ this);
+
+ setLiveState.reset(null);
+ }
+
+
+/**
+ * Returns the enumeration object of all locales in this virtual universe.
+ *
+ * @return the enumeration object
+ */
+public Enumeration<Locale> getAllLocales() {
+ return this.listOfLocales.elements();
+}
+
+ /**
+ * Returns the number of locales.
+ * @return the count of locales
+ */
+ public int numLocales() {
+ return this.listOfLocales.size();
+ }
+
+
+ /**
+ * Sets the priority of all Java 3D threads to the specified
+ * value. The default value is the priority of the thread that
+ * started Java 3D.
+ *
+ * @param priority the new thread priority
+ *
+ * @exception IllegalArgumentException if the priority is not in
+ * the range MIN_PRIORITY to MAX_PRIORITY
+ *
+ * @exception SecurityException if the priority is greater than
+ * that of the calling thread
+ *
+ * @since Java 3D 1.2
+ */
+ public static void setJ3DThreadPriority(int priority) {
+ if (priority > Thread.MAX_PRIORITY) {
+ priority = Thread.MAX_PRIORITY;
+ } else if (priority < Thread.MIN_PRIORITY) {
+ priority = Thread.MIN_PRIORITY;
+ }
+ VirtualUniverse.mc.setThreadPriority(priority);
+ }
+
+
+ /**
+ * Retrieves that priority of Java 3D's threads.
+ *
+ * @return the current priority of Java 3D's threads
+ *
+ * @since Java 3D 1.2
+ */
+ public static int getJ3DThreadPriority() {
+ return VirtualUniverse.mc.getThreadPriority();
+ }
+
+
+ /**
+ * Returns a read-only Map object containing key-value pairs that
+ * define various global properties for Java 3D. All of the keys
+ * are String objects. The values are key-specific, but most will
+ * be String objects.
+ *
+ * <p>
+ * The set of global Java 3D properties always includes values for
+ * the following keys:
+ *
+ * <p>
+ * <ul>
+ * <table BORDER=1 CELLSPACING=1 CELLPADDING=1>
+ * <tr>
+ * <td><b>Key (String)</b></td>
+ * <td><b>Value Type</b></td>
+ * </tr>
+ * <tr>
+ * <td><code>j3d.version</code></td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td><code>j3d.vendor</code></td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td><code>j3d.specification.version</code></td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td><code>j3d.specification.vendor</code></td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td><code>j3d.pipeline</code></td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td><code>j3d.renderer</code></td>
+ * <td>String</td>
+ * </tr>
+ * </table>
+ * </ul>
+ *
+ * <p>
+ * The descriptions of the values returned for each key are as follows:
+ *
+ * <p>
+ * <ul>
+ *
+ * <li>
+ * <code>j3d.version</code>
+ * <ul>
+ * A String that defines the Java 3D implementation version.
+ * The portion of the implementation version string before the first
+ * space must adhere to one of the the following three formats
+ * (anything after the first space is an optional free-form addendum
+ * to the version):
+ * <ul>
+ * <i>x</i>.<i>y</i>.<i>z</i><br>
+ * <i>x</i>.<i>y</i>.<i>z</i>_<i>p</i><br>
+ * <i>x</i>.<i>y</i>.<i>z</i>-<i>ssss</i><br>
+ * </ul>
+ * where:
+ * <ul>
+ * <i>x</i> is the major version number<br>
+ * <i>y</i> is the minor version number<br>
+ * <i>z</i> is the sub-minor version number<br>
+ * <i>p</i> is the patch revision number <br>
+ * <i>ssss</i> is a string, identifying a non-release build
+ * (e.g., beta1, build47, rc1, etc.). It may only
+ * contain letters, numbers, periods, dashes, or
+ * underscores.
+ * </ul>
+ * </ul>
+ * </li>
+ * <p>
+ *
+ * <li>
+ * <code>j3d.vendor</code>
+ * <ul>
+ * String that specifies the Java 3D implementation vendor.
+ * </ul>
+ * </li>
+ * <p>
+ *
+ * <li>
+ * <code>j3d.specification.version</code>
+ * <ul>
+ * A String that defines the Java 3D specification version.
+ * This string must be of the following form:
+ * <ul>
+ * <i>x</i>.<i>y</i>
+ * </ul>
+ * where:
+ * <ul>
+ * <i>x</i> is the major version number<br>
+ * <i>y</i> is the minor version number<br>
+ * </ul>
+ * No other characters are allowed in the specification version string.
+ * </ul>
+ * </li>
+ * <p>
+ *
+ * <li>
+ * <code>j3d.specification.vendor</code>
+ * <ul>
+ * String that specifies the Java 3D specification vendor.
+ * </ul>
+ * </li>
+ * <p>
+ *
+ * <li>
+ * <code>j3d.pipeline</code>
+ * <ul>
+ * String that specifies the Java 3D rendering pipeline. This could
+ * be one of: "NATIVE_OGL", "NATIVE_D3D", or "JOGL". Others could be
+ * added in the future.
+ * </ul>
+ * </li>
+ * <p>
+ *
+ * <li>
+ * <code>j3d.renderer</code>
+ * <ul>
+ * String that specifies the underlying rendering library. This could
+ * be one of: "OpenGL" or "DirectX". Others could be added in the future.
+ * </ul>
+ * </li>
+ * <p>
+ *
+ * </ul>
+ *
+ * @return the global Java 3D properties
+ *
+ * @since Java 3D 1.3
+ */
+ public static final Map getProperties() {
+ if (properties == null) {
+ // Create lists of keys and values
+ ArrayList<String> keys = new ArrayList<String>();
+ ArrayList<Object> values = new ArrayList<Object>();
+
+ // Implementation version string is obtained from the
+ // ImplementationVersion class.
+ keys.add("j3d.version");
+ values.add(VersionInfo.getVersion());
+
+ keys.add("j3d.vendor");
+ values.add(VersionInfo.getVendor());
+
+ keys.add("j3d.specification.version");
+ values.add(VersionInfo.getSpecificationVersion());
+
+ keys.add("j3d.specification.vendor");
+ values.add(VersionInfo.getSpecificationVendor());
+
+ keys.add("j3d.renderer");
+ values.add(Pipeline.getPipeline().getRendererName());
+
+ keys.add("j3d.pipeline");
+ values.add(Pipeline.getPipeline().getPipelineName());
+
+ // Now Create read-only properties object
+ properties = new J3dQueryProps(keys, values);
+ }
+ return properties;
+ }
+
+
+ /**
+ * This returns the next available nodeId as a string.
+ */
+ // XXXX: reuse of id's imply a slight collision problem in the
+ // render queue's.
+ // BUG 4181362
+ String getNodeId() {
+ String str;
+
+ if (nodeIdFreeList.size() == 0) {
+ str = Long.toString(nodeIdCount);
+ nodeIdCount++;
+ } else {
+ // Issue 496: Remove last object using index to avoid performance
+ // hit of a needless linear search.
+ int idx = nodeIdFreeList.size() - 1;
+ str = nodeIdFreeList.remove(idx);
+ }
+ return(str);
+ }
+
+ /**
+ * This returns the next available viewId
+ */
+ Integer getViewId() {
+ Integer id;
+ int size;
+
+ synchronized (viewIdFreeList) {
+ size = viewIdFreeList.size();
+ if (size == 0) {
+ id = new Integer(viewIdCount++);
+ } else {
+ id = viewIdFreeList.remove(size - 1);
+ }
+ }
+ return(id);
+ }
+
+ /**
+ * This returns a viewId to the freelist
+ */
+ void addViewIdToFreeList(Integer viewId) {
+ synchronized (viewIdFreeList) {
+ viewIdFreeList.add(viewId);
+ }
+ }
+
+void addViewPlatform(ViewPlatformRetained vp) {
+ synchronized (viewPlatforms) {
+ vpChanged = true;
+ viewPlatforms.add(vp);
+ }
+}
+
+void removeViewPlatform(ViewPlatformRetained vp) {
+ synchronized (viewPlatforms) {
+ if (viewPlatforms.remove(vp))
+ vpChanged = true;
+ }
+}
+
+ViewPlatformRetained[] getViewPlatformList() {
+ synchronized (viewPlatforms) {
+ if (vpChanged) {
+ viewPlatformList = viewPlatforms.toArray(new ViewPlatformRetained[viewPlatforms.size()]);
+ vpChanged = false;
+ }
+
+ return viewPlatformList;
+ }
+}
+
+ void checkForEnableEvents() {
+ if (enableFocus) {
+ enableFocusEvents();
+ }
+ if (enableKey) {
+ enableKeyEvents();
+ }
+ if (enableMouse) {
+ enableMouseEvents();
+ }
+ if (enableMouseMotion) {
+ enableMouseMotionEvents();
+ }
+ if (enableMouseWheel) {
+ enableMouseWheelEvents();
+ }
+
+ }
+
+void disableFocusEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableFocus = false;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.disableFocusEvents();
+ }
+ }
+ }
+}
+
+void enableFocusEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableFocus = true;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.enableFocusEvents();
+ }
+ }
+ }
+}
+
+void disableKeyEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableKey = false;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.disableKeyEvents();
+ }
+ }
+ }
+}
+
+void enableKeyEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableKey = true;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.enableKeyEvents();
+ }
+ }
+ }
+}
+
+void disableMouseEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableMouse = false;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.disableMouseEvents();
+ }
+ }
+ }
+}
+
+void enableMouseEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableMouse = true;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.enableMouseEvents();
+ }
+ }
+ }
+}
+
+void disableMouseMotionEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableMouseMotion = false;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.disableMouseMotionEvents();
+ }
+ }
+ }
+}
+
+void enableMouseMotionEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableMouseMotion = true;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.enableMouseMotionEvents();
+ }
+ }
+ }
+}
+
+void disableMouseWheelEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableMouseWheel = false;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.disableMouseWheelEvents();
+ }
+ }
+ }
+}
+
+void enableMouseWheelEvents() {
+ ViewPlatformRetained[] vps = getViewPlatformList();
+ enableMouseWheel = true;
+
+ for (int i = 0; i < vps.length; i++) {
+ View[] views = vps[i].getViewList();
+ for (int j = views.length - 1; j >= 0; j--) {
+ Enumeration<Canvas3D> cvs = views[j].getAllCanvas3Ds();
+ while (cvs.hasMoreElements()) {
+ Canvas3D cv = cvs.nextElement();
+ // offscreen canvas does not have event catcher
+ if (cv.eventCatcher != null)
+ cv.eventCatcher.enableMouseWheelEvents();
+ }
+ }
+ }
+}
+
+ /**
+ * Sets the "current" view (during view activation) for this virtual
+ * universe.
+ * @param last activated view
+ */
+ final void setCurrentView(View view) {
+ this.currentView = view;
+ }
+
+ /**
+ * Returns the "current" view (the last view activated for this virtual
+ * universe.
+ * @return last activated view
+ */
+ final View getCurrentView() {
+ return this.currentView;
+ }
+
+
+ /**
+ * Method to return the root thread group. This must be called from
+ * within a doPrivileged block.
+ */
+ static ThreadGroup getRootThreadGroup() {
+ return rootThreadGroup;
+ }
+
+ /**
+ * return true if all Locales under it don't have branchGroup
+ * attach to it.
+ */
+ boolean isEmpty() {
+ Enumeration<Locale> elm = listOfLocales.elements();
+
+ while (elm.hasMoreElements()) {
+ Locale loc = elm.nextElement();
+ if (!loc.branchGroups.isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void resetWaitMCFlag() {
+ synchronized (waitLock) {
+ regViewWaiting = null;
+ unRegViewWaiting = null;
+ isSceneGraphLock = true;
+ }
+ }
+
+ void waitForMC() {
+ synchronized (waitLock) {
+ if (unRegViewWaiting != null) {
+ if ((regViewWaiting == null) ||
+ (regViewWaiting != unRegViewWaiting)) {
+ while (!unRegViewWaiting.doneUnregister) {
+ MasterControl.threadYield();
+ }
+ unRegViewWaiting.doneUnregister = false;
+ unRegViewWaiting = null;
+ }
+ }
+
+ if (regViewWaiting != null) {
+ while (!VirtualUniverse.mc.isRegistered(regViewWaiting)) {
+ MasterControl.threadYield();
+ }
+ regViewWaiting = null;
+ }
+ isSceneGraphLock = false;
+ }
+ }
+
+ /**
+ * Adds the specified GraphStructureChangeListener to the set of listeners
+ * that will be notified when the graph structure is changed on a live
+ * scene graph. If the specifed listener is null no action is taken and no
+ * exception is thrown.
+ *
+ * @param listener the listener to add to the set.
+ *
+ * @since Java 3D 1.4
+ */
+ public void addGraphStructureChangeListener(GraphStructureChangeListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ if (structureChangeListenerSet == null) {
+ structureChangeListenerSet = new HashSet<GraphStructureChangeListener>();
+ }
+
+ synchronized(structureChangeListenerSet) {
+ structureChangeListenerSet.add(listener);
+ }
+ }
+
+ /**
+ * Removes the specified GraphStructureChangeListener from the set of listeners. This
+ * method performs no function, nor does it throw an exception if the specified listener
+ * is not currently in the set or is null.
+ *
+ * @param listener the listener to remove from the set.
+ *
+ * @since Java 3D 1.4
+ */
+ public void removeGraphStructureChangeListener(GraphStructureChangeListener listener) {
+ if (structureChangeListenerSet == null) {
+ return;
+ }
+
+ synchronized(structureChangeListenerSet) {
+ structureChangeListenerSet.remove(listener);
+ }
+ }
+
+ /**
+ * Processes all live BranchGroup add and removes and notifies
+ * any registered listeners. Used for add and remove
+ */
+ void notifyStructureChangeListeners(boolean add, Object parent, BranchGroup child) {
+ if (structureChangeListenerSet == null) {
+ return;
+ }
+
+ synchronized(structureChangeListenerSet) {
+ Iterator<GraphStructureChangeListener> it = structureChangeListenerSet.iterator();
+ while(it.hasNext()) {
+ GraphStructureChangeListener listener = it.next();
+ try {
+ if (add) {
+ listener.branchGroupAdded(parent, child);
+ } else {
+ listener.branchGroupRemoved(parent, child);
+ }
+ }
+ catch (RuntimeException e) {
+ System.err.println("Exception occurred in GraphStructureChangeListener:");
+ e.printStackTrace();
+ }
+ catch (Error e) {
+ // Issue 264 - catch Error
+ System.err.println("Error occurred in GraphStructureChangeListener:");
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes all live BranchGroup moves and notifies
+ * any registered listeners. Used for moveTo
+ */
+ void notifyStructureChangeListeners(Object oldParent, Object newParent, BranchGroup child) {
+ if (structureChangeListenerSet == null) {
+ return;
+ }
+
+ synchronized(structureChangeListenerSet) {
+ Iterator<GraphStructureChangeListener> it = structureChangeListenerSet.iterator();
+ while(it.hasNext()) {
+ GraphStructureChangeListener listener = it.next();
+ try {
+ listener.branchGroupMoved(oldParent, newParent, child);
+ }
+ catch (RuntimeException e) {
+ System.err.println("Exception occurred in GraphStructureChangeListener:");
+ e.printStackTrace();
+ }
+ catch (Error e) {
+ // Issue 264 - catch Error
+ System.err.println("Error occurred in GraphStructureChangeListener:");
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Adds the specified ShaderErrorListener to the set of listeners
+ * that will be notified when a programmable shader error is
+ * detected on a live scene graph. If the specifed listener is
+ * null no action is taken and no exception is thrown.
+ * If a shader error occurs, the listeners will be called
+ * asynchronously from a separate notification thread. The Java 3D
+ * renderer and behavior scheduler will continue to run as if the
+ * error had not occurred, except that shading will be disabled
+ * for the objects in error. If applications desire to detach or
+ * modify the scene graph as a result of the error, they should
+ * use a behavior post if they want that change to be
+ * synchronous with the renderer.
+ *
+ * @param listener the listener to add to the set.
+ *
+ * @since Java 3D 1.4
+ */
+ public void addShaderErrorListener(ShaderErrorListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ if (shaderErrorListenerSet == null) {
+ shaderErrorListenerSet = new HashSet<ShaderErrorListener>();
+ }
+
+ synchronized(shaderErrorListenerSet) {
+ shaderErrorListenerSet.add(listener);
+ }
+ }
+
+ /**
+ * Removes the specified ShaderErrorListener from the set of
+ * listeners. This method performs no function, nor does it throw
+ * an exception if the specified listener is not currently in the
+ * set or is null.
+ *
+ * @param listener the listener to remove from the set.
+ *
+ * @since Java 3D 1.4
+ */
+ public void removeShaderErrorListener(ShaderErrorListener listener) {
+ if (shaderErrorListenerSet == null) {
+ return;
+ }
+
+ synchronized(shaderErrorListenerSet) {
+ shaderErrorListenerSet.remove(listener);
+ }
+ }
+
+ /**
+ * Notifies all listeners of a shader error. If no listeners exist, a default
+ * listener is notified.
+ */
+ void notifyShaderErrorListeners(ShaderError error) {
+ boolean errorReported = false;
+
+ // Notify all error listeners in the set
+ if (shaderErrorListenerSet != null) {
+ synchronized(shaderErrorListenerSet) {
+ Iterator<ShaderErrorListener> it = shaderErrorListenerSet.iterator();
+ while(it.hasNext()) {
+ ShaderErrorListener listener = it.next();
+ try {
+ listener.errorOccurred(error);
+ }
+ catch (RuntimeException e) {
+ System.err.println("Exception occurred in ShaderErrorListener:");
+ e.printStackTrace();
+ }
+ catch (Error e) {
+ // Issue 264 - catch Error
+ System.err.println("Error occurred in ShaderErrorListener:");
+ e.printStackTrace();
+ }
+ errorReported = true;
+ }
+ }
+ }
+
+ // Notify the default error listener if the set is null or empty
+ if (!errorReported) {
+ defaultShaderErrorListener.errorOccurred(error);
+ }
+ }
+
+
+ // Issue 260 : rendering error listeners.
+
+ /**
+ * Adds the specified RenderingErrorListener to the set of listeners
+ * that will be notified when a rendering error is detected.
+ * If the specifed listener is null no action is taken and no exception
+ * is thrown.
+ * If a rendering error occurs, the listeners will be called
+ * asynchronously from a separate notification thread. If the set
+ * of listeners is empty, a default listener is notified. The
+ * default listener prints the error information to System.err and
+ * then calls System.exit().
+ *
+ * @param listener the listener to add to the set.
+ *
+ * @since Java 3D 1.5
+ */
+ public static void addRenderingErrorListener(RenderingErrorListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ if (renderingErrorListenerSet == null) {
+ renderingErrorListenerSet = new HashSet<RenderingErrorListener>();
+ }
+
+ synchronized(renderingErrorListenerSet) {
+ renderingErrorListenerSet.add(listener);
+ }
+ }
+
+ /**
+ * Removes the specified RenderingErrorListener from the set of
+ * listeners. This method performs no function, nor does it throw
+ * an exception if the specified listener is not currently in the
+ * set or is null.
+ *
+ * @param listener the listener to remove from the set.
+ *
+ * @since Java 3D 1.5
+ */
+ public static void removeRenderingErrorListener(RenderingErrorListener listener) {
+ if (renderingErrorListenerSet == null) {
+ return;
+ }
+
+ synchronized(renderingErrorListenerSet) {
+ renderingErrorListenerSet.remove(listener);
+ }
+ }
+
+ /**
+ * Notifies all listeners of a rendering error. If no listeners exist,
+ * a default listener is notified.
+ */
+ static void notifyRenderingErrorListeners(RenderingError error) {
+ boolean errorReported = false;
+
+ // Notify all error listeners in the set
+ if (renderingErrorListenerSet != null) {
+ synchronized(renderingErrorListenerSet) {
+ Iterator<RenderingErrorListener> it = renderingErrorListenerSet.iterator();
+ while(it.hasNext()) {
+ RenderingErrorListener listener = it.next();
+ try {
+ listener.errorOccurred(error);
+ }
+ catch (RuntimeException e) {
+ System.err.println("Exception occurred in RenderingErrorListener:");
+ e.printStackTrace();
+ }
+ catch (Error e) {
+ // Issue 264 - catch Error
+ System.err.println("Error occurred in RenderingErrorListener:");
+ e.printStackTrace();
+ }
+ errorReported = true;
+ }
+ }
+ }
+
+ // Notify the default error listener if the set is null or empty
+ if (!errorReported) {
+ defaultRenderingErrorListener.errorOccurred(error);
+ }
+ }
+
+}