facebookarchive / Keyframes

A library for converting Adobe AE shape based animations to a data format and playing it back on Android and iOS devices.
https://facebookincubator.github.io/Keyframes/
Other
5.33k stars 302 forks source link

[Android] Animation Pasue -> resume, sometimes not matched frame #71

Open pinkred opened 7 years ago

pinkred commented 7 years ago

Hello. master github added animation pause, resume. thank you.

I'm happy. because I coded this feature. so my code delete and merge master. but has a problem. long time pause -> resume frame not matched.

thank you.

I added screen video. device-2016-12-16-151249.mp4.zip

pinkred commented 7 years ago

I fixed it.

  private long mPausedCalibrateMillis;
  private long mSavedCalibrateMillis;

  public void start() {
    mStopAtLoopEnd = false;
    mStartTimeMillis = 0;
    mPausedCalibrateMillis = 0;
    mSavedCalibrateMillis = 0;
    mCurrentLoopNumber = -1;
    cancelCallback();
    postCallback();
  }

  public void playOnce() {
    mStopAtLoopEnd = true;
    mStartTimeMillis = 0;
    mCurrentLoopNumber = 0;
    mPausedCalibrateMillis = 0;
    mSavedCalibrateMillis = 0;
    cancelCallback();
    postCallback();
  }

  public void stop() {
    cancelCallback();
    mStartTimeMillis = 0;
    mPausedCalibrateMillis = 0;
    mSavedCalibrateMillis = 0;
    mCurrentLoopNumber = -1;
    mListener.get().onStop();
  }

  public void pause() {
    if(mStartTimeMillis < 0)
    {
      return;
    }

    cancelCallback();
    mStartTimeMillis *= -1;
  }

  public void resume() {
    if(mStartTimeMillis >= 0)
    {
      return;
    }

    mPausedCalibrateMillis = mPreviousProgressMillis;
    mStopAtLoopEnd = false;
    cancelCallback();
    postCallback();
  }

protected void advanceAnimation(long frameTimeMillis) {
    long currentTimeMillis = frameTimeMillis;

    if(mPausedCalibrateMillis != 0)
    {
      if(mStartTimeMillis < 0)
      {
        frameTimeMillis = mPausedCalibrateMillis;
        mSavedCalibrateMillis = currentTimeMillis;
        mStartTimeMillis *= -1;
      } else
      {
        frameTimeMillis = mPausedCalibrateMillis + (frameTimeMillis - mSavedCalibrateMillis);
      }
    }

    if (mListener.get() == null) {
      cancelCallback();
      mStartTimeMillis = 0;
      mPreviousProgressMillis = 0;
      mCurrentLoopNumber = -1;
      return;
    }
    if (mStartTimeMillis == 0) {
      mStartTimeMillis = frameTimeMillis;
    }

    int currentLoopNumber = (int) (frameTimeMillis - mStartTimeMillis) / mMillisPerLoop;
    final boolean loopHasEnded = currentLoopNumber > mCurrentLoopNumber;
    if (mStopAtLoopEnd && loopHasEnded) {
      mListener.get().onProgressUpdate(mFrameCount);
      stop();
      return;
    }
    long currentProgressMillis = (frameTimeMillis - mStartTimeMillis) % mMillisPerLoop;

    boolean shouldUpdateProgress = true;
    if (frameTimeMillis - mPreviousProgressMillis < mMinimumMillisBetweenProgressUpdates) {
      shouldUpdateProgress = false;
    } else {
      mPreviousProgressMillis = frameTimeMillis;

      if(mPausedCalibrateMillis != 0)
      {
        mPausedCalibrateMillis = mPreviousProgressMillis;
        mSavedCalibrateMillis = currentTimeMillis;
      }
    }

    if (shouldUpdateProgress) {
      mListener.get().onProgressUpdate((float) currentProgressMillis / mMillisPerLoop * mFrameCount);
    }
    mCurrentLoopNumber = (int) (frameTimeMillis - mStartTimeMillis) / mMillisPerLoop;
    postCallback();
  }