/* * @(#)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; } }