package org.andengine.util.modifier;
import org.andengine.util.modifier.IModifier.IModifierListener;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 11:18:37 - 03.09.2010
* @param <T>
*/
public class LoopModifier<T> extends BaseModifier<T> implements IModifierListener<T> {
// ===========================================================
// Constants
// ===========================================================
public static final int LOOP_CONTINUOUS = -1;
// ===========================================================
// Fields
// ===========================================================
private float mSecondsElapsed;
private final float mDuration;
private final IModifier<T> mModifier;
private ILoopModifierListener<T> mLoopModifierListener;
private final int mLoopCount;
private int mLoop;
private boolean mModifierStartedCalled;
private boolean mFinishedCached;
// ===========================================================
// Constructors
// ===========================================================
public LoopModifier(final IModifier<T> pModifier) {
this(pModifier, LoopModifier.LOOP_CONTINUOUS);
}
public LoopModifier(final IModifier<T> pModifier, final int pLoopCount) {
this(pModifier, pLoopCount, null, (IModifierListener<T>)null);
}
public LoopModifier(final IModifier<T> pModifier, final int pLoopCount, final IModifierListener<T> pModifierListener) {
this(pModifier, pLoopCount, null, pModifierListener);
}
public LoopModifier(final IModifier<T> pModifier, final int pLoopCount, final ILoopModifierListener<T> pLoopModifierListener) {
this(pModifier, pLoopCount, pLoopModifierListener, (IModifierListener<T>)null);
}
public LoopModifier(final IModifier<T> pModifier, final int pLoopCount, final ILoopModifierListener<T> pLoopModifierListener, final IModifierListener<T> pModifierListener) {
super(pModifierListener);
BaseModifier.assertNoNullModifier(pModifier);
this.mModifier = pModifier;
this.mLoopCount = pLoopCount;
this.mLoopModifierListener = pLoopModifierListener;
this.mLoop = 0;
this.mDuration = (pLoopCount == LoopModifier.LOOP_CONTINUOUS) ? Float.POSITIVE_INFINITY : pModifier.getDuration() * pLoopCount; // TODO Check if POSITIVE_INFINITY works correct with i.e. SequenceModifier
this.mModifier.addModifierListener(this);
}
protected LoopModifier(final LoopModifier<T> pLoopModifier) throws DeepCopyNotSupportedException {
this(pLoopModifier.mModifier.deepCopy(), pLoopModifier.mLoopCount);
}
@Override
public LoopModifier<T> deepCopy() throws DeepCopyNotSupportedException {
return new LoopModifier<T>(this);
}
// ===========================================================
// Getter & Setter
// ===========================================================
public ILoopModifierListener<T> getLoopModifierListener() {
return this.mLoopModifierListener;
}
public void setLoopModifierListener(final ILoopModifierListener<T> pLoopModifierListener) {
this.mLoopModifierListener = pLoopModifierListener;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public float getSecondsElapsed() {
return this.mSecondsElapsed;
}
@Override
public float getDuration() {
return this.mDuration;
}
@Override
public float onUpdate(final float pSecondsElapsed, final T pItem) {
if(this.mFinished){
return 0;
} else {
float secondsElapsedRemaining = pSecondsElapsed;
this.mFinishedCached = false;
while((secondsElapsedRemaining > 0) && !this.mFinishedCached) {
secondsElapsedRemaining -= this.mModifier.onUpdate(secondsElapsedRemaining, pItem);
}
this.mFinishedCached = false;
final float secondsElapsedUsed = pSecondsElapsed - secondsElapsedRemaining;
this.mSecondsElapsed += secondsElapsedUsed;
return secondsElapsedUsed;
}
}
@Override
public void reset() {
this.mFinished = false;
this.mLoop = 0;
this.mSecondsElapsed = 0;
this.mModifierStartedCalled = false;
this.mModifier.reset();
}
// ===========================================================
// Methods
// ===========================================================
@Override
public void onModifierStarted(final IModifier<T> pModifier, final T pItem) {
if(!this.mModifierStartedCalled) {
this.mModifierStartedCalled = true;
this.onModifierStarted(pItem);
}
if(this.mLoopModifierListener != null) {
this.mLoopModifierListener.onLoopStarted(this, this.mLoop, this.mLoopCount);
}
}
@Override
public void onModifierFinished(final IModifier<T> pModifier, final T pItem) {
if(this.mLoopModifierListener != null) {
this.mLoopModifierListener.onLoopFinished(this, this.mLoop, this.mLoopCount);
}
if(this.mLoopCount == LoopModifier.LOOP_CONTINUOUS) {
this.mSecondsElapsed = 0;
this.mModifier.reset();
} else {
this.mLoop++;
if(this.mLoop >= this.mLoopCount) {
this.mFinished = true;
this.mFinishedCached = true;
this.onModifierFinished(pItem);
} else {
this.mSecondsElapsed = 0;
this.mModifier.reset();
}
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public interface ILoopModifierListener<T> {
public void onLoopStarted(final LoopModifier<T> pLoopModifier, final int pLoop, final int pLoopCount);
public void onLoopFinished(final LoopModifier<T> pLoopModifier, final int pLoop, final int pLoopCount);
}
}