TOptional<FSectionHandle> FVirtualTrackArea::HitTestSection(FVector2D InPhysicalPosition) const
{
	TSharedPtr<FSequencerDisplayNode> Node = HitTestNode(InPhysicalPosition.Y);

	if (Node.IsValid())
	{
		TSharedPtr<FSequencerTrackNode> TrackNode = GetParentTrackNode(*Node);

		if (TrackNode.IsValid())
		{
			float Time = PixelToTime(InPhysicalPosition.X);

			const auto& Sections = TrackNode->GetSections();
			for (int32 Index = 0; Index < Sections.Num(); ++Index)
			{
				UMovieSceneSection* Section = Sections[Index]->GetSectionObject();
				if (Section->IsTimeWithinSection(Time))
				{
					return FSectionHandle(TrackNode.ToSharedRef(), Index);
				}
			}
		}
	}

	return TOptional<FSectionHandle>();
}
예제 #2
0
UMovieSceneSection* UMovieSceneAnimationTrack::GetAnimSectionAtTime(float Time)
{
	for (int32 i = 0; i < AnimationSections.Num(); ++i)
	{
		UMovieSceneSection* Section = AnimationSections[i];
		if( Section->IsTimeWithinSection( Time ) )
		{
			return Section;
		}
	}

	return NULL;
}
UMovieSceneSection* MovieSceneHelpers::FindSectionAtTime( const TArray<UMovieSceneSection*>& Sections, float Time )
{
	for( int32 SectionIndex = 0; SectionIndex < Sections.Num(); ++SectionIndex )
	{
		UMovieSceneSection* Section = Sections[SectionIndex];

		//@todo Sequencer - There can be multiple sections overlapping in time. Returning instantly does not account for that.
		if( Section->IsTimeWithinSection( Time ) && Section->IsActive() )
		{
			return Section;
		}
	}

	return NULL;
}
UMovieSceneSection* MovieSceneHelpers::FindNearestSectionAtTime( const TArray<UMovieSceneSection*>& Sections, float Time )
{
	// Only update the section if the position is within the time span of the section
	// Or if there are no sections at the time, the left closest section to the time
	// Or in the case that Time is before all sections, take the section with the earliest start time
	UMovieSceneSection* ClosestSection = nullptr;
	float ClosestSectionTime = 0.f;
	UMovieSceneSection* EarliestSection = nullptr;
	float EarliestSectionTime = 0.f;
	for( int32 SectionIndex = 0; SectionIndex < Sections.Num(); ++SectionIndex )
	{
		UMovieSceneSection* Section = Sections[SectionIndex];

		if (Section->IsActive())
		{
			//@todo Sequencer - There can be multiple sections overlapping in time. Returning instantly does not account for that.
			if( Section->IsTimeWithinSection( Time ) )
			{
				return Section;
			}

			float EndTime = Section->GetEndTime();
			if (EndTime < Time)
			{
				float ClosestTime = Time - EndTime;
				if (!ClosestSection || ClosestTime < ClosestSectionTime)
				{
					ClosestSection = Section;
					ClosestSectionTime = ClosestTime;
				}
			}

			float StartTime = Section->GetStartTime();
			if (!EarliestSection || StartTime < EarliestSectionTime)
			{
				EarliestSection = Section;
				EarliestSectionTime = StartTime;
			}
		}
	}

	// if we get here, we are off of any section
	// if ClosestSection, then we take the closest to left of this time
	// else, we take the EarliestSection
	// if that's nullptr, then there are no sections
	return ClosestSection ? ClosestSection : EarliestSection;
}
UMovieSceneSection* UMovieScenePropertyTrack::FindOrAddSection( float Time )
{
	// Find a spot for the section so that they are sorted by start time
	for( int32 SectionIndex = 0; SectionIndex < Sections.Num(); ++SectionIndex )
	{
		UMovieSceneSection* Section = Sections[SectionIndex];

		if( Section->IsTimeWithinSection( Time ) )
		{
			return Section;
		}

		// Check if there are no more sections that would overlap the time 
		if( !Sections.IsValidIndex( SectionIndex+1 ) || Sections[SectionIndex+1]->GetStartTime() > Time )
		{
			// No sections overlap the time
		
			if( SectionIndex > 0 )
			{
				// Append and grow the previous section
				UMovieSceneSection* PreviousSection = Sections[ SectionIndex ? SectionIndex-1 : 0 ];
		
				PreviousSection->SetEndTime( Time );
				return PreviousSection;
			}
			else if( Sections.IsValidIndex( SectionIndex+1 ) )
			{
				// Prepend and grow the next section because there are no sections before this one
				UMovieSceneSection* NextSection = Sections[SectionIndex+1];
				NextSection->SetStartTime( Time );
				return NextSection;
			}	
			else
			{
				// SectionIndex == 0 
				UMovieSceneSection* PreviousSection = Sections[0];
				if( PreviousSection->GetEndTime() < Time )
				{
					// Append and grow the section
					PreviousSection->SetEndTime( Time );
				}
				else
				{
					// Prepend and grow the section
					PreviousSection->SetStartTime( Time );
				}
				return PreviousSection;
			}
		}

	}

	check( Sections.Num() == 0 );

	// Add a new section that starts and ends at the same time
	UMovieSceneSection* NewSection = CreateNewSection();
	NewSection->SetStartTime( Time );
	NewSection->SetEndTime( Time );

	Sections.Add( NewSection );

	return NewSection;
}