package org.andengine.util.modifier; import org.andengine.util.modifier.IModifier.IModifierListener; import org.andengine.util.modifier.util.ModifierUtils; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * @since 19:39:25 - 19.03.2010 */ public class SequenceModifier<T> extends BaseModifier<T> implements IModifierListener<T> { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== private ISubSequenceModifierListener<T> mSubSequenceModifierListener; private final IModifier<T>[] mSubSequenceModifiers; private int mCurrentSubSequenceModifierIndex; private float mSecondsElapsed; private final float mDuration; private boolean mFinishedCached; // =========================================================== // Constructors // =========================================================== public SequenceModifier(final IModifier<T> ... pModifiers) throws IllegalArgumentException { this(null, null, pModifiers); } public SequenceModifier(final ISubSequenceModifierListener<T> pSubSequenceModifierListener, final IModifier<T> ... pModifiers) throws IllegalArgumentException { this(pSubSequenceModifierListener, null, pModifiers); } public SequenceModifier(final IModifierListener<T> pModifierListener, final IModifier<T> ... pModifiers) throws IllegalArgumentException { this(null, pModifierListener, pModifiers); } public SequenceModifier(final ISubSequenceModifierListener<T> pSubSequenceModifierListener, final IModifierListener<T> pModifierListener, final IModifier<T> ... pModifiers) throws IllegalArgumentException { super(pModifierListener); if(pModifiers.length == 0) { throw new IllegalArgumentException("pModifiers must not be empty!"); } BaseModifier.assertNoNullModifier(pModifiers); this.mSubSequenceModifierListener = pSubSequenceModifierListener; this.mSubSequenceModifiers = pModifiers; this.mDuration = ModifierUtils.getSequenceDurationOfModifier(pModifiers); pModifiers[0].addModifierListener(this); } @SuppressWarnings("unchecked") protected SequenceModifier(final SequenceModifier<T> pSequenceModifier) throws DeepCopyNotSupportedException { this.mDuration = pSequenceModifier.mDuration; final IModifier<T>[] otherModifiers = pSequenceModifier.mSubSequenceModifiers; this.mSubSequenceModifiers = new IModifier[otherModifiers.length]; final IModifier<T>[] subSequenceModifiers = this.mSubSequenceModifiers; for(int i = subSequenceModifiers.length - 1; i >= 0; i--) { subSequenceModifiers[i] = otherModifiers[i].deepCopy(); } subSequenceModifiers[0].addModifierListener(this); } @Override public SequenceModifier<T> deepCopy() throws DeepCopyNotSupportedException{ return new SequenceModifier<T>(this); } // =========================================================== // Getter & Setter // =========================================================== public ISubSequenceModifierListener<T> getSubSequenceModifierListener() { return this.mSubSequenceModifierListener; } public void setSubSequenceModifierListener(final ISubSequenceModifierListener<T> pSubSequenceModifierListener) { this.mSubSequenceModifierListener = pSubSequenceModifierListener; } // =========================================================== // 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.mSubSequenceModifiers[this.mCurrentSubSequenceModifierIndex].onUpdate(secondsElapsedRemaining, pItem); } this.mFinishedCached = false; final float secondsElapsedUsed = pSecondsElapsed - secondsElapsedRemaining; this.mSecondsElapsed += secondsElapsedUsed; return secondsElapsedUsed; } } @Override public void reset() { if(this.isFinished()) { this.mSubSequenceModifiers[this.mSubSequenceModifiers.length - 1].removeModifierListener(this); } else { this.mSubSequenceModifiers[this.mCurrentSubSequenceModifierIndex].removeModifierListener(this); } this.mCurrentSubSequenceModifierIndex = 0; this.mFinished = false; this.mSecondsElapsed = 0; this.mSubSequenceModifiers[0].addModifierListener(this); final IModifier<T>[] subSequenceModifiers = this.mSubSequenceModifiers; for(int i = subSequenceModifiers.length - 1; i >= 0; i--) { subSequenceModifiers[i].reset(); } } @Override public void onModifierStarted(final IModifier<T> pModifier, final T pItem) { if(this.mCurrentSubSequenceModifierIndex == 0) { this.onModifierStarted(pItem); } if(this.mSubSequenceModifierListener != null) { this.mSubSequenceModifierListener.onSubSequenceStarted(pModifier, pItem, this.mCurrentSubSequenceModifierIndex); } } @Override public void onModifierFinished(final IModifier<T> pModifier, final T pItem) { if(this.mSubSequenceModifierListener != null) { this.mSubSequenceModifierListener.onSubSequenceFinished(pModifier, pItem, this.mCurrentSubSequenceModifierIndex); } pModifier.removeModifierListener(this); this.mCurrentSubSequenceModifierIndex++; if(this.mCurrentSubSequenceModifierIndex < this.mSubSequenceModifiers.length) { final IModifier<T> nextSubSequenceModifier = this.mSubSequenceModifiers[this.mCurrentSubSequenceModifierIndex]; nextSubSequenceModifier.addModifierListener(this); } else { this.mFinished = true; this.mFinishedCached = true; this.onModifierFinished(pItem); } } // =========================================================== // Methods // =========================================================== // =========================================================== // Inner and Anonymous Classes // =========================================================== public interface ISubSequenceModifierListener<T> { public void onSubSequenceStarted(final IModifier<T> pModifier, final T pItem, final int pIndex); public void onSubSequenceFinished(final IModifier<T> pModifier, final T pItem, final int pIndex); } }