summaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/SceneGraphObject.java
blob: db0eb5353bc046f9fe2ab9d010dafe8002d0b242 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
/*
 * 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.Hashtable;

/**
 * SceneGraphObject is the common superclass for all scene graph
 * objects. Scene graph objects are classified into two main types:
 * nodes and node components. The Node object is the common superclass
 * of all nodes, which includes TransformGroup, Shape3D, etc.
 * The NodeComponent object is the common superclass of all node
 * components, which includes Geometry, Appearance, etc.
 *
 * <p>
 * All scene graph objects have a name, a user data object, a set of
 * capability bits, and a set of capabilityIsFrequent bits.
 *
 * <p>
 * Capability bits control whether a particular attribute in a node or
 * node component is readable or writable. For live or compiled scene
 * graphs, only those attributes whose capabilities are set before the
 * scene graph is compiled or made live may be read or written. The
 * default value for all <i>read</i> capability bits is true, meaning
 * that all attributes may be read by default. The default value for
 * all <i>write</i> capability bits is false, meaning that no
 * attributes may be written by default. Read capability bits are
 * defined as those capability bits of the form <code>ALLOW_*_READ</code>,
 * plus the <code>ALLOW_INTERSECT</code> capability bit. Write
 * capability bits are defined as those capability bits of the form
 * <code>ALLOW_*_WRITE</code>, plus the <code>ALLOW_CHILDREN_EXTEND</code>
 * and <code>ALLOW_DETACH</code> capability bits.
 *
 * <p>
 * NOTE that the <code>ENABLE_COLLISION_REPORTING</code> and
 * <code>ENABLE_PICK_REPORTING</code> bits are not really capability bits,
 * although they are set with the setCapability method. The default value
 * for each of the <code>ENABLE_*_REPORTING bits</code> is false.
 *
 * <p>
 * For more information, see the
 * <a href="doc-files/intro.html">Introduction to the Java 3D API</a>.
 */
public abstract class SceneGraphObject extends Object {
   // Any global flags? (e.g., execution cullable, collideable)

    // Reference to the retained-mode scene-graph element.
    SceneGraphObjectRetained retained;

    // This object's capability bits
    private long capabilityBits = 0L;

    // This object's capabilityIsFrequent bits
    private long capabilityIsFrequentBits = ~0L;

    //boolean indicating is Scene Graph is compiled
    private boolean compiled = false;

    //boolean indicating if Scene Graph is live.
    private boolean live = false;

    //boolean indicating if Scene Graph is live or compiled
    private boolean liveOrCompiled = false;

    // A reference to user data
    private Object userData = null;

    // Optional name for object.
    private String objectName = null;

    // use for cloneTree/cloneNode only, set to null after the operation
    Hashtable nodeHashtable = null;



    /**
     * Constructs a SceneGraphObject with default parameters.  The default
     * values are as follows:
     * <ul>
     * all <i>read</i> capability bits : set (true)<br>
     * all <i>write</i> capability bits : clear (false)<br>
     * all capabilityIsFrequent bits : set (true)<br>
     * isLive : false<br>
     * isCompiled : false<br>
     * user data : null<br>
     * name : null<br>
     * </ul>
     */
    public SceneGraphObject() {
	createRetained();
    }

    /**
     * Creates the retained mode object that this scene graph object
     * will point to.  This should be overridden by those classes
     * that have a specific retained mode object.
     */
    void createRetained() {
	this.retained = null;

	// Non-abstract subclasses of SceneGraphObject should override
	// this function with code which is something like the following:
	//
	//	this.retained = new <ClassName>Retained();
	//	this.retained.setSource(this);
    }

    /**
     * Method to set default read capability bits to true
     */
    void setDefaultReadCapabilities(int[] bits) {
        if (true /*VirtualUniverse.mc.defaultReadCapability*/) {
            for (int i=0; i < bits.length; i++) {
                setCapability(bits[i]);
            }
        }
    }

    /**
     * Retrieves the specified capability bit.  Note that only one capability
     * bit may be retrieved per method invocation--capability bits cannot
     * be ORed together.
     * @param bit the bit whose value is returned
     * @return true if the bit is set, false if the bit is clear
     */
    public final boolean getCapability(int bit) {
	return (capabilityBits & (1L << bit)) != 0L;
    }

    /**
     * Sets the specified capability bit.  Note that only one capability bit
     * may be set per method invocation--capability bits cannot be ORed
     * together.
     * @param bit the bit to set
     * @exception RestrictedAccessException if this object is part of live
     * or compiled scene graph
     */
    public final void setCapability(int bit) {
	if (isLiveOrCompiled()) {
            throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject0"));
	}

	capabilityBits |= (1L << bit);
	retained.handleFrequencyChange(bit);

    }

    /**
     * Clear the specified capability bit.  Note that only one capability bit
     * may be cleared per method invocation--capability bits cannot be ORed
     * together.
     * @param bit the bit to clear
     * @exception RestrictedAccessException if this object is part of live
     * or compiled scene graph
     */
    public final void clearCapability(int bit) {
	if (isLiveOrCompiled())
            throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject0"));

	capabilityBits &= ~(1L << bit);
	retained.handleFrequencyChange(bit);
    }


