forked from hharrison/java3d-core
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBehavior.java
More file actions
525 lines (489 loc) · 21 KB
/
Copy pathBehavior.java
File metadata and controls
525 lines (489 loc) · 21 KB
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
514
515
516
517
518
519
520
521
522
523
524
525
/*
* Copyright 1996-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 org.scijava.java3d;
import java.util.Enumeration;
/**
* The Behavior leaf node provides a framework for adding user-defined
* actions into the scene graph. Behavior is an abstract class that
* defines two methods that must be overridden by a subclass: An
* <code>initialization</code> method, called once when the behavior
* becomes "live," and a <code>processStimulus</code> method called
* whenever appropriate by the Java 3D behavior scheduler. The
* Behavior node also contains an enable flag, a scheduling region,
* a scheduling interval, and a wakeup condition.
*
* <P>
* The <i>scheduling region</i> defines a spatial volume that serves
* to enable the scheduling of Behavior nodes. A Behavior node is
* <i>active</i> (can receive stimuli) whenever an active ViewPlatform's
* activation volume intersects a Behavior object's scheduling
* region. Only active behaviors can receive stimuli.
*
* <P>
* The <i>scheduling interval</i> defines a partial order of execution
* for behaviors that wake up in response to the same wakeup condition
* (that is, those behaviors that are processed at the same "time").
* Given a set of behaviors whose wakeup conditions are satisfied at
* the same time, the behavior scheduler will execute all behaviors in
* a lower scheduling interval before executing any behavior in a
* higher scheduling interval. Within a scheduling interval,
* behaviors can be executed in any order, or in parallel. Note that
* this partial ordering is only guaranteed for those behaviors that
* wake up at the same time in response to the same wakeup condition,
* for example, the set of behaviors that wake up every frame in
* response to a WakeupOnElapsedFrames(0) wakeup condition.
*
* <P>
* The <code>initialize</code> method allows a Behavior object to
* initialize its internal state and specify its initial wakeup
* condition(s). Java 3D invokes a behavior's initialize code when the
* behavior's containing BranchGroup node is added to the virtual
* universe. Java 3D does not invoke the initialize method in a new
* thread. Thus, for Java 3D to regain control, the initialize method
* must not execute an infinite loop; it must return. Furthermore, a
* wakeup condition must be set or else the behavior's processStimulus
* method is never executed.
*
* <P>
* The <code>processStimulus</code> method receives and processes a
* behavior's ongoing messages. The Java 3D behavior scheduler invokes
* a Behavior node's processStimulus method when an active ViewPlatform's
* activation volume intersects a Behavior object's scheduling region
* and all of that behavior's wakeup criteria are satisfied. The
* processStimulus method performs its computations and actions
* (possibly including the registration of state change information
* that could cause Java 3D to wake other Behavior objects),
* establishes its next wakeup condition, and finally exits.
* A typical behavior will modify one or more nodes or node components
* in the scene graph. These modifications can happen in parallel
* with rendering. In general, applications cannot count on behavior
* execution being synchronized with rendering. There are two
* exceptions to this general rule:
* <ol>
* <li>All modifications to scene graph objects (not including geometry
* by-reference or texture by-reference) made from the
* <code>processStimulus</code> method of a single behavior instance
* are guaranteed to take effect in the same rendering frame.</li>
* <li>All modifications to scene graph objects (not including geometry
* by-reference or texture by-reference) made from the
* <code>processStimulus</code> methods of the set of behaviors that
* wake up in response to a WakeupOnElapsedFrames(0) wakeup condition
* are guaranteed to take effect in the same rendering frame.</li>
* </ol>
*
* Note that modifications to geometry by-reference or texture
* by-reference are not guaranteed to show up in the same frame as
* other scene graph changes.
*
* <P>
* <b>Code Structure</b>
* <P>
* When the Java 3D behavior scheduler invokes a Behavior object's
* processStimulus method, that method may perform any computation it
* wishes. Usually, it will change its internal state and specify its
* new wakeup conditions. Most probably, it will manipulate scene
* graph elements. However, the behavior code can only change those
* aspects of a scene graph element permitted by the capabilities
* associated with that scene graph element. A scene graph's
* capabilities restrict behavioral manipulation to those
* manipulations explicitly allowed.
*
* <P>
* The application must provide the Behavior object with references to
* those scene graph elements that the Behavior object will
* manipulate. The application provides those references as arguments
* to the behavior's constructor when it creates the Behavior
* object. Alternatively, the Behavior object itself can obtain access
* to the relevant scene graph elements either when Java 3D invokes
* its initialize method or each time Java 3D invokes its
* processStimulus method.
*
* <P>
* Behavior methods have a very rigid structure. Java 3D assumes that
* they always run to completion (if needed, they can spawn
* threads). Each method's basic structure consists of the following:
*
* <P>
* <UL>
* <LI>Code to decode and extract references from the WakeupCondition
* enumeration that caused the object's awakening.</LI>
* <LI>Code to perform the manipulations associated with the
* WakeupCondition</LI>
* <LI>Code to establish this behavior's new WakeupCondition</LI>
* <LI>A path to Exit (so that execution returns to the Java 3D
* behavior scheduler)</LI>
* </UL>
*
* <P>
* <b>WakeupCondition Object</b>
* <P>
* A WakeupCondition object is an abstract class specialized to
* fourteen different WakeupCriterion objects and to four combining
* objects containing multiple WakeupCriterion objects. A Behavior
* node provides the Java 3D behavior scheduler with a WakeupCondition
* object. When that object's WakeupCondition has been satisfied, the
* behavior scheduler hands that same WakeupCondition back to the
* Behavior via an enumeration.
*
* <P>
* <b>WakeupCriterion Object</b>
* <P>
* Java 3D provides a rich set of wakeup criteria that Behavior
* objects can use in specifying a complex WakeupCondition. These
* wakeup criteria can cause Java 3D's behavior scheduler to invoke a
* behavior's processStimulus method whenever
*
* <UL>
* <LI>The center of a ViewPlatform enters a specified region</LI>
* <LI>The center of a ViewPlatform exits a specified region</LI>
* <LI>A behavior is activated</LI>
* <LI>A behavior is deactivated</LI>
* <LI>A specified TransformGroup node's transform changes</LI>
* <LI>Collision is detected between a specified Shape3D node's
* Geometry object and any other object</LI>
* <LI>Movement occurs between a specified Shape3D node's Geometry
* object and any other object with which it collides</LI>
* <LI>A specified Shape3D node's Geometry object no longer collides
* with any other object</LI>
* <LI>A specified Behavior object posts a specific event</LI>
* <LI>A specified AWT event occurs</LI>
* <LI>A specified time interval elapses</LI>
* <LI>A specified number of frames have been drawn</LI>
* <LI>The center of a specified Sensor enters a specified region</LI>
* <LI>The center of a specified Sensor exits a specified region</LI>
* </UL>
*
* <p>
* A Behavior object constructs a WakeupCriterion by constructing the
* appropriate criterion object. The Behavior object must provide the
* appropriate arguments (usually a reference to some scene graph
* object and possibly a region of interest). Thus, to specify a
* WakeupOnViewPlatformEntry, a behavior would specify the region that
* will cause the behavior to execute if an active ViewPlatform enters it.
*
* <p>
* Note that a unique WakeupCriterion object must be used with each
* instance of a Behavior. Sharing wakeup criteria among different
* instances of a Behavior is illegal.
*
* <p>
* <b>Additional Information</b>
* <p>
* For more information, see the
* <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and
* <a href="doc-files/Behaviors.html">Behaviors and Interpolators</a>
* documents.
*
* @see WakeupCondition
*/
public abstract class Behavior extends Leaf {
/**
* Constructs a Behavior node with default parameters. The default
* values are as follows:
* <ul>
* enable flag : true<br>
* scheduling bounds : null<br>
* scheduling bounding leaf : null<br>
* scheduling interval : numSchedulingIntervals / 2<br>
* </ul>
*/
public Behavior() {
}
/**
* Initialize this behavior. Classes that extend Behavior must
* provide their own initialize method.
* <br>
* NOTE: Applications should <i>not</i> call this method. It is called
* by the Java 3D behavior scheduler.
*/
public abstract void initialize();
/**
* Process a stimulus meant for this behavior. This method is invoked
* if the Behavior's wakeup criteria are satisfied and an active
* ViewPlatform's
* activation volume intersects with the Behavior's scheduling region.
* Classes that extend Behavior must provide their own processStimulus
* method.
* <br>
* NOTE: Applications should <i>not</i> call this method. It is called
* by the Java 3D behavior scheduler.
* @param criteria an enumeration of triggered wakeup criteria for this
* behavior
*/
public abstract void processStimulus(Enumeration criteria);
/**
* Set the Behavior's scheduling region to the specified bounds.
* This is used when the scheduling bounding leaf is set to null.
* @param region the bounds that contains the Behavior's new scheduling
* region
*/
public void setSchedulingBounds(Bounds region) {
((BehaviorRetained)this.retained).setSchedulingBounds(region);
}
/**
* Retrieves the Behavior node's scheduling bounds.
* @return this Behavior's scheduling bounds information
*/
public Bounds getSchedulingBounds() {
return ((BehaviorRetained)this.retained).getSchedulingBounds();
}
/**
* Set the Behavior's scheduling region to the specified bounding leaf.
* When set to a value other than null, this overrides the scheduling
* bounds object.
* @param region the bounding leaf node used to specify the Behavior
* node's new scheduling region
*/
public void setSchedulingBoundingLeaf(BoundingLeaf region) {
((BehaviorRetained)this.retained).setSchedulingBoundingLeaf(region);
}
/**
* Retrieves the Behavior node's scheduling bounding leaf.
* @return this Behavior's scheduling bounding leaf information
*/
public BoundingLeaf getSchedulingBoundingLeaf() {
return ((BehaviorRetained)this.retained).getSchedulingBoundingLeaf();
}
/**
* Creates the retained mode BehaviorRetained object that this
* Behavior object will point to.
*/
@Override
void createRetained() {
this.retained = new BehaviorRetained();
this.retained.setSource(this);
}
/**
* Defines this behavior's wakeup criteria. This method
* may only be called from a Behavior object's initialize
* or processStimulus methods to (re)arm the next wakeup.
* It should be the last thing done by those methods.
* @param criteria the wakeup criteria for this behavior
* @exception IllegalStateException if this method is called by
* a method <i>other than</i> initialize or processStimulus
*/
protected void wakeupOn(WakeupCondition criteria) {
BehaviorRetained behavret = (BehaviorRetained) this.retained;
synchronized (behavret) {
if (!behavret.inCallback) {
throw new IllegalStateException(J3dI18N.getString("Behavior0"));
}
}
behavret.wakeupOn(criteria);
}
/**
* Retrieves this behavior's current wakeup condition as set by
* the wakeupOn method. If no wakeup condition is currently
* active, null will be returned. In particular, this means that
* null will be returned if Java 3D is executing this behavior's
* processStimulus routine and wakeupOn has not yet been called to
* re-arm the wakeup condition for next time.
*
* @return the current wakeup condition for this behavior
*
* @since Java 3D 1.3
*/
protected WakeupCondition getWakeupCondition() {
return ((BehaviorRetained)this.retained).getWakeupCondition();
}
/**
* Posts the specified postId to the Behavior Scheduler. All behaviors
* that have registered WakeupOnBehaviorPost with this postId, or a postId
* of 0, and with this behavior, or a null behavior, will have that wakeup
* condition met.
* <p>
* This feature allows applications to send arbitrary events into the
* behavior scheduler stream. It can be used as a notification scheme
* for communicating events to behaviors in the system.
* </p>
* @param postId the Id being posted
*
* @see WakeupOnBehaviorPost
*/
public void postId(int postId){
((BehaviorRetained)this.retained).postId(postId);
}
/**
* Enables or disables this Behavior. The default state is enabled.
* @param state true or false to enable or disable this Behavior
*/
public void setEnable(boolean state) {
((BehaviorRetained)this.retained).setEnable(state);
}
/**
* Retrieves the state of the Behavior enable flag.
* @return the Behavior enable state
*/
public boolean getEnable() {
return ((BehaviorRetained)this.retained).getEnable();
}
/**
* Returns the number of scheduling intervals supported by this
* implementation of Java 3D. The minimum number of supported
* intervals must be at least 10. The default scheduling interval
* for each behavior instance is set to
* <code>numSchedulingIntervals / 2</code>.
*
* @return the number of supported scheduling intervals
*
* @since Java 3D 1.3
*/
public static int getNumSchedulingIntervals() {
return BehaviorRetained.NUM_SCHEDULING_INTERVALS;
}
/**
* Sets the scheduling interval of this Behavior node to the
* specified value.
*
* The scheduling interval defines a partial order of execution
* for behaviors that wake up in response to the same wakeup
* condition (that is, those behaviors that are processed at the
* same "time"). Given a set of behaviors whose wakeup conditions
* are satisfied at the same time, the behavior scheduler will
* execute all behaviors in a lower scheduling interval before
* executing any behavior in a higher scheduling interval. Within
* a scheduling interval, behaviors can be executed in any order,
* or in parallel. Note that this partial ordering is only
* guaranteed for those behaviors that wake up at the same time in
* response to the same wakeup condition, for example, the set of
* behaviors that wake up every frame in response to a
* WakeupOnElapsedFrames(0) wakeup condition.
*
* The default value is <code>numSchedulingIntervals / 2</code>.
*
* @param schedulingInterval the new scheduling interval
*
* @exception IllegalArgumentException if
* <code>schedulingInterval</code> < 0 or
* <code>schedulingInterval</code> >=
* <code>numSchedulingIntervals</code>
*
* @since Java 3D 1.3
*/
public void setSchedulingInterval(int schedulingInterval) {
if (schedulingInterval < 0 ||
schedulingInterval >= getNumSchedulingIntervals()) {
throw new IllegalStateException(J3dI18N.getString("Behavior1"));
}
((BehaviorRetained)this.retained).
setSchedulingInterval(schedulingInterval);
}
/**
* Retrieves the current scheduling interval of this Behavior
* node.
*
* @return the current scheduling interval
*
* @since Java 3D 1.3
*/
public int getSchedulingInterval() {
return ((BehaviorRetained)this.retained).getSchedulingInterval();
}
/**
* Returns the primary view associated with this behavior. This method
* is useful with certain types of behaviors (e.g., Billboard, LOD) that
* rely on per-View information and with behaviors in general in regards
* to scheduling (the distance from the view platform determines the
* active behaviors). The "primary" view is defined to be the first
* View attached to a live ViewPlatform, if there is more than one active
* View. So, for instance, Billboard behaviors would be oriented toward
* this primary view, in the case of multiple active views into the same
* scene graph.
*/
protected View getView() {
return ((BehaviorRetained)this.retained).getView();
}
/**
* Copies all Behavior 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>
*
* @param originalNode 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.
*
* @exception RestrictedAccessException if this object is part of a live
* or compiled scenegraph.
*
* @see Node#duplicateNode
* @see Node#cloneTree
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
super.duplicateAttributes(originalNode, forceDuplicate);
BehaviorRetained attr = (BehaviorRetained) originalNode.retained;
BehaviorRetained rt = (BehaviorRetained) retained;
rt.setEnable(attr.getEnable());
rt.setSchedulingBounds(attr.getSchedulingBounds());
rt.setSchedulingInterval(attr.getSchedulingInterval());
// will set to the correct one in updateNodeReferences
rt.setSchedulingBoundingLeaf(attr.getSchedulingBoundingLeaf());
}
/**
* 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's method
* will be called and the Leaf node 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
*/
@Override
public void updateNodeReferences(NodeReferenceTable referenceTable) {
super.updateNodeReferences(referenceTable);
BehaviorRetained rt = (BehaviorRetained) retained;
BoundingLeaf bl= rt.getSchedulingBoundingLeaf();
// check for schedulingBoundingLeaf
if (bl != null) {
Object o = referenceTable.getNewObjectReference(bl);
rt.setSchedulingBoundingLeaf((BoundingLeaf) o);
}
}
}