/*
* @(#)Interpolator.java 2.0 December 2008-04-28
*
* Copyright (c) 2003-2008 Werner Randelshofer
* Hausmatt 10, Goldau, CH-6405, Switzerland.
* All rights reserved.
*
* The copyright of this software is owned by Werner Randelshofer.
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* Werner Randelshofer. For details see accompanying license terms.
*/
package org.monte.media;
/**
* A linear interpolator for use in conjunction with an Animator object.
*
*
* @author Werner Randelshofer
* @version 2.0 2008-04-28 Current time is currentTimeMillis a parameter.
* <br>1.2 2007-08-26 An interpolator can currentTimeMillis override another
* interpolator.
* <br>1.1 2005-11-02 Notify all, when finished.
* <br>1.0 December 22, 2003 Created.
*/
public abstract class Interpolator {
private float startValue;
private float endValue;
private long startTime;
private long timespan;
private boolean isFinished;
/**
* Creates a new interpolator which interpolates from 0 to 1 within one
* second.
*/
public Interpolator() {
this(0f, 1f);
}
/**
* Creates a new interpolator which interpolates from 0 to 1 within the
* specified timespan.
*/
public Interpolator(long timespan) {
this(0f, 1f, timespan);
}
/**
* Creates a new interpolator which interpolates into the specified
* direction within one second.
*
* @param reverse Set this to true, if you want to interpolate from 1 to 0
* instead of from 0 to 1.
*/
public Interpolator(boolean reverse) {
this((reverse) ? 1f : 0f, (reverse) ? 0f : 1f);
}
/**
* Creates a new interpolator which interpolates from the specified
* start value to the specified end value within one second.
*
* @param startValue A value between 0 and 1.
* @param endValue A value between 0 and 1.
*/
public Interpolator(float startValue, float endValue) {
this(startValue, endValue, 1000);
}
/**
* Creates a new interpolator which interpolates from the specified
* start value to the specified end value within the specified timespan.
*
* @param startValue A value between 0 and 1.
* @param endValue A value between 0 and 1.
* @param timespan A timespan in milliseconds.
*/
public Interpolator(float startValue, float endValue, long timespan) {
this.startValue = startValue;
this.endValue = endValue;
this.timespan = timespan;
}
/**
* Updates the interpolator.
*
* @param fraction An interpolated fraction between 0 and 1.
*/
protected abstract void update(float fraction);
/**
* Computes a fraction from the specified linear fraction.
* In the simplest case, this method returns the linear fraction.
* The returned value must be between 0 and 1.
*
* @param linearFraction The linear fraction between 0 and 1.
* @return A computed fraction between 0 and 1.
*/
protected float getFraction(float linearFraction) {
return linearFraction;
}
/**
* Returns true, if this interpolator replaces
* interpolations by that interpolator.
*/
public boolean replaces(Interpolator that) {
return false;
}
/**
* Initializes the interpolation.
* <p>
* Once this method has been called, method #finish must be called
* before the interpolator can be destroyed.
*
* @param currentTimeMillis
*/
public void initialize(long currentTimeMillis) {
startTime = currentTimeMillis;
update(getFraction(startValue));
}
/**
* Returns true, if the timespan of the Interpolator has elapsed since
* initialize was called.
*
* @param currentTimeMillis The current time.
* @return Returns true, if the time since initialize was called is greater
* or equal the timespan of the interpolator.
*/
public boolean isElapsed(long currentTimeMillis) {
return timespan <= currentTimeMillis - startTime;
}
/**
* Interpolates with the current time millis.
*
* @param currentTimeMillis
*/
public void interpolate(long currentTimeMillis) {
long elapsed = Math.min(timespan, currentTimeMillis - startTime);
float weight = elapsed / (float) timespan;
update(getFraction(startValue * (1 - weight) + endValue * weight));
}
/**
* Finishes the interpolation and calls this.notifyAll() allowing other
* threads to synchronize on isFinished() of the interpolator.
*
* @param currentTimeMillis
*/
public void finish(long currentTimeMillis) {
if (! isFinished) {
update(getFraction(endValue));
isFinished = true;
synchronized(this) {
notifyAll();
}
}
}
public boolean isFinished() {
return isFinished;
}
public boolean isSequential(Interpolator that) {
return false;
}
public void setTimespan(long t) {
this.timespan = t;
}
}