    // Internal method, returns true if no capability bits are set
    final boolean capabilityBitsEmpty() {
	return capabilityBits == 0L;
    }


    /**
     * Retrieves the isFrequent bit associated with the specified capability
     * bit.
     *
     * Note that only one isFrequent bit, for a single capability
     * bit, may be retrieved per method invocation--capability bits cannot
     * be ORed together.
     *
     * @param bit the bit whose value is returned
     *
     * @return true if the isFrequent bit is set, false if the isFrequent
     * bit is clear
     *
     * @since Java 3D 1.3
     */
    public final boolean getCapabilityIsFrequent(int bit) {
	return (capabilityIsFrequentBits & (1L << bit)) != 0L;
    }

    /**
     * Sets the isFrequent bit associated with the specified
     * capability bit.  Setting the isFrequent bit indicates that the
     * application may frequently access or modify those attributes
     * permitted by the associated capability bit.  This can be used
     * by Java 3D as a hint to avoid certain optimizations that could
     * cause those accesses or modifications to be expensive.  By
     * default the isFrequent bit associated with each capability bit
     * is set.
     *
     * <p>
     * Unlike setCapability, this method may be called on a live scene
     * graph object (but not on a compiled object).
     *
     * <p>
     * Note that only one isFrequent bit, for a single capability bit,
     * may be set per method invocation--capability bits cannot be ORed
     * together.
     *
     * @param bit the capability bit for which to set the associated
     * isFrequent bit
     *
     * @exception RestrictedAccessException if this object is part of a
     * compiled scene graph
     *
     * @since Java 3D 1.3
     */
    public final void setCapabilityIsFrequent(int bit) {
	if (isCompiled())
            throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject1"));

	capabilityIsFrequentBits |= (1L << bit);
	retained.handleFrequencyChange(bit);
    }

    /**
     * Clears the isFrequent bit associated with the specified
     * capability bit.  Clearing the isFrequent bit indicates that the
     * application will infrequently access or modify those attributes
     * permitted by the associated capability bit.  This can be used
     * by Java 3D as a hint to enable certain optimizations that it
     * might otherwise avoid, for example, optimizations that could
     * cause those accesses or modifications to be expensive.
     *
     * <p>
     * Unlike clearCapability, this method may be called on a live scene
     * graph object (but not on a compiled object).
     *
     * <p>
     * Note that only one isFrequent bit, for a single capability bit,
     * may be cleared per method invocation--capability bits cannot be ORed
     * together.
     *
     * @param bit the capability bit for which to clear the associated
     * isFrequent bit
     *
     * @exception RestrictedAccessException if this object is part of a
     * compiled scene graph
     *
     * @since Java 3D 1.3
     */
    public final void clearCapabilityIsFrequent(int bit) {
	if (isCompiled())
            throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject1"));

	capabilityIsFrequentBits &= ~(1L << bit);
	retained.handleFrequencyChange(bit);
    }


    /**
     * Sets an internal flag which indicates that this scene graph object
     * has been compiled.
     */
    final void setCompiled() {
	this.compiled = true;
	this.liveOrCompiled = this.live || this.compiled;
    }

    /**
     * Returns a flag indicating whether the node is part of a scene graph
     * that has been compiled.  If so, then only those capabilities explicitly
     * allowed by the object's capability bits are allowed.
     * @return true if node is part of a compiled scene graph, else false
     */

    public final boolean isCompiled() {
	return this.compiled;
    }

    /**
     * Sets an internal flag which indicates that this scene graph object
     * is part of a live scene graph.
     */
    final void setLive() {
	this.live = true;
	this.liveOrCompiled = this.live || this.compiled;
    }

    /**
     * Clears an internal flag which indicates that this scene graph object
     * is no longer part of a live scene graph.
     */
    final void clearLive() {
        this.live = false;
        this.liveOrCompiled = this.live || this.compiled;
    }

    /**
     * Returns a flag indicating whether the node is part of a live
     * scene graph.
     * @return true if node is part of a live scene graph, else false
     */
    public final boolean isLive() {
	return this.live;
    }

    /**
     * Returns a flag indicating whether the node is part of a live
     * scene graph or a compiled scene graph.
     * @return true if either live or compiled
     */
    final boolean isLiveOrCompiled() {
	return liveOrCompiled;
    }

    final void checkForLiveOrCompiled() {
	if (isLiveOrCompiled())
	    throw new RestrictedAccessException(J3dI18N.getString("SceneGraphObject2"));
    }

    /**
     * Sets the userData field associated with this scene graph object.
     * The userData field is a reference to an arbitrary object
     * and may be used to store any user-specific data associated
     * with this scene graph object--it is not used by the Java 3D API.
     * If this object is cloned, the userData field is copied
     * to the newly cloned object.
     * @param userData a reference to the new userData field
     */
    public void setUserData(Object userData) {
	this.userData = userData;
    }

