void GAFAnimation::resumeAnimation()
{
    if (!m_isRunning)
    {
        setAnimationRunning(true);
    }
}
void GAFObject::resumeAnimation()
{
    if (!m_isRunning)
    {
        setAnimationRunning(true, false);
    }
}
void GAFAnimation::pauseAnimation()
{
    if (m_isRunning)
    {
        setAnimationRunning(false);
    }
}
void GAFObject::pauseAnimation()
{
    if (m_isRunning)
    {
        setAnimationRunning(false, false);
    }
}
void GAFAnimation::stop()
{
    if (m_isRunning)
    {
        _currentFrameIndex = GAF_FIRST_FRAME_INDEX;
        setAnimationRunning(false);
    }
}
void GAFAnimation::start()
{
    if (!m_isRunning)
    {
        _currentFrameIndex = GAF_FIRST_FRAME_INDEX;
        setAnimationRunning(true);
    }
}
bool GAFAnimation::gotoAndPlay(int frameNumber)
{
    if (setFrame(frameNumber))
    {
        setAnimationRunning(true);
        return true;
    }
    return false;
}
void GAFObject::stop()
{
    enableTick(false);
    if (m_isRunning)
    {
        m_currentFrame = GAFFirstFrameIndex;
        setAnimationRunning(false, true);
    }
}
void GAFObject::start()
{
    enableTick(true);

    if (!m_isRunning)
    {
        m_currentFrame = m_isReversed ? m_totalFrameCount - 1 : GAFFirstFrameIndex;
        setAnimationRunning(true, true);
    }
}
void GAFObject::step()
{
    m_showingFrame = m_currentFrame;

    if (!getIsAnimationRunning())
    {
        processAnimation();
        return;
    }

    if (m_sequenceDelegate && m_timeline)
    {
        const GAFAnimationSequence * seq = nullptr;
        if (!m_isReversed)
        {
            seq = m_timeline->getSequenceByLastFrame(m_currentFrame);
        }
        else
        {
            seq = m_timeline->getSequenceByFirstFrame(m_currentFrame + 1);
        }

        if (seq)
        {
            m_sequenceDelegate(this, seq->name);
        }
    }

    if (isCurrentFrameLastInSequence())
    {
        if (m_isLooped)
        {
            if (m_animationStartedNextLoopDelegate)
                m_animationStartedNextLoopDelegate(this);
        }
        else
        {
            setAnimationRunning(false, false);

            if (m_animationFinishedPlayDelegate)
                m_animationFinishedPlayDelegate(this);
        }
    }

    processAnimation();

    m_showingFrame = m_currentFrame;
    m_currentFrame = nextFrame();
}
void GAFAnimation::step()
{
    if (! m_isReversed)
    {
        if (_currentFrameIndex < m_currentSequenceStart)
        {
            _currentFrameIndex = m_currentSequenceStart;
        }

        if (_sequenceDelegate && m_asset)
        {
            const GAFAnimationSequence * seq = m_asset->getSequenceByLastFrame(_currentFrameIndex);
            if (seq)
            {
                _sequenceDelegate->onFinishSequence(dynamic_cast<GAFAnimatedObject*>(this), seq->name);
            }
        }

        if (_currentFrameIndex >= m_currentSequenceEnd)
        {
            if (m_isLooped)
            {
                _currentFrameIndex = m_currentSequenceStart;
                
                if (m_animationPlaybackDelegate)
                {
                    m_animationPlaybackDelegate->onAnimationStartedNextLoopDelegate(this);
                }
            }
            else
            {
                setAnimationRunning(false);

                if (m_animationPlaybackDelegate)
                {
                    m_animationPlaybackDelegate->onAnimationFinishedPlayDelegate(this);
                }

                return;
            }
        }

        processAnimation();

        ++_currentFrameIndex;
    }
    else
    {
        // If switched to reverse after final frame played
        if (_currentFrameIndex >= m_currentSequenceEnd)
        {
            _currentFrameIndex = m_currentSequenceEnd - 1;
        }

        if (_sequenceDelegate && m_asset)
        {
            const GAFAnimationSequence * seq = m_asset->getSequenceByFirstFrame(_currentFrameIndex + 1);
            if (seq)
            {
                _sequenceDelegate->onFinishSequence(dynamic_cast<GAFAnimatedObject*>(this), seq->name);
            }
        }

        if (_currentFrameIndex < m_currentSequenceStart)
        {
            if (m_isLooped)
            {
                _currentFrameIndex = m_currentSequenceEnd - 1;

                if (m_animationPlaybackDelegate)
                {
                    m_animationPlaybackDelegate->onAnimationStartedNextLoopDelegate(this);
                }
            }
            else
            {
                setAnimationRunning(false);

                if (m_animationPlaybackDelegate)
                {
                    m_animationPlaybackDelegate->onAnimationFinishedPlayDelegate(this);
                }

                return;
            }
        }

        processAnimation();

        --_currentFrameIndex;
    }
}