// Copyright Epic Games, Inc. All Rights Reserved. #include "SequencerOutlinerItemDragDropOp.h" #include "MovieSceneSequence.h" #include "MovieSceneSequenceID.h" #include "MovieScene.h" #include "Sequencer.h" #include "K2Node_GetSequenceBinding.h" #include "MVVM/Extensions/IObjectBindingExtension.h" #include "MVVM/ViewModels/SequenceModel.h" #include "MVVM/ViewModels/SequencerEditorViewModel.h" #include "Widgets/Layout/SBorder.h" #include "Widgets/Images/SImage.h" #include "Widgets/Text/STextBlock.h" #include "Styling/AppStyle.h" #include "EdGraph/EdGraph.h" #define LOCTEXT_NAMESPACE "SequencerOutlinerDragDropOp" namespace UE { namespace Sequencer { TSharedRef FSequencerOutlinerDragDropOp::New(TArray>&& InDraggedNodes, FText InDefaultText, const FSlateBrush* InDefaultIcon) { TSharedRef NewOp = MakeShared(); NewOp->WeakViewModels = MoveTemp(InDraggedNodes); NewOp->DefaultHoverText = NewOp->CurrentHoverText = InDefaultText; NewOp->DefaultHoverIcon = NewOp->CurrentIconBrush = InDefaultIcon; NewOp->Construct(); return NewOp; } TArray FSequencerOutlinerDragDropOp::GetDraggedBindings() const { return GetDraggedBindingsImpl( [](const TWeakViewModelPtr&) { return true; } ); } TArray FSequencerOutlinerDragDropOp::GetDraggedRebindableBindings() const { return GetDraggedBindingsImpl( [](const TWeakViewModelPtr& WeakModel) { TViewModelPtr Object = WeakModel.ImplicitPin(); return Object && Object->SupportsRebinding(); } ); } TArray FSequencerOutlinerDragDropOp::GetDraggedBindingsImpl(TFunctionRef&)> InFilter) const { using namespace MovieScene; TArray Bindings; for (const TWeakViewModelPtr& WeakModel : GetDraggedViewModels()) { TViewModelPtr ObjectBinding = WeakModel.ImplicitPin(); if (!ObjectBinding || !InFilter(WeakModel)) { continue; } FGuid ObjectBindingID = ObjectBinding->GetObjectGuid(); TViewModelPtr Sequence = WeakModel.Pin().AsModel()->FindAncestorOfType(); if (Sequence && ObjectBindingID.IsValid()) { Bindings.Emplace(MovieScene::FFixedObjectBindingID(ObjectBindingID, Sequence->GetSequenceID())); } } return Bindings; } void FSequencerOutlinerDragDropOp::HoverTargetChanged() { if (GetHoveredGraph() && GetDraggedBindings().Num() > 0) { CurrentHoverText = LOCTEXT("CreateNode", "Add binding ID to graph"); CurrentIconBrush = FAppStyle::GetBrush( TEXT( "Graph.ConnectorFeedback.NewNode" ) ); } else { ResetToDefaultToolTip(); } } FReply FSequencerOutlinerDragDropOp::DroppedOnPanel( const TSharedRef< class SWidget >& Panel, const FVector2f& ScreenPosition, const FVector2f& GraphPosition, UEdGraph& Graph) { using namespace MovieScene; const UEdGraphSchema* Schema = Graph.GetSchema(); if (Schema) { UK2Node_GetSequenceBinding* Template = NewObject(GetTransientPackage()); FEdGraphSchemaAction_NewNode Action; Action.NodeTemplate = Template; FVector2f AddGraphPosition = GraphPosition; for (const TWeakViewModelPtr& WeakModel : GetDraggedViewModels()) { FViewModelPtr Model = WeakModel.Pin(); TViewModelPtr ObjectBinding = Model.ImplicitCast(); if (!ObjectBinding || !ObjectBinding->SupportsRebinding()) { continue; } TViewModelPtr SequenceModel = Model->FindAncestorOfType(); if (SequenceModel) { // Fixed bindings always resolve from the root Template->SetSequence(SequenceModel->GetSequencer()->GetRootMovieSceneSequence()); Template->Binding = FFixedObjectBindingID(ObjectBinding->GetObjectGuid(), SequenceModel->GetSequenceID()); UEdGraphNode* NewNode = Action.PerformAction(&Graph, GetHoveredPin(), FDeprecateSlateVector2D(AddGraphPosition), false); int32 Offset = FMath::Max(NewNode->NodeHeight, 100); Offset += Offset % 16; AddGraphPosition.Y += Offset; } } } return FReply::Handled(); } } // namespace Sequencer } // namespace UE #undef LOCTEXT_NAMESPACE