    /**
     * Retrieves the userData field from this scene graph object.
     * @return the current userData field
     */
    public Object getUserData() {
	return this.userData;
    }

   /**
     * Callback used to allow a node to check if any scene graph objects
     * referenced by that node have been duplicated via a call to
     * <code>cloneTree</code>.
     * This method is called by <code>cloneTree</code> after all nodes in
     * the sub-graph have been duplicated. The cloned Leaf
     * node and cloned NodeComponent's method
     * will be called and the Leaf node/NodeComponent can then look up
     * any object references
     * by using the <code>getNewObjectReference</code> method found in the
     * <code>NodeReferenceTable</code> object.  If a match is found, a
     * reference to the corresponding object in the newly cloned sub-graph
     * is returned.  If no corresponding reference is found, either a
     * DanglingReferenceException is thrown or a reference to the original
     * object is returned depending on the value of the
     * <code>allowDanglingReferences</code> parameter passed in the
     * <code>cloneTree</code> call.
     * <p>
     * NOTE: Applications should <i>not</i> call this method directly.
     * It should only be called by the cloneTree method.
     *
     * @param referenceTable a NodeReferenceTableObject that contains the
     *  <code>getNewObjectReference</code> method needed to search for
     *  new object instances.
     * @see NodeReferenceTable
     * @see Node#cloneTree
     * @see DanglingReferenceException
     */
    public void updateNodeReferences(NodeReferenceTable referenceTable) {
    }

    /**
     * Sets the name of this object. Object names are for information
     * only.
     *
     * @param name the new name of this object
     *
     * @since Java 3D 1.4
     */
    public void setName( String name ) {
        objectName = name;
    }

    /**
     * Returns the name of this object.
     *
     * @return the name of this object
     *
     * @since Java 3D 1.4
     */
    public String getName() {
	return objectName;
    }

    /**
     * Copies all SceneGraphObject information from
     * <code>originalNode</code> into
     * the current node.  This method is called from the
     * <code>cloneNode</code> method which is, in turn, called by the
     * <code>cloneTree</code> method.
     * <P>
     * NOTE: Applications should <i>not</i> call this method directly.
     * It should only be called by the cloneNode method.
     *
     * @param originalNode the original node to duplicate.
     *
     * @see Group#cloneNode
     * @see Node#duplicateNode
     * @see Node#cloneTree
     * @see NodeComponent#setDuplicateOnCloneTree
     */
    protected void duplicateSceneGraphObject(SceneGraphObject originalNode) {
        // Duplicate any class specific data here.
	capabilityBits = originalNode.capabilityBits;
        userData = originalNode.userData;
        objectName = originalNode.objectName;
    }


    /**
     * If <code>forceDuplicate</code> is <code>true</code> or
     * <code>duplicateOnCloneTree</code> flag is true. This procedure
     * will return a clone of originalNode or the value in
     * in <code>nodeHashtable</code> if found. Otherwise return
     * <code>originalNode</code>
     *
     * This method is called from the
     * <code>duplicateAttributes</code> method during cloneNodeComponent.
     *
     * @param originalNodeComponent the original node to duplicate.
     * @param forceDuplicate when set to <code>true</code>, causes the
     *  <code>duplicateOnCloneTree</code> flag to be ignored.  When
     *  <code>false</code>, the value of each node's
     *  <code>duplicateOnCloneTree</code> variable determines whether
     *  NodeComponent data is duplicated or copied.
     * @param nodeHashtable is used to keep track of mapping between old and
     *  new node references.
     */
    NodeComponent getNodeComponent(NodeComponent originalNodeComponent,
				   boolean forceDuplicate,
				   Hashtable hashtable) {
        if ((originalNodeComponent != null) &&
	        (forceDuplicate ||
		 originalNodeComponent.duplicateChild())) {
	    NodeComponent nc = (NodeComponent)
	                           hashtable.get(originalNodeComponent);
	    if (nc == null) {
	        originalNodeComponent.nodeHashtable = hashtable;
		try {
  	            nc = originalNodeComponent.
		             cloneNodeComponent(forceDuplicate);
		} catch (RuntimeException e) {
		  // must reset nodeHashtable in any case
		  originalNodeComponent.nodeHashtable = null;
		  throw e;
		}
		originalNodeComponent.nodeHashtable = null;
		// put link to be shared by other Node
		hashtable.put(originalNodeComponent, nc);
	    } // use the share clone node otherwise
	    return nc;
	} else {
	    return originalNodeComponent;
	}
    }

    // Internal method to make a prefix out of the name of this object
    String getNamePrefix() {
	String name = getName();

	if (name != null) {
	    return "[" + name + "] ";
	}

	return "";
    }

    /**
     * Returns a String representation of this SceneGraphObject.
     * If its name is non-null, then it is concatenated with
     * super.toString().
     */
    @Override
    public String toString() {
	return getNamePrefix() + super.toString();
    }

}