//
// AnimationControlJ3D.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad.java3d;

import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.StringTokenizer;

import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.WakeupOnElapsedTime;
import javax.vecmath.Point3d;

import visad.AnimationControl;
import visad.AnimationSetControl;
import visad.Control;
import visad.DataDisplayLink;
import visad.DataRenderer;
import visad.DisplayException;
import visad.RealType;
import visad.Set;
import visad.ToggleControl;
import visad.VisADError;
import visad.VisADException;
import visad.browser.Convert;

/**
   AnimationControlJ3D is the VisAD class for controlling Animation
   display scalars under Java3D.

WLH - manipulate a list of Switch nodes in scene graph.

*/ public class AnimationControlJ3D extends AVControlJ3D implements AnimationControl { private static final long serialVersionUID = 7763197458917167330L; private static final long DEFAULT_DWELL = 500; protected int current = 0;//DML: made protected so subclass can use it. private boolean direction; // true = forward private long step = DEFAULT_DWELL; // time in milliseconds between animation steps private WakeupOnElapsedTime[] stepValues; // times in milliseconds between animation steps private transient AnimationSetControl animationSet; private ToggleControl animate; private RealType real; private boolean computeSet = true; /** Behavior for initiating time stepping. */ private transient Behavior steppingBehaviour; public AnimationControlJ3D(DisplayImplJ3D d, RealType r) { super(d); real = r; current = 0; direction = true; animationSet = new AnimationSetControl(d, this); // initialize the stepValues array stepValues = new WakeupOnElapsedTime[]{ new WakeupOnElapsedTime(DEFAULT_DWELL) }; try { Set set = animationSet.getSet(); if (set != null) stepValues = new WakeupOnElapsedTime[set.getLength()]; } catch (VisADException v) { } for (int i = 0; i < stepValues.length; i++) { stepValues[i] = new WakeupOnElapsedTime(DEFAULT_DWELL); } d.addControl(animationSet); animate = new ToggleControl(d, this); d.addControl(animate); try { animate.setOn(false); } catch (VisADException v) { } catch (RemoteException v) { } // add stepping behavior near the root of the scene graph steppingBehaviour = new TakeStepBehavior(); BranchGroup bg = new BranchGroup(); bg.addChild(steppingBehaviour); DisplayRendererJ3D rend = (DisplayRendererJ3D) d.getDisplayRenderer(); BranchGroup root = rend.getRoot(); root.addChild(bg); } AnimationControlJ3D() { this(null, null); } public int getCurrent() { return current; } /** set the current ordinal step number = c */ public void setCurrent(int c) throws VisADException, RemoteException { if (animationSet != null) { current = animationSet.clipCurrent(c); init(); } else { current = 0; } // WLH 5 May 2000 // changeControl(true); changeControl(false); } /** set the current step by the value of the RealType mapped to Display.Animation */ public void setCurrent(double value) throws VisADException, RemoteException { if (animationSet != null) { current = animationSet.getIndex(value); init(); } else { current = 0; } // WLH 5 May 2000 // changeControl(true); changeControl(false); } /** * Set the animation direction. * * @param dir true for forward, false for backward * * @throws VisADException Couldn't create necessary VisAD object. The * direction remains unchanged. * @throws RemoteException Java RMI exception */ public void setDirection(boolean dir) throws VisADException, RemoteException { direction = dir; // WLH 5 May 2000 // changeControl(true); changeControl(false); } /** Get the animation direction. * * @return true for forward, false for backward */ public boolean getDirection() { return direction; } /** * Return the dwell time for the current step */ public long getStep() { if (stepValues == null || current < 0 || stepValues.length <= current) return DEFAULT_DWELL; else return stepValues[current].getElapsedFrameTime(); } /** * return an array of the dwell times for all the steps. */ public long[] getSteps() { long[] steps = new long[stepValues.length]; for (int i=0; i 0"); } step = st; for (int i=0; i < stepValues.length; i++) { stepValues[i] = new WakeupOnElapsedTime(st); } // WLH 5 May 2000 // changeControl(true); changeControl(false); } /** * set the dwell time for individual steps. * * @param steps an array of dwell rates for each step in the animation * If the length of the array is less than the number of * frames in the animation, the subsequent step values will * be set to the value of the last step. * * @throws VisADException Couldn't create necessary VisAD object. The * dwell times remain unchanged. * @throws RemoteException Java RMI exception */ public void setSteps(int[] steps) throws VisADException, RemoteException { // verify that the values are valid for (int i = 0; i < stepValues.length; i++) { long step = (i < steps.length) ? steps[i] : steps[steps.length-1]; stepValues[i] = new WakeupOnElapsedTime(step); if (step <= 0) throw new DisplayException("AnimationControlJ3D.setSteps: " + "step " + i + " must be > 0"); } // WLH 5 May 2000 // changeControl(true); changeControl(true); } /** * advance one step (forward or backward) * * @throws VisADException Couldn't create necessary VisAD object. No * step is taken. * @throws RemoteException Java RMI exception */ public void takeStep() throws VisADException, RemoteException { if (direction) current++; else current--; if (animationSet != null) { current = animationSet.clipCurrent(current); init(); } getDisplayRenderer().render_trigger(); changeControl(false); } public void init() throws VisADException { if (animationSet != null) { double value = animationSet.getValue(current); Set set = animationSet.getSet(); animation_string(real, set, value, current); selectSwitches(value, set); } } public Set getSet() { if (animationSet != null) { return animationSet.getSet(); } else { return null; } } /** *

Sets the set of times in this animation control. If the argument * set is equal to the current set, then nothing is done.

* * @param s The set of times. * @throws VisADException if a VisAD failure occurs. * @throws RemoteException if a Java RMI failure occurs. */ public void setSet(Set s) throws VisADException, RemoteException { if (s == null && animationSet != null && animationSet.getSet() == null) return; // check for null/null if (animationSet == null || s == null || (s != null && !s.equals(animationSet.getSet()))) { setSet(s, false); // have to do this if animationSet == null if (s == null) { stepValues = new WakeupOnElapsedTime[]{new WakeupOnElapsedTime(DEFAULT_DWELL)}; current = 0; } else if (s.getLength() != stepValues.length) { stepValues = new WakeupOnElapsedTime[s.getLength()]; for (int i = 0; i < stepValues.length; i++) { stepValues[i] = new WakeupOnElapsedTime(step); } } } } /** *

Sets the set of times in this animation control. If the argument * set is equal to the current set, then nothing is done.

* * @param s The set of times. * @param noChange changeControl(!noChange) to not trigger * re-transform, used by ScalarMap.setRange * @throws VisADException if a VisAD failure occurs. * @throws RemoteException if a Java RMI failure occurs. */ public void setSet(Set s, boolean noChange) throws VisADException, RemoteException { if (animationSet != null) { if (s == null) { stepValues = new WakeupOnElapsedTime[]{new WakeupOnElapsedTime(DEFAULT_DWELL)}; current = 0; } else if (s.getLength() != stepValues.length) { stepValues = new WakeupOnElapsedTime[s.getLength()]; for (int i = 0; i < stepValues.length; i++) { stepValues[i] = new WakeupOnElapsedTime(step); } } animationSet.setSet(s, noChange); } } /** return true if automatic stepping is on */ public boolean getOn() { if (animate != null) { return animate.getOn(); } else { return false; } } /** * Set automatic stepping on or off. * * @param o true = turn stepping on, false = turn stepping off * * @throws VisADException Couldn't create necessary VisAD object. No * change in automatic stepping occurs. * @throws RemoteException Java RMI exception */ public void setOn(boolean o) throws VisADException, RemoteException { if (animate != null) { animate.setOn(o); } } /** * toggle automatic stepping between off and on * * @throws VisADException Couldn't create necessary VisAD object. No * change in automatic stepping occurs. * @throws RemoteException Java RMI exception */ public void toggle() throws VisADException, RemoteException { if (animate != null) { animate.setOn(!animate.getOn()); } } public RealType getRealType() { return real; } public void subSetTicks() { if (animationSet != null) { animationSet.setTicks(); } if (animate != null) { animate.setTicks(); } } public boolean subCheckTicks(DataRenderer r, DataDisplayLink link) { boolean flag = false; if (animationSet != null) { flag |= animationSet.checkTicks(r, link); } if (animate != null) { flag |= animate.checkTicks(r, link); } return flag; } public boolean subPeekTicks(DataRenderer r, DataDisplayLink link) { boolean flag = false; if (animationSet != null) { flag |= animationSet.peekTicks(r, link); } if (animate != null) { flag |= animate.peekTicks(r, link); } return flag; } public void subResetTicks() { if (animationSet != null) { animationSet.resetTicks(); } if (animate != null) { animate.resetTicks(); } } /** get a String that can be used to reconstruct this AnimationControl later */ public String getSaveString() { int numSteps; long[] steps; if (stepValues == null) { numSteps = 1; steps = new long[1]; steps[0] = DEFAULT_DWELL; } else { numSteps = stepValues.length; steps = new long[numSteps]; for (int i = 0; i < numSteps; i++) steps[i] = stepValues[i].getElapsedFrameTime(); } StringBuffer sb = new StringBuffer(35 + 12 * numSteps); sb.append(animate != null && animate.getOn()); sb.append(' '); sb.append(direction); sb.append(' '); sb.append(current); sb.append(' '); sb.append(numSteps); for (int i=0; iBehavior
which initiates animation stepping based on * elapsed time. */ private class TakeStepBehavior extends Behavior { public TakeStepBehavior() { setSchedulingBounds(new BoundingSphere(new Point3d(0,0,0), 10000000)); } // initialize dwell when added to universe public void initialize() { updateDwell(); } /** * Unconditionally attempt to take the next step. */ public void processStimulus(Enumeration criteria) { try { if (animate != null && animate.getOn()) { takeStep(); } } catch (VisADException v) { throw new VisADError("Unable to take animation step", v); } catch (RemoteException v) { throw new VisADError("Unable to take animation step", v); } updateDwell(); } /** * Set the wake up criteria for the current step value (dwell). */ public void updateDwell() { // set the wake up criteria with the dwell for the current step if (0 <= current && current < stepValues.length) { wakeupOn(stepValues[current]); } else { wakeupOn(new WakeupOnElapsedTime(DEFAULT_DWELL)); } } } /** * Stop animating. */ @Override public void stop() { steppingBehaviour.setEnable(false); } /** * Start animating. */ @Override public void run() { steppingBehaviour.setEnable(true); } }

Ads help maintain this website.