EActiveTimerReturnType UpdateScrollerState(double InCurrentTime, float InDeltaTime)
	{
		if (ScrollerState == EScrollerState::Stop_Wait)
		{
			TimeElapsed = 0.0f;
			ScrollerState = EScrollerState::FadeOff;
			ScrollBox->SetScrollOffset(ScrollOffset);

			auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin();
			if (PinnedActiveTimerHandle.IsValid())
			{
				UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef());
			}
			ActiveTimerHandle = RegisterActiveTimer(0, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState));
		}
		else if (ScrollerState == EScrollerState::Start_Wait)
		{
			TimeElapsed = 0.0f;
			ScrollOffset = 0.0f;
			ScrollerState = EScrollerState::Scrolling;
			ScrollBox->SetScrollOffset(ScrollOffset);

			auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin();
			if (PinnedActiveTimerHandle.IsValid())
			{
				UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef());
			}
			ActiveTimerHandle = RegisterActiveTimer(0, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState));
		}
		return EActiveTimerReturnType::Continue;
	}
FReply SInlineEditableTextBlock::OnMouseButtonDoubleClick( const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent )
{
	auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin();
	if (PinnedActiveTimerHandle.IsValid())
	{
		UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef());
	}
	return FReply::Unhandled();
}
FReply SInlineEditableTextBlock::OnDragOver( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
{
	// Cancel during a drag over event, otherwise the widget may enter edit mode.
	auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin();
	if (PinnedActiveTimerHandle.IsValid())
	{
		UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef());
	}
	return FReply::Unhandled();
}
void SCreditsScreen::HandleUserScrolled(float ScrollOffset)
{
	// If the user scrolls up, and we're currently playing, then stop playing.
	if ( bIsPlaying && ScrollOffset < PreviousScrollPosition )
	{
		bIsPlaying = false;
		if ( ActiveTimerHandle.IsValid() )
		{
			UnRegisterActiveTimer( ActiveTimerHandle.Pin().ToSharedRef() );
		}
	}

	PreviousScrollPosition = ScrollOffset;
}
void SProgressBar::SetActiveTimerTickRate(float TickRate)
{
	if (CurrentTickRate != TickRate || !ActiveTimerHandle.IsValid())
	{
		CurrentTickRate = TickRate;

		TSharedPtr<FActiveTimerHandle> SharedActiveTimerHandle = ActiveTimerHandle.Pin();
		if (SharedActiveTimerHandle.IsValid())
		{
			UnRegisterActiveTimer(SharedActiveTimerHandle.ToSharedRef());
		}

		ActiveTimerHandle = RegisterActiveTimer(TickRate, FWidgetActiveTimerDelegate::CreateSP(this, &SProgressBar::ActiveTick));
	}
}
void SEditorViewport::OnToggleRealtime()
{
	if (Client->IsRealtime())
	{
		Client->SetRealtime( false );
		if ( ActiveTimerHandle.IsValid() )
		{
			UnRegisterActiveTimer( ActiveTimerHandle.Pin().ToSharedRef() );
		}
		
	}
	else
	{
		Client->SetRealtime( true );
		ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SEditorViewport::EnsureTick ) );
	}
}
FReply SCreditsScreen::HandleTogglePlayPause()
{
	if ( bIsPlaying )
	{
		bIsPlaying = false;
		if ( ActiveTimerHandle.IsValid() )
		{
			UnRegisterActiveTimer( ActiveTimerHandle.Pin().ToSharedRef() );
		}
	}
	else
	{
		bIsPlaying = true;
		if ( !ActiveTimerHandle.IsValid() )
		{
			ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SCreditsScreen::RollCredits ) );
		}
	}

	return FReply::Handled();
}
	virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override
	{
		const float ContentSize = ScrollBox->GetDesiredSize().X;
		const float Speed = 20.0f;
		const float StartDelay = 2.0f;
		const float EndDelay = 2.0f;
		const float FadeOnDelay = 0.5f;
		const float FadeOffDelay = 0.5f;

		TimeElapsed += InDeltaTime;

		switch (ScrollerState)
		{
			case EScrollerState::FadeOn:
			{
				FontAlpha = TimeElapsed / FadeOnDelay;
				if (TimeElapsed >= FadeOnDelay)
				{
					FontAlpha = 1.0f;
					TimeElapsed = 0.0f;
					ScrollOffset = 0.0f;
					ScrollerState = EScrollerState::Start;
				}
			}break;
			case EScrollerState::Start:
			{
				// Unregister Tick Delegate
				auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin();
				if (PinnedActiveTimerHandle.IsValid())
				{
					UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef());
				}

				// Check to see if we need to scroll
				if (ExternalScrollbar->DistanceFromBottom() == 0.0f && ExternalScrollbar->DistanceFromTop() == 0.0f)
				{
					// Don't run auto scrolling if text already fits.
					break;
				}
				else
				{
					ActiveTimerHandle = RegisterActiveTimer(StartDelay, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState));
					ScrollerState = EScrollerState::Start_Wait;
				}
			}break;
			case EScrollerState::Start_Wait:
				break;
			case EScrollerState::Scrolling:
			{
				ScrollOffset += Speed * InDeltaTime;
				if (ExternalScrollbar->DistanceFromBottom()==0.0f)
				{
					ScrollOffset = ContentSize;
					TimeElapsed = 0.0f;
					ScrollerState = EScrollerState::Stop;
				}
				
			}break;
			case EScrollerState::Stop:
			{
				// Unregister Tick Delegate
				auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin();
				if (PinnedActiveTimerHandle.IsValid())
				{
					UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef());
				}

				// Check to see if we need to scroll
				if (ExternalScrollbar->DistanceFromBottom() == 0.0f && ExternalScrollbar->DistanceFromTop() == 0.0f)
				{
					// Don't run auto scrolling if text already fits.
					break;
				}
				else
				{
					ActiveTimerHandle = RegisterActiveTimer(EndDelay, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState));
					ScrollerState = EScrollerState::Stop_Wait;
				}
			}break;
			case EScrollerState::Stop_Wait:
				break;
			case EScrollerState::FadeOff:
			{
				FontAlpha = 1.0f - TimeElapsed / FadeOffDelay;
				if (TimeElapsed >= FadeOffDelay)
				{
					FontAlpha = 0.0f;
					TimeElapsed = 0.0f;
					ScrollOffset = 0.0f;
					ScrollerState = EScrollerState::FadeOn;
				}
			}break;
		};
		ScrollBox->SetScrollOffset(ScrollOffset);
	}