void ViewController::playViewTransition()
{
	Eigen::Vector3f target(Eigen::Vector3f::Identity());
	if(mCurrentView) 
		target = mCurrentView->getPosition();

	// no need to animate, we're not going anywhere (probably goToNextGamelist() or goToPrevGamelist() when there's only 1 system)
	if(target == -mCamera.translation() && !isAnimationPlaying(0))
		return;

	if(Settings::getInstance()->getString("TransitionStyle") == "fade")
	{
		// fade
		// stop whatever's currently playing, leaving mFadeOpacity wherever it is
		cancelAnimation(0);

		auto fadeFunc = [this](float t) {
			mFadeOpacity = lerp<float>(0, 1, t);
		};

		const static int FADE_DURATION = 240; // fade in/out time
		const static int FADE_WAIT = 320; // time to wait between in/out
		setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), 0, [this, fadeFunc, target] {
			this->mCamera.translation() = -target;
			updateHelpPrompts();
			setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), FADE_WAIT, nullptr, true);
		});

		// fast-forward animation if we're partway faded
		if(target == -mCamera.translation())
		{
			// not changing screens, so cancel the first half entirely
			advanceAnimation(0, FADE_DURATION);
			advanceAnimation(0, FADE_WAIT);
			advanceAnimation(0, FADE_DURATION - (int)(mFadeOpacity * FADE_DURATION));
		}else{
			advanceAnimation(0, (int)(mFadeOpacity * FADE_DURATION));
		}
	}else{
		// slide
		setAnimation(new MoveCameraAnimation(mCamera, target));
		updateHelpPrompts(); // update help prompts immediately
	}
}
void AnimationViewerPanel::refresh()
{
    if (!isAnimationPlaying() || isAnimationExist())
    {
        refreshed = true;
        clearSprites();
    }

    if (!isAnimationPlaying())
    {
        float targetX = mpAnimationModel->getTargetSprite()->mSpriteDescriptor.mPosition.mX;
        float targetY = mpAnimationModel->getTargetSprite()->mSpriteDescriptor.mPosition.mY;

        QPoint centerPoint = getCenterPoint();

        if (targetX < -centerPoint.x()){targetX = -centerPoint.x();}
        if (targetX > centerPoint.x()){targetX = centerPoint.x();}
        if (targetY < -centerPoint.y()){targetY = -centerPoint.y();}
        if (targetY > centerPoint.y()){targetY = centerPoint.y();}

        mpAnimationModel->setTargetSpritePosition(targetX, targetY);

        // set cel reference
        KeyFrame::KeyFramePosition keyframePosition = mpAnimationModel->getCurrentKeyFramePosition();
        KeyFrame* pKeyframe = mpAnimationModel->getKeyFrame(keyframePosition.mLineNo, keyframePosition.mFrameNo);

        if (pKeyframe)
        {
            mpSelectedCelModel->setKeyFrameDataReference(pKeyframe->mpKeyFrameData);
            emit celSelected(pKeyframe->mpKeyFrameData);
        }
        else
        {
            mpSelectedCelModel->setKeyFrameDataReference(NULL);
            emit celSelected(NULL);
        }
    }

     // Update target info
    GLSprite* pTargetMonsterSprite = mpAnimationModel->createGLSpriteAt(NULL, mpAnimationModel->getCurrentKeyFramePosition().mFrameNo, AnimationModel::LINE_target);
    if (pTargetMonsterSprite)
    {
        if (pTargetMonsterSprite->mLineNo == AnimationModel::LINE_target)
        {
            GLSprite::Point2 pt = spTargetSprite->mSpriteDescriptor.mPosition;
            pt.mX = pTargetMonsterSprite->mSpriteDescriptor.mPosition.mX + AnimationModel::TARGET_originX;
            pt.mY = pTargetMonsterSprite->mSpriteDescriptor.mPosition.mY + AnimationModel::TARGET_originY;
            spTargetSprite->mSpriteDescriptor.mPosition = pt;
            //spTargetSprite->mSpriteDescriptor.mTextureSrcRect = pTargetMonsterSprite->mSpriteDescriptor.mTextureSrcRect;
            spTargetSprite->mSpriteDescriptor.mCenter.mX = 0;
            spTargetSprite->mSpriteDescriptor.mCenter.mY = 0;
        }
        delete pTargetMonsterSprite;
    }

    mGlSpriteList = mpAnimationModel->createGLSpriteListAt(NULL, mpAnimationModel->getCurrentKeyFramePosition().mFrameNo);

    mRenderSpriteList.append(mGlSpriteList);
    for (int lineNo = 0; lineNo < AnimationModel::LINE_COUNT; lineNo++)
    {
        for (int i = mEmittedAnimationList[lineNo].count() - 1; i >= 0; i--)
        {
            mRenderSpriteList.push_back(mEmittedAnimationList[lineNo][i]->getSprite());
        }
    }
    qSort(mRenderSpriteList.begin(), mRenderSpriteList.end(), GLSprite::priorityLessThan);

    repaint();
}