// Copyright Epic Games, Inc. All Rights Reserved. #include "Slate/UMGDragDropOp.h" #include "Application/SlateApplicationBase.h" #include "Engine/GameViewportClient.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/SWidget.h" #include "Widgets/Text/STextBlock.h" #include "Blueprint/DragDropOperation.h" #include "Slate/SObjectWidget.h" #include "Widgets/Layout/SDPIScaler.h" ////////////////////////////////////////////////////////////////////////// // FUMGDragDropOp FUMGDragDropOp::FUMGDragDropOp() : DragOperation(nullptr) , GameViewport(nullptr) { StartTime = FSlateApplicationBase::Get().GetCurrentTime(); } void FUMGDragDropOp::AddReferencedObjects(FReferenceCollector& Collector) { Collector.AddReferencedObject(DragOperation); } FString FUMGDragDropOp::GetReferencerName() const { return TEXT("FUMGDragDropOp"); } void FUMGDragDropOp::Construct() { } bool FUMGDragDropOp::AffectedByPointerEvent(const FPointerEvent& PointerEvent) { return DragOperation && PointerEvent.GetPointerIndex() == PointerIndex; } void FUMGDragDropOp::OnDrop( bool bDropWasHandled, const FPointerEvent& MouseEvent ) { if ( DragOperation ) { if ( bDropWasHandled && MouseEvent.GetPointerIndex() == PointerIndex ) { DragOperation->Drop(MouseEvent); } else { if ( TSharedPtr SourceUserWidgetPtr = SourceUserWidget.Pin() ) { SourceUserWidgetPtr->OnDragCancelled(FDragDropEvent(MouseEvent, AsShared()), DragOperation); } DragOperation->DragCancelled(MouseEvent); } } FDragDropOperation::OnDrop(bDropWasHandled, MouseEvent); } void FUMGDragDropOp::OnDragged( const class FDragDropEvent& DragDropEvent ) { if ( DragOperation && DragDropEvent.GetPointerIndex() == PointerIndex) { DragOperation->Dragged(DragDropEvent); FVector2D CachedDesiredSize = DecoratorWidget->GetDesiredSize(); FVector2D Position = DragDropEvent.GetScreenSpacePosition(); Position += CachedDesiredSize * DragOperation->Offset; switch ( DragOperation->Pivot ) { case EDragPivot::MouseDown: Position += MouseDownOffset; break; case EDragPivot::TopLeft: // Position is already Top Left. break; case EDragPivot::TopCenter: Position -= CachedDesiredSize * FVector2D(0.5f, 0); break; case EDragPivot::TopRight: Position -= CachedDesiredSize * FVector2D(1, 0); break; case EDragPivot::CenterLeft: Position -= CachedDesiredSize * FVector2D(0, 0.5f); break; case EDragPivot::CenterCenter: Position -= CachedDesiredSize * FVector2D(0.5f, 0.5f); break; case EDragPivot::CenterRight: Position -= CachedDesiredSize * FVector2D(1.0f, 0.5f); break; case EDragPivot::BottomLeft: Position -= CachedDesiredSize * FVector2D(0, 1); break; case EDragPivot::BottomCenter: Position -= CachedDesiredSize * FVector2D(0.5f, 1); break; case EDragPivot::BottomRight: Position -= CachedDesiredSize * FVector2D(1, 1); break; } const double AnimationTime = 0.150; double DeltaTime = FSlateApplicationBase::Get().GetCurrentTime() - StartTime; if ( DeltaTime < AnimationTime ) { double T = DeltaTime / AnimationTime; FVector2D LerpPosition = ( Position - StartingScreenPos ) * T; DecoratorPosition = StartingScreenPos + LerpPosition; } else { DecoratorPosition = Position; } } } TSharedPtr FUMGDragDropOp::GetDefaultDecorator() const { return DecoratorWidget; } FCursorReply FUMGDragDropOp::OnCursorQuery() { FCursorReply CursorReply = FGameDragDropOperation::OnCursorQuery(); if ( !CursorReply.IsEventHandled() ) { CursorReply = CursorReply.Cursor(EMouseCursor::Default); } if ( UGameViewportClient* GameViewportPtr = GameViewport.Get() ) { TOptional> CursorWidget = GameViewportPtr->MapCursor(nullptr, CursorReply); if ( CursorWidget.IsSet() ) { CursorReply.SetCursorWidget(GameViewportPtr->GetWindow(), CursorWidget.GetValue()); } } if (TSharedPtr SourceUserWidgetObj = SourceUserWidget.Pin()) { if (UUserWidget* SourceUserWidgetPtr = SourceUserWidgetObj->GetWidgetObject()) { if (SourceUserWidgetPtr->bOverride_Cursor) { CursorReply = CursorReply.Cursor(SourceUserWidgetPtr->GetCursor()); } } } return CursorReply; } TSharedRef FUMGDragDropOp::New(UDragDropOperation* InOperation, const int32 PointerIndex, const FVector2D &PointerPosition, const FVector2D &ScreenPositionOfDragee, float DPIScale, TSharedPtr SourceUserWidget) { check(InOperation); check(SourceUserWidget); TSharedRef Operation = MakeShareable(new FUMGDragDropOp()); Operation->PointerIndex = PointerIndex; Operation->MouseDownOffset = ScreenPositionOfDragee - PointerPosition; Operation->StartingScreenPos = ScreenPositionOfDragee; Operation->SourceUserWidget = SourceUserWidget; Operation->GameViewport = SourceUserWidget->GetWidgetObject()->GetWorld()->GetGameViewport(); Operation->DragOperation = InOperation; TSharedPtr DragVisual; if ( InOperation->DefaultDragVisual == nullptr ) { DragVisual = SNew(STextBlock) .Text(FText::FromString(InOperation->Tag)); } else { //TODO Make sure users are not trying to add a widget that already exists elsewhere. DragVisual = InOperation->DefaultDragVisual->TakeWidget(); } Operation->DecoratorWidget = SNew(SDPIScaler) .DPIScale(DPIScale) [ DragVisual.ToSharedRef() ]; Operation->DecoratorWidget->SlatePrepass(); Operation->Construct(); return Operation; }