1 /*
2  * $RCSfile: SceneGraphObject.java,v $
3  *
4  * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6  *
7  * This code is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 only, as
9  * published by the Free Software Foundation.  Sun designates this
10  * particular file as subject to the "Classpath" exception as provided
11  * by Sun in the LICENSE file that accompanied this code.
12  *
13  * This code is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  * version 2 for more details (a copy is included in the LICENSE file that
17  * accompanied this code).
18  *
19  * You should have received a copy of the GNU General Public License version
20  * 2 along with this work; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24  * CA 95054 USA or visit www.sun.com if you need additional information or
25  * have any questions.
26  *
27  * $Revision: 1.7 $
28  * $Date: 2008/02/28 20:17:29 $
29  * $State: Exp $
30  */
31 
32 package javax.media.j3d;
33 
34 import java.util.Hashtable;
35 
36 /**
37  * SceneGraphObject is the common superclass for all scene graph
38  * objects. Scene graph objects are classified into two main types:
39  * nodes and node components. The Node object is the common superclass
40  * of all nodes, which includes TransformGroup, Shape3D, etc.
41  * The NodeComponent object is the common superclass of all node
42  * components, which includes Geometry, Appearance, etc.
43  *
44  * <p>
45  * All scene graph objects have a name, a user data object, a set of
46  * capability bits, and a set of capabilityIsFrequent bits.
47  *
48  * <p>
49  * Capability bits control whether a particular attribute in a node or
50  * node component is readable or writable. For live or compiled scene
51  * graphs, only those attributes whose capabilities are set before the
52  * scene graph is compiled or made live may be read or written. The
53  * default value for all <i>read</i> capability bits is true, meaning
54  * that all attributes may be read by default. The default value for
55  * all <i>write</i> capability bits is false, meaning that no
56  * attributes may be written by default. Read capability bits are
57  * defined as those capability bits of the form <code>ALLOW_*_READ</code>,
58  * plus the <code>ALLOW_INTERSECT</code> capability bit. Write
59  * capability bits are defined as those capability bits of the form
60  * <code>ALLOW_*_WRITE</code>, plus the <code>ALLOW_CHILDREN_EXTEND</code>
61  * and <code>ALLOW_DETACH</code> capability bits.
62  *
63  * <p>
64  * NOTE that the <code>ENABLE_COLLISION_REPORTING</code> and
65  * <code>ENABLE_PICK_REPORTING</code> bits are not really capability bits,
66  * although they are set with the setCapability method. The default value
67  * for each of the <code>ENABLE_*_REPORTING bits</code> is false.
68  *
69  * <p>
70  * For more information, see the
71  * <a href="doc-files/intro.html">Introduction to the Java 3D API</a>.
72  */
73 public abstract class SceneGraphObject extends Object {
74    // Any global flags? (e.g., execution cullable, collideable)
75 
76     // Reference to the retained-mode scene-graph element.
77     SceneGraphObjectRetained retained;
78 
79     // This object's capability bits
80     private long capabilityBits = 0L;
81 
82     // This object's capabilityIsFrequent bits
83     private long capabilityIsFrequentBits = ~0L;
84 
85     //boolean indicating is Scene Graph is compiled
86     private boolean compiled = false;
87 
88     //boolean indicating if Scene Graph is live.
89     private boolean live = false;
90 
91     //boolean indicating if Scene Graph is live or compiled
92     private boolean liveOrCompiled = false;
93 
94     // A reference to user data
95     private Object userData = null;
96 
97     // Optional name for object.
98     private String objectName = null;
99 
100     // use for cloneTree/cloneNode only, set to null after the operation
101     Hashtable nodeHashtable = null;
102 
103 
104 
105     /**
106      * Constructs a SceneGraphObject with default parameters.  The default
107      * values are as follows:
108      * <ul>
109      * all <i>read</i> capability bits : set (true)<br>
110      * all <i>write</i> capability bits : clear (false)<br>
111      * all capabilityIsFrequent bits : set (true)<br>
112      * isLive : false<br>
113      * isCompiled : false<br>
114      * user data : null<br>
115      * name : null<br>
116      * </ul>
117      */
SceneGraphObject()118     public SceneGraphObject() {
119 	createRetained();
120     }
121 
122     /**
123      * Creates the retained mode object that this scene graph object
124      * will point to.  This should be overridden by those classes
125      * that have a specific retained mode object.
126      */
createRetained()127     void createRetained() {
128 	this.retained = null;
129 
130 	// Non-abstract subclasses of SceneGraphObject should override
131 	// this function with code which is something like the following:
132 	//
133 	//	this.retained = new <ClassName>Retained();
134 	//	this.retained.setSource(this);
135     }
136 
137     /**
138      * Method to set default read capability bits to true
139      */
setDefaultReadCapabilities(int[] bits)140     void setDefaultReadCapabilities(int[] bits) {
141         if (true /*VirtualUniverse.mc.defaultReadCapability*/) {
142             for (int i=0; i < bits.length; i++) {
143                 setCapability(bits[i]);
144             }
145         }
146     }
147 
148     /**
149      * Retrieves the specified capability bit.  Note that only one capability
150      * bit may be retrieved per method invocation--capability bits cannot
151      * be ORed together.
152      * @param bit the bit whose value is returned
153      * @return true if the bit is set, false if the bit is clear
154      */
getCapability(int bit)155     public final boolean getCapability(int bit) {
156 	return (capabilityBits & (1L << bit)) != 0L;
157     }
158 
159     /**
160      * Sets the specified capability bit.  Note that only one capability bit
161      * may be set per method invocation--capability bits cannot be ORed
162      * together.
163      * @param bit the bit to set
164      * @exception RestrictedAccessException if this object is part of live
165      * or compiled scene graph
166      */
setCapability(int bit)167     public final void setCapability(int bit) {
168 	if (isLiveOrCompiled()) {
169             throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject0"));
170 	}
171 
172 	capabilityBits |= (1L << bit);
173 	retained.handleFrequencyChange(bit);
174 
175     }
176 
177     /**
178      * Clear the specified capability bit.  Note that only one capability bit
179      * may be cleared per method invocation--capability bits cannot be ORed
180      * together.
181      * @param bit the bit to clear
182      * @exception RestrictedAccessException if this object is part of live
183      * or compiled scene graph
184      */
clearCapability(int bit)185     public final void clearCapability(int bit) {
186 	if (isLiveOrCompiled())
187             throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject0"));
188 
189 	capabilityBits &= ~(1L << bit);
190 	retained.handleFrequencyChange(bit);
191     }
192 
193 
194     // Internal method, returns true if no capability bits are set
capabilityBitsEmpty()195     final boolean capabilityBitsEmpty() {
196 	return capabilityBits == 0L;
197     }
198 
199 
200     /**
201      * Retrieves the isFrequent bit associated with the specified capability
202      * bit.
203      *
204      * Note that only one isFrequent bit, for a single capability
205      * bit, may be retrieved per method invocation--capability bits cannot
206      * be ORed together.
207      *
208      * @param bit the bit whose value is returned
209      *
210      * @return true if the isFrequent bit is set, false if the isFrequent
211      * bit is clear
212      *
213      * @since Java 3D 1.3
214      */
getCapabilityIsFrequent(int bit)215     public final boolean getCapabilityIsFrequent(int bit) {
216 	return (capabilityIsFrequentBits & (1L << bit)) != 0L;
217     }
218 
219     /**
220      * Sets the isFrequent bit associated with the specified
221      * capability bit.  Setting the isFrequent bit indicates that the
222      * application may frequently access or modify those attributes
223      * permitted by the associated capability bit.  This can be used
224      * by Java 3D as a hint to avoid certain optimizations that could
225      * cause those accesses or modifications to be expensive.  By
226      * default the isFrequent bit associated with each capability bit
227      * is set.
228      *
229      * <p>
230      * Unlike setCapability, this method may be called on a live scene
231      * graph object (but not on a compiled object).
232      *
233      * <p>
234      * Note that only one isFrequent bit, for a single capability bit,
235      * may be set per method invocation--capability bits cannot be ORed
236      * together.
237      *
238      * @param bit the capability bit for which to set the associated
239      * isFrequent bit
240      *
241      * @exception RestrictedAccessException if this object is part of a
242      * compiled scene graph
243      *
244      * @since Java 3D 1.3
245      */
setCapabilityIsFrequent(int bit)246     public final void setCapabilityIsFrequent(int bit) {
247 	if (isCompiled())
248             throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject1"));
249 
250 	capabilityIsFrequentBits |= (1L << bit);
251 	retained.handleFrequencyChange(bit);
252     }
253 
254     /**
255      * Clears the isFrequent bit associated with the specified
256      * capability bit.  Clearing the isFrequent bit indicates that the
257      * application will infrequently access or modify those attributes
258      * permitted by the associated capability bit.  This can be used
259      * by Java 3D as a hint to enable certain optimizations that it
260      * might otherwise avoid, for example, optimizations that could
261      * cause those accesses or modifications to be expensive.
262      *
263      * <p>
264      * Unlike clearCapability, this method may be called on a live scene
265      * graph object (but not on a compiled object).
266      *
267      * <p>
268      * Note that only one isFrequent bit, for a single capability bit,
269      * may be cleared per method invocation--capability bits cannot be ORed
270      * together.
271      *
272      * @param bit the capability bit for which to clear the associated
273      * isFrequent bit
274      *
275      * @exception RestrictedAccessException if this object is part of a
276      * compiled scene graph
277      *
278      * @since Java 3D 1.3
279      */
clearCapabilityIsFrequent(int bit)280     public final void clearCapabilityIsFrequent(int bit) {
281 	if (isCompiled())
282             throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject1"));
283 
284 	capabilityIsFrequentBits &= ~(1L << bit);
285 	retained.handleFrequencyChange(bit);
286     }
287 
288 
289     /**
290      * Sets an internal flag which indicates that this scene graph object
291      * has been compiled.
292      */
setCompiled()293     final void setCompiled() {
294 	this.compiled = true;
295 	this.liveOrCompiled = this.live || this.compiled;
296     }
297 
298     /**
299      * Returns a flag indicating whether the node is part of a scene graph
300      * that has been compiled.  If so, then only those capabilities explicitly
301      * allowed by the object's capability bits are allowed.
302      * @return true if node is part of a compiled scene graph, else false
303      */
304 
isCompiled()305     public final boolean isCompiled() {
306 	return this.compiled;
307     }
308 
309     /**
310      * Sets an internal flag which indicates that this scene graph object
311      * is part of a live scene graph.
312      */
setLive()313     final void setLive() {
314 	this.live = true;
315 	this.liveOrCompiled = this.live || this.compiled;
316     }
317 
318     /**
319      * Clears an internal flag which indicates that this scene graph object
320      * is no longer part of a live scene graph.
321      */
clearLive()322     final void clearLive() {
323         this.live = false;
324         this.liveOrCompiled = this.live || this.compiled;
325     }
326 
327     /**
328      * Returns a flag indicating whether the node is part of a live
329      * scene graph.
330      * @return true if node is part of a live scene graph, else false
331      */
isLive()332     public final boolean isLive() {
333 	return this.live;
334     }
335 
336     /**
337      * Returns a flag indicating whether the node is part of a live
338      * scene graph or a compiled scene graph.
339      * @return true if either live or compiled
340      */
isLiveOrCompiled()341     final boolean isLiveOrCompiled() {
342 	return liveOrCompiled;
343     }
344 
checkForLiveOrCompiled()345     final void checkForLiveOrCompiled() {
346 	if (isLiveOrCompiled())
347 	    throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject2"));
348     }
349 
350     /**
351      * Sets the userData field associated with this scene graph object.
352      * The userData field is a reference to an arbitrary object
353      * and may be used to store any user-specific data associated
354      * with this scene graph object--it is not used by the Java 3D API.
355      * If this object is cloned, the userData field is copied
356      * to the newly cloned object.
357      * @param userData a reference to the new userData field
358      */
setUserData(Object userData)359     public void setUserData(Object userData) {
360 	this.userData = userData;
361     }
362 
363     /**
364      * Retrieves the userData field from this scene graph object.
365      * @return the current userData field
366      */
getUserData()367     public Object getUserData() {
368 	return this.userData;
369     }
370 
371    /**
372      * Callback used to allow a node to check if any scene graph objects
373      * referenced by that node have been duplicated via a call to
374      * <code>cloneTree</code>.
375      * This method is called by <code>cloneTree</code> after all nodes in
376      * the sub-graph have been duplicated. The cloned Leaf
377      * node and cloned NodeComponent's method
378      * will be called and the Leaf node/NodeComponent can then look up
379      * any object references
380      * by using the <code>getNewObjectReference</code> method found in the
381      * <code>NodeReferenceTable</code> object.  If a match is found, a
382      * reference to the corresponding object in the newly cloned sub-graph
383      * is returned.  If no corresponding reference is found, either a
384      * DanglingReferenceException is thrown or a reference to the original
385      * object is returned depending on the value of the
386      * <code>allowDanglingReferences</code> parameter passed in the
387      * <code>cloneTree</code> call.
388      * <p>
389      * NOTE: Applications should <i>not</i> call this method directly.
390      * It should only be called by the cloneTree method.
391      *
392      * @param referenceTable a NodeReferenceTableObject that contains the
393      *  <code>getNewObjectReference</code> method needed to search for
394      *  new object instances.
395      * @see NodeReferenceTable
396      * @see Node#cloneTree
397      * @see DanglingReferenceException
398      */
updateNodeReferences(NodeReferenceTable referenceTable)399     public void updateNodeReferences(NodeReferenceTable referenceTable) {
400     }
401 
402     /**
403      * Sets the name of this object. Object names are for information
404      * only.
405      *
406      * @param name the new name of this object
407      *
408      * @since Java 3D 1.4
409      */
setName( String name )410     public void setName( String name ) {
411         objectName = name;
412     }
413 
414     /**
415      * Returns the name of this object.
416      *
417      * @return the name of this object
418      *
419      * @since Java 3D 1.4
420      */
getName()421     public String getName() {
422 	return objectName;
423     }
424 
425     /**
426      * Copies all SceneGraphObject information from
427      * <code>originalNode</code> into
428      * the current node.  This method is called from the
429      * <code>cloneNode</code> method which is, in turn, called by the
430      * <code>cloneTree</code> method.
431      * <P>
432      * NOTE: Applications should <i>not</i> call this method directly.
433      * It should only be called by the cloneNode method.
434      *
435      * @param originalNode the original node to duplicate.
436      *
437      * @see Group#cloneNode
438      * @see Node#duplicateNode
439      * @see Node#cloneTree
440      * @see NodeComponent#setDuplicateOnCloneTree
441      */
duplicateSceneGraphObject(SceneGraphObject originalNode)442     protected void duplicateSceneGraphObject(SceneGraphObject originalNode) {
443         // Duplicate any class specific data here.
444 	capabilityBits = originalNode.capabilityBits;
445         userData = originalNode.userData;
446         objectName = originalNode.objectName;
447     }
448 
449 
450     /**
451      * If <code>forceDuplicate</code> is <code>true</code> or
452      * <code>duplicateOnCloneTree</code> flag is true. This procedure
453      * will return a clone of originalNode or the value in
454      * in <code>nodeHashtable</code> if found. Otherwise return
455      * <code>originalNode</code>
456      *
457      * This method is called from the
458      * <code>duplicateAttributes</code> method during cloneNodeComponent.
459      *
460      * @param originalNodeComponent the original node to duplicate.
461      * @param forceDuplicate when set to <code>true</code>, causes the
462      *  <code>duplicateOnCloneTree</code> flag to be ignored.  When
463      *  <code>false</code>, the value of each node's
464      *  <code>duplicateOnCloneTree</code> variable determines whether
465      *  NodeComponent data is duplicated or copied.
466      * @param nodeHashtable is used to keep track of mapping between old and
467      *  new node references.
468      */
getNodeComponent(NodeComponent originalNodeComponent, boolean forceDuplicate, Hashtable hashtable)469     NodeComponent getNodeComponent(NodeComponent originalNodeComponent,
470 				   boolean forceDuplicate,
471 				   Hashtable hashtable) {
472         if ((originalNodeComponent != null) &&
473 	        (forceDuplicate ||
474 		 originalNodeComponent.duplicateChild())) {
475 	    NodeComponent nc = (NodeComponent)
476 	                           hashtable.get(originalNodeComponent);
477 	    if (nc == null) {
478 	        originalNodeComponent.nodeHashtable = hashtable;
479 		try {
480   	            nc = originalNodeComponent.
481 		             cloneNodeComponent(forceDuplicate);
482 		} catch (RuntimeException e) {
483 		  // must reset nodeHashtable in any case
484 		  originalNodeComponent.nodeHashtable = null;
485 		  throw e;
486 		}
487 		originalNodeComponent.nodeHashtable = null;
488 		// put link to be shared by other Node
489 		hashtable.put(originalNodeComponent, nc);
490 	    } // use the share clone node otherwise
491 	    return nc;
492 	} else {
493 	    return originalNodeComponent;
494 	}
495     }
496 
497     // Internal method to make a prefix out of the name of this object
getNamePrefix()498     String getNamePrefix() {
499 	String name = getName();
500 
501 	if (name != null) {
502 	    return "[" + name + "] ";
503 	}
504 
505 	return "";
506     }
507 
508     /**
509      * Returns a String representation of this SceneGraphObject.
510      * If its name is non-null, then it is concatenated with
511      * super.toString().
512      */
toString()513     public String toString() {
514 	return getNamePrefix() + super.toString();
515     }
516 
517 }
518