CARingBufferError CARingBuffer::CheckTimeBounds(SampleTime& startRead, SampleTime& endRead) { SampleTime startTime, endTime; CARingBufferError err = GetTimeBounds(startTime, endTime); if (err) return err; startRead = std::max(startRead, startTime); endRead = std::min(endRead, endTime); if (startRead < startTime) { if (endRead > endTime) return kCARingBufferError_TooMuch; if (endRead < startTime) return kCARingBufferError_WayBehind; else return kCARingBufferError_SlightlyBehind; } if (endRead > endTime) // we are going to read chunks of zeros its okay { if (startRead > endTime) return kCARingBufferError_WayAhead; else return kCARingBufferError_SlightlyAhead; } return kCARingBufferError_OK; // success }
FReply FSequencer::OnPlay() { if( PlaybackState == EMovieScenePlayerStatus::Playing || PlaybackState == EMovieScenePlayerStatus::Recording ) { PlaybackState = EMovieScenePlayerStatus::Stopped; // Update on stop (cleans up things like sounds that are playing) RootMovieSceneInstance->Update( ScrubPosition, ScrubPosition, *this ); } else { TRange<float> TimeBounds = GetTimeBounds(); if (!TimeBounds.IsEmpty()) { float CurrentTime = GetGlobalTime(); if (CurrentTime < TimeBounds.GetLowerBoundValue() || CurrentTime >= TimeBounds.GetUpperBoundValue()) { SetGlobalTime(TimeBounds.GetLowerBoundValue()); } PlaybackState = EMovieScenePlayerStatus::Playing; // Make sure Slate ticks during playback SequencerWidget->RegisterActiveTimerForPlayback(); } } return FReply::Handled(); }
void FSequencer::FilterToShotSections(const TArray< TWeakObjectPtr<class UMovieSceneSection> >& ShotSections, bool bZoomToShotBounds ) { TArray< TWeakObjectPtr<UMovieSceneSection> > ActualShotSections; for (int32 i = 0; i < ShotSections.Num(); ++i) { if (ShotSections[i]->IsA<UMovieSceneShotSection>()) { ActualShotSections.Add(ShotSections[i]); } } bool bWasPreviouslyFiltering = IsShotFilteringOn(); bool bIsNowFiltering = ActualShotSections.Num() > 0; FilteringShots.Empty(); UnfilterableSections.Empty(); UnfilterableObjects.Empty(); if (bIsNowFiltering) { for ( int32 ShotSectionIndex = 0; ShotSectionIndex < ActualShotSections.Num(); ++ShotSectionIndex ) { FilteringShots.Add( ActualShotSections[ShotSectionIndex] ); } // populate unfilterable shots - shots that started not filtered TArray< TWeakObjectPtr<class UMovieSceneSection> > TempUnfilterableSections; const TArray<UMovieSceneSection*>& AllSections = GetFocusedMovieScene()->GetAllSections(); for (int32 SectionIndex = 0; SectionIndex < AllSections.Num(); ++SectionIndex) { UMovieSceneSection* Section = AllSections[SectionIndex]; if (!Section->IsA<UMovieSceneShotSection>() && IsSectionVisible(Section)) { TempUnfilterableSections.Add(Section); } } // wait until after we've collected them all before applying in order to // prevent wastefully searching through UnfilterableSections in IsSectionVisible UnfilterableSections = TempUnfilterableSections; } if (!bWasPreviouslyFiltering && bIsNowFiltering) { OverlayAnimation.Play( SequencerWidget.ToSharedRef() ); } else if (bWasPreviouslyFiltering && !bIsNowFiltering) { OverlayAnimation.PlayReverse( SequencerWidget.ToSharedRef() ); } if( bZoomToShotBounds ) { // zoom in OnViewRangeChanged(GetTimeBounds(), true); } SequencerWidget->UpdateBreadcrumbs(ActualShotSections); }
FReply FSequencer::OnStepToBeginning() { PlaybackState = EMovieScenePlayerStatus::Stopped; TRange<float> TimeBounds = GetTimeBounds(); if (!TimeBounds.IsEmpty()) { SetGlobalTime(TimeBounds.GetLowerBoundValue()); } return FReply::Handled(); }
// This is the ClipTimeBounds() implementation as it ships in the sample code today. It's not all that helpful in that it doesn't signal why the time bounds have been clipped. CARingBufferError CARingBuffer::ClipTimeBounds(SampleTime& startRead, SampleTime& endRead) { SampleTime startTime, endTime; CARingBufferError err = GetTimeBounds(startTime, endTime); if (err) return err; startRead = std::max(startRead, startTime); endRead = std::min(endRead, endTime); endRead = std::max(endRead, startRead); return kCARingBufferError_OK; // success }
void FSequencer::Tick(float InDeltaTime) { if (bNeedTreeRefresh) { // @todo - Sequencer Will be called too often UpdateRuntimeInstances(); SequencerWidget->UpdateLayoutTree(); bNeedTreeRefresh = false; } float NewTime = GetGlobalTime() + InDeltaTime; if (PlaybackState == EMovieScenePlayerStatus::Playing || PlaybackState == EMovieScenePlayerStatus::Recording) { TRange<float> TimeBounds = GetTimeBounds(); if (!TimeBounds.IsEmpty()) { if (NewTime > TimeBounds.GetUpperBoundValue()) { if (bLoopingEnabled) { NewTime -= TimeBounds.Size<float>(); } else { NewTime = TimeBounds.GetUpperBoundValue(); PlaybackState = EMovieScenePlayerStatus::Stopped; } } if (NewTime < TimeBounds.GetLowerBoundValue()) { NewTime = TimeBounds.GetLowerBoundValue(); } SetGlobalTime(NewTime); } else { // no bounds at all, stop playing PlaybackState = EMovieScenePlayerStatus::Stopped; } } // Tick all the tools we own as well for (int32 EditorIndex = 0; EditorIndex < TrackEditors.Num(); ++EditorIndex) { TrackEditors[EditorIndex]->Tick(InDeltaTime); } }
void FSequencer::ZoomToSelectedSections() { TArray< TRange<float> > Bounds; for (TWeakObjectPtr<UMovieSceneSection> SelectedSection : *Selection.GetSelectedSections()) { Bounds.Add(SelectedSection->GetRange()); } TRange<float> BoundsHull = TRange<float>::Hull(Bounds); if (BoundsHull.IsEmpty()) { BoundsHull = GetTimeBounds(); } if (!BoundsHull.IsEmpty() && !BoundsHull.IsDegenerate()) { OnViewRangeChanged(BoundsHull, true); } }
CARingBufferError CARingBuffer::ClipTimeBounds(SampleTime& startRead, SampleTime& endRead) { SampleTime startTime, endTime; CARingBufferError err = GetTimeBounds(startTime, endTime); if (err) return err; // This is based on an older implementation of ClipTimeBounds. The difference is that these min/max calls were removed in favour of more explicit clipping in the logic below. The 2nd min() call would prevent the 2nd if() condition below from ever being true. // startRead = std::max(startRead, startTime); // endRead = std::min(endRead, endTime); if (startRead < startTime) { startRead = startTime; if (endRead > endTime) { endRead = endTime; return kCARingBufferError_TooMuch; } if (endRead < startTime) { endRead = startTime; return kCARingBufferError_WayBehind; } else { return kCARingBufferError_SlightlyBehind; } } if (endRead > endTime) { // we are going to read chunks of zeros its okay endRead = endTime; if (startRead > endTime) { startRead = endTime; return kCARingBufferError_WayAhead; } else { return kCARingBufferError_SlightlyAhead; } } return kCARingBufferError_OK; // success }