javax.media.j3d.SwitchValueInterpolator Maven / Gradle / Ivy
/*
* 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.Enumeration;
/**
* SwitchValueInterpolator behavior. This class defines a
* behavior that modifies the selected child of the target
* switch node by linearly interpolating between a pair of
* specified child index values (using the value generated
* by the specified Alpha object).
*/
public class SwitchValueInterpolator extends Interpolator {
Switch target;
int firstSwitchIndex;
int lastSwitchIndex;
int childCount;
// We can't use a boolean flag since it is possible
// that after alpha change, this procedure only run
// once at alpha.finish(). So the best way is to
// detect alpha value change.
private float prevAlphaValue = Float.NaN;
private WakeupCriterion passiveWakeupCriterion = new WakeupOnElapsedFrames(0, true);
// non-public, default constructor used by cloneNode
SwitchValueInterpolator() {
}
/**
* Constructs a SwitchValueInterpolator behavior that varies its target
* Switch node's child index between 0 and n-1, where n
* is the number of children in the target Switch node.
* @param alpha the alpha object for this interpolator
* @param target the Switch node affected by this interpolator
*/
public SwitchValueInterpolator(Alpha alpha,
Switch target) {
super(alpha);
this.target = target;
firstSwitchIndex = 0;
childCount = target.numChildren();
lastSwitchIndex = childCount - 1;
}
/**
* Constructs a SwitchValueInterpolator behavior that varies its target
* Switch node's child index between the two values provided.
* @param alpha the alpha object for this interpolator
* @param target the Switch node affected by this interpolator
* @param firstChildIndex the index of first child in the Switch node to
* select
* @param lastChildIndex the index of last child in the Switch node to
* select
*/
public SwitchValueInterpolator(Alpha alpha,
Switch target,
int firstChildIndex,
int lastChildIndex) {
super(alpha);
this.target = target;
firstSwitchIndex = firstChildIndex;
lastSwitchIndex = lastChildIndex;
computeChildCount();
}
/**
* This method sets the firstChildIndex for this interpolator.
* @param firstIndex the new index for the first child
*/
public void setFirstChildIndex(int firstIndex) {
firstSwitchIndex = firstIndex;
computeChildCount();
}
/**
* This method retrieves this interpolator's firstChildIndex.
* @return the interpolator's firstChildIndex
*/
public int getFirstChildIndex() {
return this.firstSwitchIndex;
}
/**
* This method sets the lastChildIndex for this interpolator.
* @param lastIndex the new index for the last child
*/
public void setLastChildIndex(int lastIndex) {
lastSwitchIndex = lastIndex;
computeChildCount();
}
/**
* This method retrieves this interpolator's lastSwitchIndex.
* @return the interpolator's maximum scale value
*/
public int getLastChildIndex() {
return this.lastSwitchIndex;
}
/**
* This method sets the target for this interpolator.
* @param target the target Switch node
*/
public void setTarget(Switch target) {
this.target = target;
}
/**
* This method retrieves this interpolator's target Switch node
* reference.
* @return the interpolator's target Switch node
*/
public Switch getTarget() {
return target;
}
// The SwitchValueInterpolator's initialize routine uses the default
// initialization routine.
/**
* This method is invoked by the behavior scheduler every frame.
* It maps the alpha value that corresponds to the current time
* into a child index value and updates the specified Switch node
* with this new child index value.
* @param criteria an enumeration of the criteria that triggered
* this stimulus
*/
@Override
public void processStimulus(Enumeration criteria) {
// Handle stimulus
WakeupCriterion criterion = passiveWakeupCriterion;
if (alpha != null) {
float value = alpha.value();
if (value != prevAlphaValue) {
int child;
if (lastSwitchIndex > firstSwitchIndex) {
child = (int)(firstSwitchIndex +
(int)(value * (childCount-1) + 0.49999999999f));
} else {
child = (int)(firstSwitchIndex -
(int)(value * (childCount-1) + 0.49999999999f));
}
target.setWhichChild(child);
prevAlphaValue = value;
}
if (!alpha.finished() && !alpha.isPaused()) {
criterion = defaultWakeupCriterion;
}
}
wakeupOn(criterion);
}
/**
* calculate the number of the child to manage for this switch node
*/
final private void computeChildCount() {
if (lastSwitchIndex >= firstSwitchIndex) {
childCount = lastSwitchIndex - firstSwitchIndex + 1;
} else {
childCount = firstSwitchIndex - lastSwitchIndex + 1;
}
}
/**
* Used to create a new instance of the node. This routine is called
* by cloneTree
to duplicate the current node.
* @param forceDuplicate when set to true
, causes the
* duplicateOnCloneTree
flag to be ignored. When
* false
, the value of each node's
* duplicateOnCloneTree
variable determines whether
* NodeComponent data is duplicated or copied.
*
* @see Node#cloneTree
* @see Node#cloneNode
* @see Node#duplicateNode
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
public Node cloneNode(boolean forceDuplicate) {
SwitchValueInterpolator svi = new SwitchValueInterpolator();
svi.duplicateNode(this, forceDuplicate);
return svi;
}
/**
* Copies all SwitchValueInterpolator information from
* originalNode
into
* the current node. This method is called from the
* cloneNode
method which is, in turn, called by the
* cloneTree
method.
*
* @param originalNode the original node to duplicate.
* @param forceDuplicate when set to true
, causes the
* duplicateOnCloneTree
flag to be ignored. When
* false
, the value of each node's
* duplicateOnCloneTree
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);
SwitchValueInterpolator si =
(SwitchValueInterpolator) originalNode;
setFirstChildIndex(si.getFirstChildIndex());
setLastChildIndex(si.getLastChildIndex());
// this reference will be updated in updateNodeReferences()
setTarget(si.getTarget());
}
/**
* Callback used to allow a node to check if any nodes referenced
* by that node have been duplicated via a call to cloneTree
.
* This method is called by cloneTree
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 node references
* by using the getNewObjectReference
method found in the
* NodeReferenceTable
object. If a match is found, a
* reference to the corresponding Node 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
* node is returned depending on the value of the
* allowDanglingReferences
parameter passed in the
* cloneTree
call.
*
* NOTE: Applications should not call this method directly.
* It should only be called by the cloneTree method.
*
* @param referenceTable a NodeReferenceTableObject that contains the
* getNewObjectReference
method needed to search for
* new object instances.
* @see NodeReferenceTable
* @see Node#cloneTree
* @see DanglingReferenceException
*/
@Override
public void updateNodeReferences(NodeReferenceTable referenceTable) {
super.updateNodeReferences(referenceTable);
// check Switch
Node n = getTarget();
if (n != null) {
setTarget((Switch) referenceTable.getNewObjectReference(n));
}
}
}