001: package com.xoetrope.swing.animation;
002:
003: import java.awt.Toolkit;
004: import java.util.Vector;
005: import javax.swing.SwingUtilities;
006: import net.xoetrope.xui.helper.ReflectionHelper;
007: import net.xoetrope.xui.helper.XuiUtilities;
008:
009: /**
010: * A thread to control the animation of one or more animation objects.
011: *
012: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
013: * the GNU Public License (GPL), please see license.txt for more details. If
014: * you make commercial use of this software you must purchase a commercial
015: * license from Xoetrope.</p>
016: * <p> $Revision: 1.16 $</p>
017: */
018: public class AnimationThread extends Thread {
019: /**
020: * The objects controller by this thread
021: */
022: protected Vector animationObjects;
023:
024: /**
025: * A self reference
026: */
027: protected XAnimation animationThread;
028:
029: /**
030: * The sleep time in milliseconds
031: */
032: protected long sleepTime;
033:
034: /**
035: * The start time
036: */
037: protected long startTime;
038:
039: /**
040: * The current tick count
041: */
042: protected long tickCount;
043:
044: /**
045: * Flag indication if the animation runs as a continuous loop
046: */
047: protected boolean isLoop;
048:
049: /**
050: * The number of times to play the animation
051: */
052: protected long numLoops;
053:
054: /**
055: * The number of steps in a single animation loop, by default Long.MAX_VALUE steps per cycle
056: */
057: protected long numSteps;
058:
059: /**
060: * The length of the animation loop in milliseconds
061: */
062: protected long loopTime;
063:
064: protected AnimationObject currentAnimationObject;
065:
066: private boolean bUseNanoTime;
067:
068: private static final int MAX_FRAME_SKIPS = 5;
069: private static final int NO_DELAYS_PER_YIELD = 16;
070:
071: /** Creates a new instance of AnimationThread */
072: public AnimationThread() {
073: // animationThread = this;
074: // animationThread.setPriority( Thread.MIN_PRIORITY );
075: // animationObjects = new Vector();
076: // tickCount = 0;
077: // numLoops = 0;
078: // loopTime = 0L;
079: // sleepTime = 100L;
080: // numSteps = Long.MAX_VALUE;
081: //
082: // bUseNanoTime = ( XuiUtilities.getMinorVersion() >= 5 );
083: // }
084: //
085: // /**
086: // * Add an object to the animation series
087: // * @param obj the next object in the series
088: // */
089: // public void addAnimation( AnimationObject obj )
090: // {
091: // animationObjects.add( obj );
092: // }
093: //
094: // /**
095: // * Flag whether or not the thread loops
096: // * @param loop true to play the animation in a loop
097: // */
098: // public void setIsLoop( boolean loop )
099: // {
100: // isLoop = loop;
101: // }
102: //
103: // /**
104: // * How many loops have completed so far
105: // * @return the number of loops
106: // */
107: // public long getNumLoops()
108: // {
109: // return numLoops;
110: // }
111: //
112: // /**
113: // * Set the sleep time between animation steps
114: // * @param st the sleep time in milliseconds
115: // */
116: // public void setSleepTime( long st )
117: // {
118: // sleepTime = st;
119: // }
120: //
121: // /**
122: // * Get the time since the animation was started
123: // * @return the elapsed time in milliseconds
124: // */
125: // public long getElapsedTime()
126: // {
127: // return ( getTime() - startTime ) / 1000000L;
128: // }
129: //
130: // /**
131: // * Get the number of steps executed in the animation
132: // * @return the tick count
133: // */
134: // public long getTickCount()
135: // {
136: // return tickCount;
137: // }
138: //
139: // /**
140: // * Get the step position within the loop on the basis of the number of frames
141: // * rendered
142: // * @return the step number
143: // */
144: // public long getStep()
145: // {
146: // return tickCount % numSteps;
147: // }
148: //
149: // /**
150: // * Get the step position within the loop on the basis of the elapsed time
151: // * @return the step number
152: // */
153: // public long getStepPosition()
154: // {
155: // double tickPosition = 0.5 + ( getElapsedTime() / (double)sleepTime );
156: // return ((long)tickPosition) % numSteps;
157: // }
158: //
159: // /**
160: // * Get the number of steps
161: // * @return the number of steps
162: // */
163: // public long getNumSteps()
164: // {
165: // return numSteps;
166: // }
167: //
168: // /**
169: // * Get the step position within the loop
170: // */
171: // public void setNumSteps( long steps )
172: // {
173: // numSteps = steps;
174: // if ( loopTime > 0L )
175: // setSleepTime( loopTime / steps );
176: // }
177: //
178: // /**
179: // * Get the length of the animation loop
180: // * @return the loop time
181: // */
182: // public long getLoopTime()
183: // {
184: // return loopTime;
185: // }
186: //
187: // /**
188: // * Set the length of the animation loop
189: // * @param time the time in milliseconds
190: // */
191: // public void setLoopTime( long time )
192: // {
193: // loopTime = time;
194: // }
195: //
196: // /**
197: // * Define the animation loop in terms of the loop time and the number of steps
198: // * in the animation (roughly equivalent to the frame rate )
199: // * @param time the loop time in milliseconds
200: // * @param steps the number of steps in the animation.
201: // */
202: // public void setLoop( long time, long steps )
203: // {
204: // loopTime = time;
205: // setNumSteps( steps );
206: // }
207: //
208: // /**
209: // * Do the animation
210: // */
211: // public void run()
212: // {
213: // long beforeTime, afterTime, timeDiff, nextSleepTime;
214: // long overSleepTime = 0L;
215: // int noDelays = 0;
216: // long excess = 0L;
217: // long period = sleepTime * 1000000L;
218: //
219: // beforeTime = getTime();
220: //
221: // Thread me = Thread.currentThread();
222: //
223: // final Runnable doRender = new Runnable()
224: // {
225: // public void run()
226: // {
227: // currentAnimationObject.step( animationThread );
228: // currentAnimationObject.render( animationThread );
229: // Toolkit.getDefaultToolkit().sync();
230: // }
231: // };
232: //
233: // while ( animationThread == me ) {
234: // boolean continueAnimating = false;
235: // for ( int i = 0; i < animationObjects.size(); i++ ) {
236: // currentAnimationObject = (AnimationObject)animationObjects.elementAt( i );
237: // // If the animation hassn't started we need to keep this thread alive till it runs
238: // if ( !currentAnimationObject.isStarted( this ))
239: // continueAnimating = true;
240: // if ( currentAnimationObject.isAnimated( this )) {
241: // try {
242: // SwingUtilities.invokeAndWait( doRender );
243: // }
244: // catch ( Exception e )
245: // {
246: // }
247: // }
248: //
249: // // Only continue render the object if its animation has not finished
250: // if ( !currentAnimationObject.isFinished( this ))
251: // continueAnimating = true;
252: // }
253: // tickCount++;
254: //
255: // // If nothing has been animated or is waiting to be animated finish.
256: // if ( !continueAnimating ) {
257: // if ( isLoop ) {
258: // reset();
259: // numLoops++;
260: // }
261: // else
262: // break;
263: // }
264: //
265: // afterTime = getTime();
266: // timeDiff = afterTime - beforeTime;
267: // nextSleepTime = ( period - timeDiff ) - overSleepTime;
268: // if ( nextSleepTime > 0 ) {
269: // try {
270: // animationThread.sleep( nextSleepTime / 1000000L );
271: // }
272: // catch ( InterruptedException ex ) {}
273: // overSleepTime = ( getTime() - afterTime ) - nextSleepTime;
274: // }
275: // else {
276: // excess -= nextSleepTime;
277: // overSleepTime = 0L;
278: //
279: // if ( ++noDelays > NO_DELAYS_PER_YIELD ) {
280: // animationThread.yield();
281: // noDelays = 0;
282: // }
283: // }
284: // beforeTime = getTime();
285: //
286: // int skips = 0;
287: // while (( excess > period ) && ( skips < MAX_FRAME_SKIPS )) {
288: // excess -= period;
289: // currentAnimationObject.step( animationThread );
290: // skips++;
291: // }
292: // }
293: // animationThread = null;
294: // }
295: //
296: // /**
297: // * Start the animation
298: // */
299: // public void start()
300: // {
301: // startTime = getTime();
302: // tickCount = 0L;
303: // numLoops = 0L;
304: // super.start();
305: // }
306: //
307: // /**
308: // * Has the thread terminated?
309: // * @return true if the thread has terminated, otherwise false
310: // */
311: // public synchronized boolean hasTerminated()
312: // {
313: // return ( animationThread == null );
314: // }
315: //
316: // /**
317: // * Reset the animation to its initial state
318: // */
319: // protected void reset()
320: // {
321: // tickCount = 0;
322: // for ( int i = 0; i < animationObjects.size(); i++ ) {
323: // AnimationObject ao = (AnimationObject)animationObjects.elementAt( i );
324: // ao.reset( this );
325: // }
326: // }
327: //
328: // protected long getTime()
329: // {
330: // if ( !bUseNanoTime )
331: // return System.currentTimeMillis() * 1000000L;
332: // else
333: // return ((Long)ReflectionHelper.getViaReflection( System.class, "nanoTime", null )).longValue();
334: }
335: }
|