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>(); }
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; }