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