int32 FFaceFXAnimationSection::OnPaintSection(FSequencerSectionPainter& Painter) const
{
	const ESlateDrawEffect::Type DrawEffects = Painter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;

	UFaceFXAnimationSection* AnimSection = CastChecked<UFaceFXAnimationSection>(&Section);
	const float AnimSectionDuration = AnimSection->GetAnimationDuration();

	const FTimeToPixel& TimeToPixelConverter = Painter.GetTimeConverter();

	int32 LayerId = Painter.PaintSectionBackground();

	// Add lines where the animation starts and ends/loops
	float CurrentTime = AnimSection->GetStartTime();
	const float AnimLength = AnimSectionDuration - AnimSection->GetStartOffset() + AnimSection->GetEndOffset();
	while (CurrentTime < AnimSection->GetEndTime() && !FMath::IsNearlyZero(AnimSectionDuration) && AnimLength > 0)
	{
		if (CurrentTime > AnimSection->GetStartTime())
		{
			const float CurrentPixels = TimeToPixelConverter.TimeToPixel(CurrentTime);

			TArray<FVector2D> Points;
			Points.Add(FVector2D(CurrentPixels, 0));
			Points.Add(FVector2D(CurrentPixels, Painter.SectionGeometry.Size.Y));

			FSlateDrawElement::MakeLines(Painter.DrawElements, ++LayerId, Painter.SectionGeometry.ToPaintGeometry(), Points, Painter.SectionClippingRect, DrawEffects);
		}
		CurrentTime += AnimLength;
	}
	return LayerId;
}
int32 FFaceFXAnimationSection::OnPaintSection(FSequencerSectionPainter& Painter) const
{
	const UFaceFXAnimationSection* AnimSection = CastChecked<UFaceFXAnimationSection>(&Section);
	int32 LayerId = Painter.PaintSectionBackground();

	if (!AnimSection->HasStartFrame())
	{
		return LayerId;
	}

	const UFaceFXAnimationTrack* AnimTrack = AnimSection->GetTrack();
	if (!AnimTrack)
	{
		return LayerId;
	}

	const UMovieScene* TrackMovieScene = AnimTrack->GetTypedOuter<UMovieScene>();
	if (!TrackMovieScene)
	{
		return LayerId;
	}

	const ESlateDrawEffect DrawEffects = Painter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;
	const float AnimSectionDuration = AnimSection->GetAnimationDurationInSeconds();

	const FTimeToPixel& TimeToPixelConverter = Painter.GetTimeConverter();

	// Add lines where the animation starts and ends/loops
	const FFrameNumber StartFrame = AnimSection->GetInclusiveStartFrame();
	const FFrameNumber EndFrame = AnimSection->HasEndFrame() ? AnimSection->GetExclusiveEndFrame() : FFrameNumber(TNumericLimits<FFrameNumber>::Max());

	//get the animation length in frames
	const FFrameRate FrameResolution = TrackMovieScene->GetTickResolution();
	const float AnimLength = AnimSectionDuration - AnimSection->GetStartOffset() + AnimSection->GetEndOffset();
	const FFrameNumber AnimLengthFrames = FrameResolution.AsFrameNumber(AnimLength);

	//go over all full loops of the animation and draw the markers between each of them
	FFrameNumber CurrentFrame = StartFrame;
	while (CurrentFrame < EndFrame && !FMath::IsNearlyZero(AnimSectionDuration) && AnimLength > 0)
	{
		if (CurrentFrame > StartFrame)
		{
			const float CurrentPixels = TimeToPixelConverter.FrameToPixel(CurrentFrame);

			TArray<FVector2D> Points;
			Points.Add(FVector2D(CurrentPixels, 0));
			Points.Add(FVector2D(CurrentPixels, Painter.SectionGeometry.Size.Y));

			FSlateDrawElement::MakeLines(Painter.DrawElements, ++LayerId, Painter.SectionGeometry.ToPaintGeometry(), Points, DrawEffects);
		}
		CurrentFrame += AnimLengthFrames;
	}
	return LayerId;
}
int32 FCinematicShotSection::OnPaintSection(FSequencerSectionPainter& InPainter) const
{
	static const FSlateBrush* FilmBorder = FEditorStyle::GetBrush("Sequencer.Section.FilmBorder");

	InPainter.LayerId = InPainter.PaintSectionBackground();

	FVector2D SectionSize = InPainter.SectionGeometry.GetLocalSize();

	FSlateDrawElement::MakeBox(
		InPainter.DrawElements,
		InPainter.LayerId++,
		InPainter.SectionGeometry.ToPaintGeometry(FVector2D(SectionSize.X-2.f, 7.f), FSlateLayoutTransform(FVector2D(1.f, 4.f))),
		FilmBorder,
		InPainter.SectionClippingRect.InsetBy(FMargin(1.f)),
		InPainter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect
	);

	FSlateDrawElement::MakeBox(
		InPainter.DrawElements,
		InPainter.LayerId++,
		InPainter.SectionGeometry.ToPaintGeometry(FVector2D(SectionSize.X-2.f, 7.f), FSlateLayoutTransform(FVector2D(1.f, SectionSize.Y - 11.f))),
		FilmBorder,
		InPainter.SectionClippingRect.InsetBy(FMargin(1.f)),
		InPainter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect
	);

	if (SequenceInstance.IsValid())
	{
		return FThumbnailSection::OnPaintSection(InPainter);
	}

	return InPainter.LayerId;
}
	virtual int32 OnPaintSection( FSequencerSectionPainter& InPainter ) const override 
	{
		return InPainter.PaintSectionBackground();
	}
