// Copyright Epic Games, Inc. All Rights Reserved. #include "MVVM/Views/SSequencerTrackAreaView.h" #include "MVVM/Extensions/IObjectBindingExtension.h" #include "MVVM/Extensions/ITrackExtension.h" #include "MVVM/ViewModels/OutlinerSpacer.h" #include "MVVM/ViewModels/SequencerTrackAreaViewModel.h" #include "MVVM/Views/SOutlinerView.h" #include "ITimeSlider.h" #include "SequencerTimeSliderController.h" #include "Tools/SequencerEditTool_Selection.h" #include "Sequencer.h" #include "ISequencerTrackEditor.h" #include "Framework/Application/SlateApplication.h" namespace UE { namespace Sequencer { void SSequencerTrackAreaView::Construct(const FArguments& InArgs, TWeakPtr InWeakViewModel, TSharedRef InTimeSliderController) { TimeSliderController = InTimeSliderController; STrackAreaView::Construct(InArgs, InWeakViewModel); // Add the time slider controller to the input stack InputStack.AddHandler(TimeSliderController.Get()); } int32 SSequencerTrackAreaView::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { TSharedPtr ViewModel = WeakViewModel.Pin(); if (ViewModel) { FSequencerEditorViewModel* EditorViewModel = ViewModel->GetEditor()->CastThisChecked(); TSharedRef Sequencer = StaticCastSharedRef(EditorViewModel->GetSequencer().ToSharedRef()); // Give track editors a chance to paint // @todo_sequencer_mvvm: move track editors' code to viewmodels. //const TArray>& TrackEditors = Sequencer->GetTrackEditors(); //for (const TSharedPtr& TrackEditor : TrackEditors) //{ // LayerId = TrackEditor->PaintTrackArea(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId + 1, InWidgetStyle); //} } return STrackAreaView::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled); } FReply SSequencerTrackAreaView::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { //FContextMenuSuppressor SuppressContextMenus(TimeSliderController.ToSharedRef()); return STrackAreaView::OnMouseButtonUp(MyGeometry, MouseEvent); } void SSequencerTrackAreaView::UpdateHoverStates(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { STrackAreaView::UpdateHoverStates(MyGeometry, MouseEvent); TSharedPtr ViewModel = WeakViewModel.Pin(); TSharedPtr Hotspot = ViewModel ? ViewModel->GetHotspot() : nullptr; if (!Hotspot && ViewModel) { // Any other region implies selection mode ViewModel->AttemptToActivateTool(FSequencerEditTool_Selection::Identifier); } } void SSequencerTrackAreaView::OnResized(const FVector2D& OldSize, const FVector2D& NewSize) { // Zoom by the difference in horizontal size const float Difference = OldSize.X - SizeLastFrame->X; TRange OldRange = TimeSliderController->GetViewRange().GetAnimationTarget(); double NewRangeMin = OldRange.GetLowerBoundValue(); double NewRangeMax = OldRange.GetUpperBoundValue() + (Difference * OldRange.Size() / SizeLastFrame->X); TRange ClampRange = TimeSliderController->GetClampRange(); if (NewRangeMin < ClampRange.GetLowerBoundValue() || NewRangeMax > ClampRange.GetUpperBoundValue()) { double NewClampRangeMin = NewRangeMin < ClampRange.GetLowerBoundValue() ? NewRangeMin : ClampRange.GetLowerBoundValue(); double NewClampRangeMax = NewRangeMax > ClampRange.GetUpperBoundValue() ? NewRangeMax : ClampRange.GetUpperBoundValue(); TimeSliderController->SetClampRange(NewClampRangeMin, NewClampRangeMax); } TimeSliderController->SetViewRange( NewRangeMin, NewRangeMax, EViewRangeInterpolation::Immediate ); } FReply SSequencerTrackAreaView::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { using namespace UE::Sequencer; TSharedPtr Outliner = WeakOutliner.Pin(); TViewModelPtr DroppedItem = Outliner->HitTestNode(MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).Y); if (DroppedItem && DroppedItem.AsModel()->IsA()) { DroppedItem = nullptr; } WeakDroppedItem = DroppedItem; bAllowDrop = false; DropFrameRange.Reset(); TSharedPtr ViewModel = WeakViewModel.Pin(); FSequencerEditorViewModel* EditorViewModel = ViewModel->GetEditor()->CastThisChecked(); TSharedPtr Sequencer = EditorViewModel->GetSequencerImpl(); if (Sequencer && DroppedItem) { if (TSharedPtr TrackDestination = DroppedItem.ImplicitCast()) { UMovieSceneTrack* Track = TrackDestination->GetTrack(); const int32 TrackRow = TrackDestination->GetRowIndex(); TSharedPtr BindingExtension = DroppedItem.AsModel()->FindAncestorOfType(); FGuid ObjectBinding = BindingExtension ? BindingExtension->GetObjectGuid() : FGuid(); // give track editors a chance to accept the drag event const TArray>& TrackEditors = Sequencer->GetTrackEditors(); FVector2D LocalPos = MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()); FFrameNumber DropFrameNumber = TimeToPixel->PixelToFrame(LocalPos.X).FrameNumber; if (Sequencer->GetSequencerSettings()->GetForceWholeFrames()) { DropFrameNumber = FFrameRate::Snap(DropFrameNumber, Sequencer->GetFocusedTickResolution(), Sequencer->GetFocusedDisplayRate()).FrameNumber; } // If shift is pressed, drop onto the current time if (FSlateApplication::Get().GetModifierKeys().IsShiftDown()) { DropFrameNumber = Sequencer->GetLocalTime().Time.FrameNumber; } FSequencerDragDropParams DragDropParams(Track, TrackRow, ObjectBinding, DropFrameNumber, TRange()); for (const TSharedPtr& TrackEditor : TrackEditors) { if (TrackEditor->OnAllowDrop(DragDropEvent, DragDropParams)) { bAllowDrop = true; DropFrameRange = DragDropParams.FrameRange; return FReply::Handled(); } } } } return SPanel::OnDragOver(MyGeometry, DragDropEvent); } FReply SSequencerTrackAreaView::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { WeakDroppedItem = WeakOutliner.Pin()->HitTestNode(MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).Y); TSharedPtr DroppedItem = WeakDroppedItem.Pin(); TSharedPtr ViewModel = WeakViewModel.Pin(); FSequencerEditorViewModel* EditorViewModel = ViewModel->GetEditor()->CastThisChecked(); TSharedPtr Sequencer = EditorViewModel->GetSequencerImpl(); if (Sequencer && DroppedItem) { ITrackExtension* TrackDestination = DroppedItem->CastThis(); if (TrackDestination) { UMovieSceneTrack* Track = TrackDestination->GetTrack(); const int32 TrackRow = TrackDestination->GetRowIndex(); TSharedPtr BindingExtension = DroppedItem->FindAncestorOfType(); FGuid ObjectBinding = BindingExtension ? BindingExtension->GetObjectGuid() : FGuid(); // give track editors a chance to process the drag event const TArray>& TrackEditors = Sequencer->GetTrackEditors(); FVector2D LocalPos = MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()); FFrameNumber DropFrameNumber = TimeToPixel->PixelToFrame(LocalPos.X).FrameNumber; if (Sequencer->GetSequencerSettings()->GetForceWholeFrames()) { DropFrameNumber = FFrameRate::Snap(DropFrameNumber, Sequencer->GetFocusedTickResolution(), Sequencer->GetFocusedDisplayRate()).FrameNumber; } // If shift is pressed, drop onto the current time if (FSlateApplication::Get().GetModifierKeys().IsShiftDown()) { DropFrameNumber = Sequencer->GetLocalTime().Time.FrameNumber; } FSequencerDragDropParams DragDropParams(Track, TrackRow, ObjectBinding, DropFrameNumber, TRange()); for (const TSharedPtr& TrackEditor : TrackEditors) { if (TrackEditor->OnAllowDrop(DragDropEvent, DragDropParams)) { WeakDroppedItem = nullptr; return TrackEditor->OnDrop(DragDropEvent, DragDropParams); } } } } WeakDroppedItem = nullptr; return SPanel::OnDrop(MyGeometry, DragDropEvent); } } // namespace Sequencer } // namespace UE