int32 FEventTrackSection::OnPaintSection( FSequencerSectionPainter& InPainter ) const
{
	return InPainter.PaintSectionBackground();
}
int32 FParticleSection::OnPaintSection( FSequencerSectionPainter& InPainter ) const
{
	TSharedPtr<ISequencer> OwningSequencer = OwningSequencerPtr.Pin();

	if (!OwningSequencer.IsValid())
	{
		return InPainter.LayerId + 1;
	}

	const ESlateDrawEffect::Type DrawEffects = InPainter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;
	UMovieSceneParticleSection* AnimSection = Cast<UMovieSceneParticleSection>( &Section );
	const FTimeToPixel& TimeToPixelConverter = InPainter.GetTimeConverter();

	FLinearColor TrackColor;

	// @todo Sequencer - These values should be cached and then refreshed only when the particle system changes.
	bool bIsLooping = false;
	float LastEmitterEndTime = 0;
	UMovieSceneParticleSection* ParticleSection = Cast<UMovieSceneParticleSection>( &Section );
	if ( ParticleSection != nullptr )
	{
		UMovieSceneParticleTrack* ParentTrack = Cast<UMovieSceneParticleTrack>( ParticleSection->GetOuter() );
		if ( ParentTrack != nullptr )
		{
			TrackColor = ParentTrack->GetColorTint();

			FGuid ObjectHandle;
			for ( const FMovieSceneBinding& Binding : OwningSequencer->GetFocusedMovieSceneSequence()->GetMovieScene()->GetBindings() )
			{
				if ( Binding.GetTracks().Contains( ParentTrack ) )
				{
					ObjectHandle = Binding.GetObjectGuid();
					break;
				}
			}

			if ( ObjectHandle.IsValid() )
			{
				UObject* BoundObject = OwningSequencer->GetFocusedMovieSceneSequenceInstance()->FindObject( ObjectHandle, *OwningSequencer );
				UParticleSystemComponent* ParticleSystemComponent = Cast<UParticleSystemComponent>(BoundObject);
				if(AEmitter* ParticleSystemActor = Cast<AEmitter>(BoundObject))
				{
					ParticleSystemComponent = ParticleSystemActor->GetParticleSystemComponent();
				}

				if ( ParticleSystemComponent != nullptr && ParticleSystemComponent->Template != nullptr )
				{
					for ( UParticleEmitter* Emitter : ParticleSystemComponent->Template->Emitters )
					{
						UParticleModuleRequired* RequiredModule = Emitter->GetLODLevel( 0 )->RequiredModule;
						bIsLooping |= RequiredModule->EmitterLoops == 0;
						LastEmitterEndTime = FMath::Max( LastEmitterEndTime, RequiredModule->EmitterDelay + RequiredModule->EmitterDuration );
					}
				}
			}
		}
	}

	// @todo Sequencer - This should only draw the visible ranges.
	TArray<TRange<float>> DrawRanges;
	TOptional<float> CurrentRangeStart;
	for ( auto KeyIterator = ParticleSection->GetParticleCurve().GetKeyIterator(); KeyIterator; ++KeyIterator )
	{
		FIntegralKey Key = *KeyIterator;
		if ( (EParticleKey::Type)Key.Value == EParticleKey::Activate )
		{
			if ( CurrentRangeStart.IsSet() == false )
			{
				CurrentRangeStart = Key.Time;
			}
			else
			{
				if ( bIsLooping == false )
				{
					if ( Key.Time > CurrentRangeStart.GetValue() + LastEmitterEndTime )
					{
						DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), CurrentRangeStart.GetValue() + LastEmitterEndTime ) );
					}
					else
					{
						DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), Key.Time ) );
					}
					CurrentRangeStart = Key.Time;
				}
			}
		}
		if ( (EParticleKey::Type)Key.Value == EParticleKey::Deactivate )
		{
			if ( CurrentRangeStart.IsSet() )
			{
				if (bIsLooping)
				{
					DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), Key.Time ) );
				}
				else
				{
					if ( Key.Time > CurrentRangeStart.GetValue() + LastEmitterEndTime )
					{
						DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), CurrentRangeStart.GetValue() + LastEmitterEndTime ) );
					}
					else
					{
						DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), Key.Time ) );
					}
				}
				CurrentRangeStart.Reset();
			}
		}
	}
	if ( CurrentRangeStart.IsSet() )
	{
		if ( bIsLooping )
		{
			DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), OwningSequencer->GetViewRange().GetUpperBoundValue() ) );
		}
		else
		{
			DrawRanges.Add( TRange<float>( CurrentRangeStart.GetValue(), CurrentRangeStart.GetValue() + LastEmitterEndTime ) );
		}
	}

	for ( const TRange<float>& DrawRange : DrawRanges )
	{
		float XOffset = TimeToPixelConverter.TimeToPixel(DrawRange.GetLowerBoundValue());
		float XSize = TimeToPixelConverter.TimeToPixel(DrawRange.GetUpperBoundValue()) - XOffset;
		FSlateDrawElement::MakeBox(
			InPainter.DrawElements,
			InPainter.LayerId,
			InPainter.SectionGeometry.ToPaintGeometry( FVector2D( XOffset, (InPainter.SectionGeometry.GetLocalSize().Y - SequencerSectionConstants::KeySize.Y) / 2 ), FVector2D( XSize, SequencerSectionConstants::KeySize.Y ) ),
			FEditorStyle::GetBrush( "Sequencer.Section.Background" ),
			InPainter.SectionClippingRect,
			DrawEffects
			);
		FSlateDrawElement::MakeBox(
			InPainter.DrawElements,
			InPainter.LayerId,
			InPainter.SectionGeometry.ToPaintGeometry( FVector2D( XOffset, (InPainter.SectionGeometry.GetLocalSize().Y - SequencerSectionConstants::KeySize.Y) / 2 ), FVector2D( XSize, SequencerSectionConstants::KeySize.Y ) ),
			FEditorStyle::GetBrush( "Sequencer.Section.BackgroundTint" ),
			InPainter.SectionClippingRect,
			DrawEffects,
			TrackColor
			);
	}

	return InPainter.LayerId+1;
}