FReply FScrollyZoomy::OnMouseMove( const TSharedRef<SWidget> MyWidget, IScrollableZoomable& ScrollableZoomable, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if (MouseEvent.IsMouseButtonDown(EKeys::RightMouseButton)) { // If scrolling with the right mouse button, we need to remember how much we scrolled. // If we did not scroll at all, we will bring up the context menu when the mouse is released. AmountScrolledWhileRightMouseDown += FMath::Abs( MouseEvent.GetCursorDelta().X ) + FMath::Abs( MouseEvent.GetCursorDelta().Y ); // Has the mouse moved far enough with the right mouse button held down to start capturing // the mouse and dragging the view? if (IsRightClickScrolling()) { this->HorizontalIntertia.AddScrollSample( MouseEvent.GetCursorDelta().X, FPlatformTime::Seconds() ); this->VerticalIntertia.AddScrollSample( MouseEvent.GetCursorDelta().Y, FPlatformTime::Seconds() ); const bool DidScroll = ScrollableZoomable.ScrollBy( MouseEvent.GetCursorDelta() ); FReply Reply = FReply::Handled(); // Capture the mouse if we need to if (MyWidget->HasMouseCapture() == false) { Reply.CaptureMouse( MyWidget ).UseHighPrecisionMouseMovement( MyWidget ); SoftwareCursorPosition = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); bShowSoftwareCursor = true; } // Check if the mouse has moved. if (DidScroll) { SoftwareCursorPosition += MouseEvent.GetCursorDelta(); } return Reply; } } return FReply::Unhandled(); }
FReply SSection::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( bDragging && DragOperation.IsValid() ) { // If dragging tell the operation we are no longer dragging DragOperation->OnEndDrag(ParentSectionArea); } else { if( ( MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton || MouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) && HasMouseCapture() && MyGeometry.IsUnderLocation( MouseEvent.GetScreenSpacePosition() ) ) { HandleSelection( MyGeometry, MouseEvent ); } if( MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && HasMouseCapture() ) { TSharedPtr<SWidget> MenuContent = OnSummonContextMenu( MyGeometry, MouseEvent ); if (MenuContent.IsValid()) { FWidgetPath WidgetPath = MouseEvent.GetEventPath() != nullptr ? *MouseEvent.GetEventPath() : FWidgetPath(); FSlateApplication::Get().PushMenu( AsShared(), WidgetPath, MenuContent.ToSharedRef(), MouseEvent.GetScreenSpacePosition(), FPopupTransitionEffect( FPopupTransitionEffect::ContextMenu ) ); return FReply::Handled().ReleaseMouseCapture().SetUserFocus(MenuContent.ToSharedRef(), EFocusCause::SetDirectly); } } } ResetState(); return FReply::Handled().ReleaseMouseCapture(); }
TSharedPtr<SWidget> STrack::SummonContextMenu(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { bool SummonedContextMenu = false; const bool bCloseWindowAfterMenuSelection = true; FMenuBuilder MenuBuilder( bCloseWindowAfterMenuSelection, EditorActions ); FVector2D CursorPos = MouseEvent.GetScreenSpacePosition(); float DataPos = LocalToDataX( MyGeometry.AbsoluteToLocal(CursorPos).X, MyGeometry ); // Context menu for a node int NotifyIndex = GetHitNode(MyGeometry, MyGeometry.AbsoluteToLocal(CursorPos)); if(NotifyIndex != INDEX_NONE) { if(TrackNodes[NotifyIndex]->OnNodeRightClickContextMenu.IsBound()) { TrackNodes[NotifyIndex]->OnNodeRightClickContextMenu.Execute(MenuBuilder); SummonedContextMenu = true; } } // Context menu for track itself if(OnTrackRightClickContextMenu.IsBound()) { SummonedContextMenu = true; OnTrackRightClickContextMenu.Execute(MenuBuilder, DataPos, DraggableBarIndex); } // Build the menu if we actually added anything to it TSharedPtr<SWindow> ContextMenuWindow = NULL; if(SummonedContextMenu) { ContextMenuWindow = FSlateApplication::Get().PushMenu( SharedThis( this ), MenuBuilder.MakeWidget(), CursorPos, FPopupTransitionEffect( FPopupTransitionEffect::ContextMenu )); } return ContextMenuWindow; }
FReply FSceneViewport::OnTouchMoved( const FGeometry& MyGeometry, const FPointerEvent& TouchEvent ) { // Start a new reply state CurrentReplyState = FReply::Handled(); UpdateCachedMousePos(MyGeometry, TouchEvent); UpdateCachedGeometry(MyGeometry); if( ViewportClient ) { // Switch to the viewport clients world before processing input FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient ); const FVector2D TouchPosition = MyGeometry.AbsoluteToLocal(TouchEvent.GetScreenSpacePosition()); if( !ViewportClient->InputTouch( this, TouchEvent.GetUserIndex(), TouchEvent.GetPointerIndex(), ETouchType::Moved, TouchPosition, FDateTime::Now(), TouchEvent.GetTouchpadIndex()) ) { CurrentReplyState = FReply::Unhandled(); } } return CurrentReplyState; }
TSharedPtr<SWidget> SSection::OnSummonContextMenu( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { FSelectedKey Key = GetKeyUnderMouse( MouseEvent.GetScreenSpacePosition(), MyGeometry ); FSequencer& Sequencer = GetSequencer(); UMovieSceneSection* SceneSection = SectionInterface->GetSectionObject(); // @todo sequencer replace with UI Commands instead of faking it const bool bShouldCloseWindowAfterMenuSelection = true; FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, NULL); if (Key.IsValid()) { MenuBuilder.AddMenuEntry( NSLOCTEXT("Sequencer", "DeleteKey", "Delete"), NSLOCTEXT("Sequencer", "DeleteKeyToolTip", "Deletes the selected keys."), FSlateIcon(), FUIAction(FExecuteAction::CreateSP(&Sequencer, &FSequencer::DeleteSelectedKeys)) ); } else { SectionInterface->BuildSectionContextMenu(MenuBuilder); // @todo Sequencer this should delete all selected sections // delete/selection needs to be rethought in general MenuBuilder.AddMenuEntry( NSLOCTEXT("Sequencer", "DeleteSection", "Delete"), NSLOCTEXT("Sequencer", "DeleteSectionToolTip", "Deletes this section."), FSlateIcon(), FUIAction(FExecuteAction::CreateSP(&Sequencer, &FSequencer::DeleteSection, SceneSection)) ); } return MenuBuilder.MakeWidget(); }
FReply SProfilerThreadView::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { FReply Reply = FReply::Unhandled(); if( IsReady() ) { MousePositionOnButtonDown = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); if( MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton ) { bIsLeftMousePressed = true; DistanceDragged = PositionXMS; // Capture mouse, so we can move outside this widget. Reply = FReply::Handled().CaptureMouse( SharedThis( this ) ); } else if( MouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { bIsRightMousePressed = true; } } return Reply; }
void STableViewBase::OnRightMouseButtonUp(const FPointerEvent& MouseEvent) { const FVector2D& SummonLocation = MouseEvent.GetScreenSpacePosition(); const bool bShouldOpenContextMenu = !IsRightClickScrolling(); const bool bContextMenuOpeningBound = OnContextMenuOpening.IsBound(); if ( bShouldOpenContextMenu && bContextMenuOpeningBound ) { // Get the context menu content. If NULL, don't open a menu. TSharedPtr<SWidget> MenuContent = OnContextMenuOpening.Execute(); if( MenuContent.IsValid() ) { bShowSoftwareCursor = false; FWidgetPath WidgetPath = MouseEvent.GetEventPath() != nullptr ? *MouseEvent.GetEventPath() : FWidgetPath(); FSlateApplication::Get().PushMenu(AsShared(), WidgetPath, MenuContent.ToSharedRef(), SummonLocation, FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)); } } AmountScrolledWhileRightMouseDown = 0; }
FReply SVirtualJoystick::OnTouchMoved(const FGeometry& MyGeometry, const FPointerEvent& Event) { FVector2D LocalCoord = MyGeometry.AbsoluteToLocal( Event.GetScreenSpacePosition() ); for (int32 ControlIndex = 0; ControlIndex < Controls.Num(); ControlIndex++) { FControlInfo& Control = Controls[ControlIndex]; // is this control the one captured to this pointer? if (Control.CapturedPointerIndex == Event.GetPointerIndex()) { if (Control.bNeedUpdatedCenter) { return FReply::Unhandled(); } else if (HandleTouch(ControlIndex, LocalCoord, MyGeometry.Size)) { return FReply::Handled(); } } } return FReply::Unhandled(); }
bool SColorWheel::ProcessMouseAction(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, bool bProcessWhenOutsideColorWheel) { const FVector2D LocalMouseCoordinate = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); const FVector2D Location = LocalMouseCoordinate / (MyGeometry.Size * 0.5f) - FVector2D(1.0f, 1.0f); const float Radius = Location.Size(); if (Radius <= 1.0f || bProcessWhenOutsideColorWheel) { float Angle = FMath::Atan2(Location.Y, Location.X); if (Angle < 0.0f) { Angle += 2.0f * PI; } FLinearColor NewColor = SelectedColor.Get(); NewColor.R = Angle * 180.0f * INV_PI; NewColor.G = FMath::Min(Radius, 1.0f); OnValueChanged.ExecuteIfBound(NewColor); } return (Radius <= 1.0f); }
FReply SProfilerThreadView::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { // SCOPE_LOG_TIME_FUNC(); FReply Reply = FReply::Unhandled(); if( IsReady() ) { const FVector2D LocalMousePosition = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); HoveredPositionX = 0.0;//PositionToFrameIndex( LocalMousePosition.X ); HoveredPositionY = 0.0; const float CursorPosXDelta = -MouseEvent.GetCursorDelta().X; const float ScrollSpeed = 1.0f / ZoomFactorX; if( MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton ) ) { if( HasMouseCapture() && !MouseEvent.GetCursorDelta().IsZero() ) { DistanceDragged += CursorPosXDelta*ScrollSpeed*0.1; // Inform other widgets that we have scrolled the thread-view. SetPositionX( FMath::Clamp( DistanceDragged, 0.0, TotalRangeXMS - RangeXMS ) ); CursorType = EThreadViewCursor::Hand; Reply = FReply::Handled(); } } else { CursorType = EThreadViewCursor::Default; } } return Reply; }
int32 SWidget::FindChildUnderMouse( const FArrangedChildren& Children, const FPointerEvent& MouseEvent ) { const FVector2D& AbsoluteCursorLocation = MouseEvent.GetScreenSpacePosition(); return SWidget::FindChildUnderPosition( Children, AbsoluteCursorLocation ); }
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { struct FWidgetPicker { static bool FindWidgetsUnderPoint(const FVector2D& InHitTestPoint, const FVector2D& InWindowPosition, const TSharedRef<FWidgetReflectorNodeBase>& InWidget, TArray<TSharedRef<FWidgetReflectorNodeBase>>& OutWidgets) { const bool bNeedsHitTesting = InWidget->GetHitTestInfo().IsHitTestVisible || InWidget->GetHitTestInfo().AreChildrenHitTestVisible; if (bNeedsHitTesting) { const FSlateRect HitTestRect = FSlateRect::FromPointAndExtent( InWidget->GetAccumulatedLayoutTransform().GetTranslation() - InWindowPosition, TransformPoint(InWidget->GetAccumulatedLayoutTransform().GetScale(), InWidget->GetLocalSize()) ); if (HitTestRect.ContainsPoint(InHitTestPoint)) { OutWidgets.Add(InWidget); if (InWidget->GetHitTestInfo().AreChildrenHitTestVisible) { for (const auto& ChildWidget : InWidget->GetChildNodes()) { if (FindWidgetsUnderPoint(InHitTestPoint, InWindowPosition, ChildWidget, OutWidgets)) { return true; } } } return InWidget->GetHitTestInfo().IsHitTestVisible; } } return false; } }; if (bIsPicking) { // We need to pick in the snapshot window space, so convert the mouse co-ordinates to be relative to our top-left position const FVector2D& ScreenMousePos = MouseEvent.GetScreenSpacePosition(); const FVector2D LocalMousePos = MyGeometry.AbsoluteToLocal(ScreenMousePos); const FVector2D ScrolledPos = LocalMousePos - PhysicalOffset; PickedWidgets.Reset(); TSharedPtr<FWidgetReflectorNodeBase> Window = SnapshotDataPtr->GetWindow(SelectedWindowIndex); if (Window.IsValid()) { FWidgetPicker::FindWidgetsUnderPoint( ScrolledPos, Window->GetAccumulatedLayoutTransform().GetTranslation(), Window.ToSharedRef(), PickedWidgets ); } if (PickedWidgets.Num() > 0) { OnWidgetPathPicked.ExecuteIfBound(PickedWidgets); } } return ScrollyZoomy.OnMouseMove(AsShared(), *this, MyGeometry, MouseEvent); }
FReply FTextEditHelper::OnMouseMove( const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent, const TSharedRef< ITextEditorWidget >& TextEditor ) { FReply Reply = FReply::Unhandled(); if( TextEditor->IsDragSelecting() && TextEditor->GetWidget()->HasMouseCapture() && InMouseEvent.GetCursorDelta() != FVector2D::ZeroVector ) { TextEditor->MoveCursor( FMoveCursor::ViaScreenPointer( InMyGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition( ) ), InMyGeometry.Scale, ECursorAction::SelectText ) ); TextEditor->SetHasDragSelectedSinceFocused( true ); Reply = FReply::Handled(); } return Reply; }
void FSceneViewport::UpdateCachedMousePos( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) { CachedMousePos = InGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition() ).IntPoint(); }
FReply FSceneViewport::OnMouseButtonDown( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) { // Start a new reply state // Prevent throttling when interacting with the viewport so we can move around in it CurrentReplyState = FReply::Handled().PreventThrottling(); KeyStateMap.Add(InMouseEvent.GetEffectingButton(), true); UpdateModifierKeys( InMouseEvent ); UpdateCachedMousePos( InGeometry, InMouseEvent ); UpdateCachedGeometry(InGeometry); // Switch to the viewport clients world before processing input FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient ); if( ViewportClient && GetSizeXY() != FIntPoint::ZeroValue ) { // If we're obtaining focus, we have to copy the modifier key states prior to processing this mouse button event, as this is the only point at which the mouse down // event is processed when focus initially changes and the modifier keys need to be in-place to detect any unique drag-like events. if ( !HasFocus() ) { FModifierKeysState KeysState = FSlateApplication::Get().GetModifierKeys(); ApplyModifierKeys( KeysState ); } const bool bAnyMenuWasVisible = FSlateApplication::Get().AnyMenusVisible(); // Process the mouse event if (!ViewportClient->InputKey(this, InMouseEvent.GetUserIndex(), InMouseEvent.GetEffectingButton(), IE_Pressed)) { CurrentReplyState = FReply::Unhandled(); } // a new menu was opened if there was previously not a menu visible but now there is const bool bNewMenuWasOpened = !bAnyMenuWasVisible && FSlateApplication::Get().AnyMenusVisible(); if (!ViewportClient->IgnoreInput() && !bNewMenuWasOpened && // We should not focus the viewport if a menu was opened as it would close the menu ( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CapturePermanently || ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringMouseDown || ( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringRightMouseDown && InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) ) ) { TSharedRef<SViewport> ViewportWidgetRef = ViewportWidget.Pin().ToSharedRef(); // Mouse down should focus viewport for user input CurrentReplyState.SetUserFocus(ViewportWidgetRef, EFocusCause::SetDirectly, true); UWorld* World = ViewportClient->GetWorld(); if (World && World->IsGameWorld() && World->GetFirstPlayerController()) { CurrentReplyState.CaptureMouse(ViewportWidgetRef); CurrentReplyState.LockMouseToWidget(ViewportWidgetRef); bool bShouldShowMouseCursor = World->GetFirstPlayerController()->ShouldShowMouseCursor(); if (ViewportClient->HideCursorDuringCapture() && bShouldShowMouseCursor) { bCursorHiddenDueToCapture = true; MousePosBeforeHiddenDueToCapture = FIntPoint( InMouseEvent.GetScreenSpacePosition().X, InMouseEvent.GetScreenSpacePosition().Y ); } if (bCursorHiddenDueToCapture || !bShouldShowMouseCursor) { CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef); } } else { CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef); } } } // Re-set prevent throttling here as it can get reset when inside of InputKey() CurrentReplyState.PreventThrottling(); return CurrentReplyState; }
float SDockingTabWell::ComputeDraggedTabOffset( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, const FVector2D& InTabGrabOffsetFraction ) const { const FVector2D ComputedChildSize = ComputeChildSize(MyGeometry); return MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ).X - InTabGrabOffsetFraction .X * ComputedChildSize.X; }
void SColorGradientEditor::OpenGradientStopContextMenu(const FPointerEvent& MouseEvent) { const FVector2D& Location = MouseEvent.GetScreenSpacePosition(); FMenuBuilder GradientStopMenu( true, NULL ); FUIAction RemoveStopAction( FExecuteAction::CreateSP( this, &SColorGradientEditor::OnRemoveSelectedGradientStop ) ); { TSharedPtr<SWidget> WidgetToFocus; // Set color if( SelectedStop.IsValidColorMark( CurveOwner->GetCurves() ) ) { GradientStopMenu.BeginSection( NAME_None, LOCTEXT("ColorMenuSecton", "Color") ); FUIAction SetColorAction( FExecuteAction::CreateSP( this, &SColorGradientEditor::OpenGradientStopColorPicker ) ); GradientStopMenu.AddMenuEntry( LOCTEXT("SetColorMenuItem", "Choose Color..."), LOCTEXT("SetColorMenuItem_ToolTip", "Opens a color picker to change the color of the stop"), FSlateIcon(), SetColorAction ); GradientStopMenu.EndSection(); } else { GradientStopMenu.BeginSection( NAME_None, LOCTEXT("AlphaMenuSection", "Opacity") ); TSharedRef<SWidget> Widget = SNew( SBox ) .WidthOverride( 100.0f ) [ SNew( SSpinBox<float> ) .MinSliderValue(0.0f) .MaxSliderValue(1.0f) .MinValue(-FLT_MAX) .MaxValue(FLT_MAX) .Value( SelectedStop.GetColor( *CurveOwner ).A ) .OnBeginSliderMovement( this, &SColorGradientEditor::OnBeginChangeAlphaValue ) .OnEndSliderMovement( this, &SColorGradientEditor::OnEndChangeAlphaValue ) .OnValueChanged( this, &SColorGradientEditor::OnAlphaValueChanged ) .OnValueCommitted( this, &SColorGradientEditor::OnAlphaValueCommitted ) ]; GradientStopMenu.AddWidget( Widget, FText::GetEmpty() ); GradientStopMenu.EndSection(); } // Set time { TSharedRef<SEditableTextBox> EditableTextBox = SNew( SEditableTextBox ) .MinDesiredWidth(50.0f) .Text( FText::AsNumber( SelectedStop.Time ) ) .OnTextCommitted( this, &SColorGradientEditor::OnSetGradientStopTimeFromPopup ) .SelectAllTextWhenFocused( true ) .ClearKeyboardFocusOnCommit( false ) .SelectAllTextOnCommit( true ); GradientStopMenu.BeginSection( NAME_None, LOCTEXT("TimeMenuSection", "Time") ); GradientStopMenu.AddWidget( EditableTextBox, FText::GetEmpty() ); GradientStopMenu.EndSection(); WidgetToFocus = EditableTextBox; } GradientStopMenu.AddMenuSeparator(); // Add a Remove option GradientStopMenu.AddMenuEntry( LOCTEXT("RemoveGradientStop", "Remove Stop"), LOCTEXT("RemoveGradientStopTooltip", "Removes the selected gradient stop"), FSlateIcon(), RemoveStopAction ); FWidgetPath WidgetPath = MouseEvent.GetEventPath() != nullptr ? *MouseEvent.GetEventPath() : FWidgetPath(); FSlateApplication::Get().PushMenu(AsShared(), WidgetPath, GradientStopMenu.MakeWidget(), Location, FPopupTransitionEffect::ContextMenu); FSlateApplication::Get().SetKeyboardFocus( WidgetToFocus.ToSharedRef() ); } ContextMenuPosition = Location; }
/** * Invoked when the drag and drop operation has ended. * * @param bDropWasHandled true when the drop was handled by some widget; false otherwise */ void FDockingDragOperation::OnDrop( bool bDropWasHandled, const FPointerEvent& MouseEvent ) { check(CursorDecoratorWindow.IsValid()); const FVector2D WindowSize = CursorDecoratorWindow->GetSizeInScreen(); // Destroy the CursorDecoratorWindow by calling the base class implementation because we are relocating the content into a more permanent home. FDragDropOperation::OnDrop(bDropWasHandled, MouseEvent); TabBeingDragged->SetDraggedOverDockArea( NULL ); if (!bDropWasHandled) { // If we dropped the tab into an existing DockNode then it would have handled the DropEvent. // We are here because that didn't happen, so make a new window with a new DockNode and drop the tab into that. const FVector2D PositionToDrop = MouseEvent.GetScreenSpacePosition() - GetDecoratorOffsetFromCursor(); TSharedRef<FTabManager> MyTabManager = TabBeingDragged->GetTabManager(); TSharedPtr<SWindow> NewWindowParent = MyTabManager->GetPrivateApi().GetParentWindow(); TSharedRef<SWindow> NewWindow = SNew(SWindow) .Title( FGlobalTabmanager::Get()->GetApplicationTitle() ) .AutoCenter(EAutoCenter::None) .ScreenPosition( PositionToDrop ) // Make room for the title bar; otherwise windows will get progressive smaller whenver you float them. .ClientSize( SWindow::ComputeWindowSizeForContent( WindowSize ) ) .CreateTitleBar(false); TSharedPtr<SDockingTabStack> NewDockNode; if ( TabBeingDragged->GetTabRole() == ETabRole::NomadTab ) { TabBeingDragged->SetTabManager(FGlobalTabmanager::Get()); } // Create a new dockarea TSharedRef<SDockingArea> NewDockArea = SNew(SDockingArea, TabBeingDragged->GetTabManager(), FTabManager::NewPrimaryArea()) . ParentWindow( NewWindow ) . InitialContent ( SAssignNew(NewDockNode, SDockingTabStack, FTabManager::NewStack()) ); if (TabBeingDragged->GetTabRole() == ETabRole::MajorTab || TabBeingDragged->GetTabRole() == ETabRole::NomadTab) { TSharedPtr<SWindow> RootWindow = FGlobalTabmanager::Get()->GetRootWindow(); if ( RootWindow.IsValid() ) { // We have a root window, so all MajorTabs are nested under it. FSlateApplication::Get().AddWindowAsNativeChild( NewWindow, RootWindow.ToSharedRef() )->SetContent(NewDockArea); } else { // App tabs get put in top-level windows. They show up on the taskbar. FSlateApplication::Get().AddWindow( NewWindow )->SetContent(NewDockArea); } } else { // Other tab types are placed in child windows. Their life is controlled by the top-level windows. // They do not show up on the taskbar. if ( NewWindowParent.IsValid() ) { FSlateApplication::Get().AddWindowAsNativeChild( NewWindow, NewWindowParent.ToSharedRef() )->SetContent(NewDockArea); } else { FSlateApplication::Get().AddWindow( NewWindow )->SetContent(NewDockArea); } } // Do this after the window parenting so that the window title is set correctly NewDockNode->OpenTab(TabBeingDragged.ToSharedRef()); // Let every widget under this tab manager know that this tab has found a new home. TabOwnerAreaOfOrigin->GetTabManager()->GetPrivateApi().OnTabRelocated( TabBeingDragged.ToSharedRef(), NewWindow ); } else { // The event was handled, so we HAVE to have some window that we dropped onto. TSharedRef<SWindow> WindowDroppedInto = MouseEvent.GetWindow(); // Let every widget under this tab manager know that this tab has found a new home. TSharedPtr<SWindow> NewWindow = ( TabOwnerAreaOfOrigin->GetParentWindow() == WindowDroppedInto ) // Tab dropped into same window as before, meaning there is no NewWindow. ? TSharedPtr<SWindow>() // Tab was dropped into a different window, so the tab manager needs to know in order to re-parent child windows. : WindowDroppedInto; TabOwnerAreaOfOrigin->GetTabManager()->GetPrivateApi().OnTabRelocated( TabBeingDragged.ToSharedRef(), WindowDroppedInto ); } }
FReply FTextEditHelper::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& InMouseEvent, const TSharedRef< ITextEditorWidget >& TextEditor ) { FReply Reply = FReply::Unhandled(); // If the mouse is already captured, then don't allow a new action to be taken if( !TextEditor->GetWidget()->HasMouseCapture() ) { if( InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton || InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { // Am I getting focus right now? const bool bIsGettingFocus = !TextEditor->GetWidget()->HasKeyboardFocus(); if( bIsGettingFocus ) { // We might be receiving keyboard focus due to this event. Because the keyboard focus received callback // won't fire until after this function exits, we need to make sure our widget's state is in order early // Assume we'll be given keyboard focus, so load text for editing TextEditor->LoadText(); // Reset 'mouse has moved' state. We'll use this in OnMouseMove to determine whether we // should reset the selection range to the caret's position. TextEditor->SetWasFocusedByLastMouseDown( true ); } if( InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton ) { if( InMouseEvent.IsShiftDown() ) { TextEditor->MoveCursor( FMoveCursor::ViaScreenPointer( MyGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition( ) ), MyGeometry.Scale, ECursorAction::SelectText ) ); } else { // Deselect any text that was selected TextEditor->ClearSelection(); TextEditor->MoveCursor( FMoveCursor::ViaScreenPointer( MyGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition( ) ), MyGeometry.Scale, ECursorAction::MoveCursor ) ); } // Start drag selection TextEditor->BeginDragSelection(); } else if( InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { // If the user right clicked on a character that wasn't already selected, we'll clear // the selection if ( TextEditor->AnyTextSelected( ) && !TextEditor->IsTextSelectedAt( MyGeometry, InMouseEvent.GetScreenSpacePosition() ) ) { // Deselect any text that was selected TextEditor->ClearSelection(); } } // Right clicking to summon context menu, but we'll do that on mouse-up. Reply = FReply::Handled(); Reply.CaptureMouse( TextEditor->GetWidget() ); Reply.SetUserFocus(TextEditor->GetWidget(), EFocusCause::Mouse); } } return Reply; }
FVector2D UKismetInputLibrary::PointerEvent_GetScreenSpacePosition(const FPointerEvent& Input) { return Input.GetScreenSpacePosition(); }
FReply SCaptureRegionWidget::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if (IsEnabled() && MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { FVector2D ViewportPosition = MouseEvent.GetScreenSpacePosition() - MyGeometry.AbsolutePosition; FIntRect& CurrentCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion; switch (PotentialInteraction) { case PI_DrawNewCaptureRegion: { DragStartPosition = MouseEvent.GetScreenSpacePosition() - MyGeometry.AbsolutePosition; BuildNewCaptureRegion(DragStartPosition, DragStartPosition); CurrentState = State_Dragging; break; } case PI_ResizeBL: { DragStartPosition = FVector2D(CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Min.Y); BuildNewCaptureRegion(ViewportPosition, DragStartPosition); CurrentState = State_Dragging; break; } case PI_ResizeTL: { DragStartPosition = FVector2D(CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Max.Y); BuildNewCaptureRegion(ViewportPosition, DragStartPosition); CurrentState = State_Dragging; break; } case PI_ResizeBR: { DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y); BuildNewCaptureRegion(ViewportPosition, DragStartPosition); CurrentState = State_Dragging; break; } case PI_ResizeTR: { DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Max.Y); BuildNewCaptureRegion(ViewportPosition, DragStartPosition); CurrentState = State_Dragging; break; } case PI_ResizeBottom: { DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y); CurrentState = State_YAxisResize; break; } case PI_ResizeTop: { DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Max.Y); CurrentState = State_YAxisResize; break; } case PI_ResizeLeft: { DragStartPosition = FVector2D(CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Min.Y); CurrentState = State_XAxisResize; break; } case PI_ResizeRight: { DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y); CurrentState = State_XAxisResize; break; } case PI_MoveExistingRegion: { DragStartPosition = ViewportPosition; CurrentState = State_Moving; break; } } return FReply::Handled(); } else { return FReply::Unhandled(); } }
FReply SCaptureRegionWidget::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if (IsEnabled()) { FVector2D ViewportPosition = MouseEvent.GetScreenSpacePosition() - MyGeometry.AbsolutePosition; FIntRect& CurrentCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion; switch (CurrentState) { case State_Dragging: { BuildNewCaptureRegion(ViewportPosition, DragStartPosition); break; } case State_Moving: { FVector2D Delta = ViewportPosition - DragStartPosition; DragStartPosition = ViewportPosition; CurrentCaptureRegion += FIntPoint((int32)Delta.X, (int32)Delta.Y); //OnCaptureRegionChanged.ExecuteIfBound(CurrentCaptureRegion); SendUpdatedCaptureRegion(); break; } case State_XAxisResize: { ViewportPosition.Y = CurrentCaptureRegion.Max.Y; BuildNewCaptureRegion(ViewportPosition, DragStartPosition); break; } case State_YAxisResize: { ViewportPosition.X = CurrentCaptureRegion.Max.X; BuildNewCaptureRegion(ViewportPosition, DragStartPosition); break; } case State_Inactive: { if (CurrentCaptureRegion.Area() > 0 && !bIgnoreExistingCaptureRegion) { // Common tests bool bWithinXRangeOfExistingRegion = ViewportPosition.X >= CurrentCaptureRegion.Min.X && ViewportPosition.X <= CurrentCaptureRegion.Max.X; bool bWithinYRangeOfExistingRegion = ViewportPosition.Y >= CurrentCaptureRegion.Min.Y && ViewportPosition.Y <= CurrentCaptureRegion.Max.Y; // Distance away from an edge which we consider intersecting const float EdgeDistance = 5; // Check if we're over the corners if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y)).Size() < EdgeDistance) { this->Cursor = EMouseCursor::ResizeSouthEast; PotentialInteraction = PI_ResizeTL; } else if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Max.Y)).Size() < EdgeDistance) { this->Cursor = EMouseCursor::ResizeSouthWest; PotentialInteraction = PI_ResizeBL; } else if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Min.Y)).Size() < EdgeDistance) { this->Cursor = EMouseCursor::ResizeSouthWest; PotentialInteraction = PI_ResizeTR; } else if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Max.Y)).Size() < EdgeDistance) { this->Cursor = EMouseCursor::ResizeSouthEast; PotentialInteraction = PI_ResizeBR; } else if (FMath::Abs((float)CurrentCaptureRegion.Min.X - ViewportPosition.X) < EdgeDistance && bWithinYRangeOfExistingRegion) { this->Cursor = EMouseCursor::ResizeLeftRight; PotentialInteraction = PI_ResizeLeft; } else if (FMath::Abs((float)CurrentCaptureRegion.Max.X - ViewportPosition.X) < EdgeDistance && bWithinYRangeOfExistingRegion) { this->Cursor = EMouseCursor::ResizeLeftRight; PotentialInteraction = PI_ResizeRight; } else if (FMath::Abs((float)CurrentCaptureRegion.Min.Y - ViewportPosition.Y) < EdgeDistance && bWithinXRangeOfExistingRegion) { this->Cursor = EMouseCursor::ResizeUpDown; PotentialInteraction = PI_ResizeTop; } else if (FMath::Abs((float)CurrentCaptureRegion.Max.Y - ViewportPosition.Y) < EdgeDistance && bWithinXRangeOfExistingRegion) { this->Cursor = EMouseCursor::ResizeUpDown; PotentialInteraction = PI_ResizeBottom; } else if (CurrentCaptureRegion.Contains(FIntPoint((int32)ViewportPosition.X, (int32)ViewportPosition.Y))) { this->Cursor = EMouseCursor::CardinalCross; PotentialInteraction = PI_MoveExistingRegion; } else { this->Cursor = EMouseCursor::Crosshairs; PotentialInteraction = PI_DrawNewCaptureRegion; } } else { this->Cursor = EMouseCursor::Crosshairs; PotentialInteraction = PI_DrawNewCaptureRegion; } break; } default: { check(false); break; } } return FReply::Handled(); } else { return FReply::Unhandled(); } }
FReply SSection::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( HasMouseCapture() ) { // Have mouse capture and there are drag operations that need to be performed if( MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton ) ) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); FVector2D LocalMousePos = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); if( !bDragging ) { // If we are not dragging determine if the mouse has moved far enough to start a drag if( DistanceDragged >= SequencerSectionConstants::SectionDragStartDistance ) { bDragging = true; if( PressedKey.IsValid() ) { // Clear selected sections when beginning to drag keys GetSequencer().GetSelection().EmptySelectedSections(); bool bSelectDueToDrag = true; HandleKeySelection( PressedKey, MouseEvent, bSelectDueToDrag ); bool bKeysUnderMouse = true; CreateDragOperation( MyGeometry, MouseEvent, bKeysUnderMouse ); } else { // Clear selected keys when beginning to drag a section GetSequencer().GetSelection().EmptySelectedKeys(); HandleSectionSelection( MouseEvent ); bool bKeysUnderMouse = false; CreateDragOperation( MyGeometry, MouseEvent, bKeysUnderMouse ); } if( DragOperation.IsValid() ) { DragOperation->OnBeginDrag(LocalMousePos, ParentSectionArea); } } } else if( DragOperation.IsValid() ) { // Already in a drag, tell all operations to perform their drag implementations FTimeToPixel TimeToPixelConverter = SectionInterface->GetSectionObject()->IsInfinite() ? FTimeToPixel( ParentGeometry, GetSequencer().GetViewRange()) : FTimeToPixel( MyGeometry, TRange<float>( SectionInterface->GetSectionObject()->GetStartTime(), SectionInterface->GetSectionObject()->GetEndTime() ) ); DragOperation->OnDrag( MouseEvent, LocalMousePos, TimeToPixelConverter, ParentSectionArea ); } } return FReply::Handled(); } else { // Not dragging ResetHoveredState(); // Checked for hovered key // @todo Sequencer - Needs visual cue HoveredKey = GetKeyUnderMouse( MouseEvent.GetScreenSpacePosition(), MyGeometry ); // Only check for edge interaction if not hovering over a key if( !HoveredKey.IsValid() ) { CheckForEdgeInteraction( MouseEvent, MyGeometry ); } } return FReply::Unhandled(); }
FReply FSequencerTimeSliderController::OnMouseButtonUp( SWidget& WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { bool bHandleLeftMouseButton = MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && WidgetOwner.HasMouseCapture(); bool bHandleRightMouseButton = MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && WidgetOwner.HasMouseCapture() && TimeSliderArgs.AllowZoom ; if ( bHandleRightMouseButton ) { if (!bPanning) { // Open a context menu if allowed if (ContextMenuSupression == 0 && TimeSliderArgs.PlaybackRange.IsSet()) { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); float MouseValue = RangeToScreen.LocalXToInput( CursorPos.X ); if (TimeSliderArgs.Settings->GetIsSnapEnabled()) { MouseValue = TimeSliderArgs.Settings->SnapTimeToInterval(MouseValue); } TSharedRef<SWidget> MenuContent = OpenSetPlaybackRangeMenu(MouseValue); FSlateApplication::Get().PushMenu( WidgetOwner.AsShared(), MouseEvent.GetEventPath() != nullptr ? *MouseEvent.GetEventPath() : FWidgetPath(), MenuContent, MouseEvent.GetScreenSpacePosition(), FPopupTransitionEffect( FPopupTransitionEffect::ContextMenu ) ); return FReply::Handled().SetUserFocus(MenuContent, EFocusCause::SetDirectly).ReleaseMouseCapture(); } // return unhandled in case our parent wants to use our right mouse button to open a context menu return FReply::Unhandled().ReleaseMouseCapture(); } bPanning = false; return FReply::Handled().ReleaseMouseCapture(); } else if ( bHandleLeftMouseButton ) { if (MouseDragType == DRAG_START_RANGE) { TimeSliderArgs.OnEndPlaybackRangeDrag.ExecuteIfBound(); } // Set the end range time? else if (MouseDragType == DRAG_END_RANGE) { TimeSliderArgs.OnEndPlaybackRangeDrag.ExecuteIfBound(); } else if (MouseDragType == DRAG_SETTING_RANGE) { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); float NewValue = RangeToScreen.LocalXToInput(CursorPos.X); if ( TimeSliderArgs.Settings->GetIsSnapEnabled() ) { NewValue = TimeSliderArgs.Settings->SnapTimeToInterval(NewValue); } float DownValue = MouseDownRange[0]; if ( TimeSliderArgs.Settings->GetIsSnapEnabled() ) { DownValue = TimeSliderArgs.Settings->SnapTimeToInterval(DownValue); } // Zoom in if (NewValue > DownValue) { // push the current value onto the stack RangeStack.Add(FVector2D(TimeSliderArgs.ViewRange.Get().GetLowerBoundValue(), TimeSliderArgs.ViewRange.Get().GetUpperBoundValue())); } // Zoom out else if (RangeStack.Num()) { // pop the stack FVector2D LastRange = RangeStack.Pop(); DownValue = LastRange[0]; NewValue = LastRange[1]; } TimeSliderArgs.OnViewRangeChanged.ExecuteIfBound(TRange<float>(DownValue, NewValue), EViewRangeInterpolation::Immediate); if( !TimeSliderArgs.ViewRange.IsBound() ) { // The output is not bound to a delegate so we'll manage the value ourselves TimeSliderArgs.ViewRange.Set( TRange<float>( DownValue, NewValue ) ); } } else { TimeSliderArgs.OnEndScrubberMovement.ExecuteIfBound(); FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); float NewValue = RangeToScreen.LocalXToInput(CursorPos.X); if ( TimeSliderArgs.Settings->GetIsSnapEnabled() && TimeSliderArgs.Settings->GetSnapPlayTimeToInterval() ) { NewValue = TimeSliderArgs.Settings->SnapTimeToInterval(NewValue); } CommitScrubPosition( NewValue, /*bIsScrubbing=*/false ); } MouseDragType = DRAG_NONE; return FReply::Handled().ReleaseMouseCapture(); } return FReply::Unhandled(); }
/** SWidget interface */ virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { const bool bIsRightMouseButtonDown = MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton ); const bool bIsLeftMouseButtonDown = MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton ); PastePosition = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ); if ( this->HasMouseCapture() ) { const FVector2D CursorDelta = MouseEvent.GetCursorDelta(); // Track how much the mouse moved since the mouse down. TotalMouseDelta += CursorDelta.Size(); if (bIsRightMouseButtonDown) { FReply ReplyState = FReply::Handled(); if( !CursorDelta.IsZero() ) { bShowSoftwareCursor = true; } // Panning and mouse is outside of panel? Pasting should just go to the screen center. PastePosition = PanelCoordToGraphCoord( 0.5 * MyGeometry.Size ); this->bIsPanning = true; ViewOffset -= CursorDelta / GetZoomAmount(); return ReplyState; } else if (bIsLeftMouseButtonDown) { TSharedPtr<SNode> NodeBeingDragged = NodeUnderMousePtr.Pin(); if ( IsEditable.Get() ) { // Update the amount to pan panel UpdateViewOffset(MyGeometry, MouseEvent.GetScreenSpacePosition()); const bool bCursorInDeadZone = TotalMouseDelta <= FSlateApplication::Get().GetDragTriggerDistance(); if ( NodeBeingDragged.IsValid() ) { if ( !bCursorInDeadZone ) { // Note, NodeGrabOffset() comes from the node itself, so it's already scaled correctly. FVector2D AnchorNodeNewPos = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ) - NodeGrabOffset; // Dragging an unselected node automatically selects it. SelectionManager.StartDraggingNode(NodeBeingDragged->GetObjectBeingDisplayed(), MouseEvent); // Move all the selected nodes. { const FVector2D AnchorNodeOldPos = NodeBeingDragged->GetPosition(); const FVector2D DeltaPos = AnchorNodeNewPos - AnchorNodeOldPos; if (DeltaPos.Size() > KINDA_SMALL_NUMBER) { MoveSelectedNodes(NodeBeingDragged, AnchorNodeNewPos); } } } return FReply::Handled(); } } if ( !NodeBeingDragged.IsValid() ) { // We are marquee selecting const FVector2D GraphMousePos = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ); Marquee.Rect.UpdateEndPoint(GraphMousePos); FindNodesAffectedByMarquee( /*out*/ Marquee.AffectedNodes ); return FReply::Handled(); } } } return FReply::Unhandled(); }
FReply SScrubWidget::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { // Bar Dragging if(DraggingBar) { // Update bar if we are dragging FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); FTrackScaleInfo ScaleInfo(ViewInputMin.Get(), ViewInputMax.Get(), 0.f, 0.f, MyGeometry.Size); float NewDataPos = FMath::Clamp( ScaleInfo.LocalXToInput(CursorPos.X), ViewInputMin.Get(), ViewInputMax.Get() ); OnBarDrag.ExecuteIfBound(DraggableBarIndex, NewDataPos); } else { // Update what bar we are hovering over FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); FTrackScaleInfo ScaleInfo(ViewInputMin.Get(), ViewInputMax.Get(), 0.f, 0.f, MyGeometry.Size); DraggableBarIndex = INDEX_NONE; if ( DraggableBars.IsBound() ) { const TArray<float>& DraggableBarsVal = DraggableBars.Get(); for ( int32 I=0; I < DraggableBarsVal.Num(); I++ ) { if( FMath::Abs( ScaleInfo.InputToLocalX(DraggableBarsVal[I]) - CursorPos.X ) < 10 ) { DraggableBarIndex = I; break; } } } } if ( this->HasMouseCapture() ) { if (MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton ) && bPanning) { FTrackScaleInfo ScaleInfo(ViewInputMin.Get(), ViewInputMax.Get(), 0.f, 0.f, MyGeometry.Size); FVector2D ScreenDelta = MouseEvent.GetCursorDelta(); float InputDeltaX = ScreenDelta.X/ScaleInfo.PixelsPerInput; bMouseMovedDuringPanning |= !ScreenDelta.IsNearlyZero(0.001f); float NewViewInputMin = ViewInputMin.Get() - InputDeltaX; float NewViewInputMax = ViewInputMax.Get() - InputDeltaX; // we'd like to keep the range if outside when panning if ( NewViewInputMin < 0.f ) { NewViewInputMin = 0.f; NewViewInputMax = ScaleInfo.ViewInputRange; } else if ( NewViewInputMax > SequenceLength.Get() ) { NewViewInputMax = SequenceLength.Get(); NewViewInputMin = NewViewInputMax - ScaleInfo.ViewInputRange; } OnSetInputViewRange.ExecuteIfBound(NewViewInputMin, NewViewInputMax); } else if (!bDragging) { DistanceDragged += FMath::Abs(MouseEvent.GetCursorDelta().X); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistance() ) { bDragging = true; } if( bDragging ) { OnBeginSliderMovement.ExecuteIfBound(); } } else if (bDragging) { FTrackScaleInfo TimeScaleInfo(ViewInputMin.Get(), ViewInputMax.Get(), 0.f, 0.f, MyGeometry.Size); FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); float NewValue = TimeScaleInfo.LocalXToInput(CursorPos.X); CommitValue( NewValue, true, false ); } return FReply::Handled(); } return FReply::Unhandled(); }
FReply FCanvasSlotExtension::HandleAnchorDragging(const FGeometry& Geometry, const FPointerEvent& Event, EAnchorWidget::Type AnchorType) { if ( bMovingAnchor && !Event.GetCursorDelta().IsZero() ) { float InverseSize = 1.0f / Designer->GetPreviewScale(); for ( FWidgetReference& Selection : SelectionCache ) { UWidget* PreviewWidget = Selection.GetPreview(); if ( UCanvasPanel* Canvas = Cast<UCanvasPanel>(PreviewWidget->GetParent()) ) { UCanvasPanelSlot* PreviewCanvasSlot = Cast<UCanvasPanelSlot>(PreviewWidget->Slot); FGeometry Geometry; if ( Canvas->GetGeometryForSlot(PreviewCanvasSlot, Geometry) ) { FGeometry CanvasGeometry = Canvas->GetCanvasWidget()->GetCachedGeometry(); FVector2D StartLocalPosition = CanvasGeometry.AbsoluteToLocal(MouseDownPosition); FVector2D NewLocalPosition = CanvasGeometry.AbsoluteToLocal(Event.GetScreenSpacePosition()); FVector2D LocalPositionDelta = NewLocalPosition - StartLocalPosition; FVector2D AnchorDelta = LocalPositionDelta / CanvasGeometry.Size; const FAnchorData OldLayoutData = PreviewCanvasSlot->LayoutData; FAnchorData LayoutData = OldLayoutData; switch ( AnchorType ) { case EAnchorWidget::Center: LayoutData.Anchors.Maximum = BeginAnchors.Maximum + AnchorDelta; LayoutData.Anchors.Minimum = BeginAnchors.Minimum + AnchorDelta; LayoutData.Anchors.Minimum.X = FMath::Clamp(LayoutData.Anchors.Minimum.X, 0.0f, 1.0f); LayoutData.Anchors.Maximum.X = FMath::Clamp(LayoutData.Anchors.Maximum.X, 0.0f, 1.0f); LayoutData.Anchors.Minimum.Y = FMath::Clamp(LayoutData.Anchors.Minimum.Y, 0.0f, 1.0f); LayoutData.Anchors.Maximum.Y = FMath::Clamp(LayoutData.Anchors.Maximum.Y, 0.0f, 1.0f); break; } switch ( AnchorType ) { case EAnchorWidget::Left: case EAnchorWidget::TopLeft: case EAnchorWidget::BottomLeft: LayoutData.Anchors.Minimum.X = BeginAnchors.Minimum.X + AnchorDelta.X; LayoutData.Anchors.Minimum.X = FMath::Clamp(LayoutData.Anchors.Minimum.X, 0.0f, LayoutData.Anchors.Maximum.X); break; } switch ( AnchorType ) { case EAnchorWidget::Right: case EAnchorWidget::TopRight: case EAnchorWidget::BottomRight: LayoutData.Anchors.Maximum.X = BeginAnchors.Maximum.X + AnchorDelta.X; LayoutData.Anchors.Maximum.X = FMath::Clamp(LayoutData.Anchors.Maximum.X, LayoutData.Anchors.Minimum.X, 1.0f); break; } switch ( AnchorType ) { case EAnchorWidget::Top: case EAnchorWidget::TopLeft: case EAnchorWidget::TopRight: LayoutData.Anchors.Minimum.Y = BeginAnchors.Minimum.Y + AnchorDelta.Y; LayoutData.Anchors.Minimum.Y = FMath::Clamp(LayoutData.Anchors.Minimum.Y, 0.0f, LayoutData.Anchors.Maximum.Y); break; } switch ( AnchorType ) { case EAnchorWidget::Bottom: case EAnchorWidget::BottomLeft: case EAnchorWidget::BottomRight: LayoutData.Anchors.Maximum.Y = BeginAnchors.Maximum.Y + AnchorDelta.Y; LayoutData.Anchors.Maximum.Y = FMath::Clamp(LayoutData.Anchors.Maximum.Y, LayoutData.Anchors.Minimum.Y, 1.0f); break; } // Major percentage snapping { const float MajorAnchorLine = 0.1f; const float MajorAnchorLineSnapDistance = 0.1f; if ( LayoutData.Anchors.Minimum.X != OldLayoutData.Anchors.Minimum.X ) { ProximitySnapValue(MajorAnchorLine, MajorAnchorLineSnapDistance, LayoutData.Anchors.Minimum.X); } if ( LayoutData.Anchors.Minimum.Y != OldLayoutData.Anchors.Minimum.Y ) { ProximitySnapValue(MajorAnchorLine, MajorAnchorLineSnapDistance, LayoutData.Anchors.Minimum.Y); } if ( LayoutData.Anchors.Maximum.X != OldLayoutData.Anchors.Maximum.X ) { ProximitySnapValue(MajorAnchorLine, MajorAnchorLineSnapDistance, LayoutData.Anchors.Maximum.X); } if ( LayoutData.Anchors.Maximum.Y != OldLayoutData.Anchors.Maximum.Y ) { ProximitySnapValue(MajorAnchorLine, MajorAnchorLineSnapDistance, LayoutData.Anchors.Maximum.Y); } } // Rebase the layout and restore the old value after calculating the new final layout // result. { PreviewCanvasSlot->SaveBaseLayout(); PreviewCanvasSlot->LayoutData = LayoutData; PreviewCanvasSlot->RebaseLayout(); LayoutData = PreviewCanvasSlot->LayoutData; PreviewCanvasSlot->LayoutData = OldLayoutData; } // If control is pressed reset all positional offset information if ( FSlateApplication::Get().GetModifierKeys().IsControlDown() ) { FMargin NewOffsets = FMargin(0, 0, LayoutData.Anchors.IsStretchedHorizontal() ? 0 : LayoutData.Offsets.Right, LayoutData.Anchors.IsStretchedVertical() ? 0 : LayoutData.Offsets.Bottom); LayoutData.Offsets = NewOffsets; } UWidget* TemplateWidget = Selection.GetTemplate(); UCanvasPanelSlot* TemplateCanvasSlot = CastChecked<UCanvasPanelSlot>(TemplateWidget->Slot); static const FName LayoutDataName(TEXT("LayoutData")); FObjectEditorUtils::SetPropertyValue<UCanvasPanelSlot, FAnchorData>(PreviewCanvasSlot, LayoutDataName, LayoutData); FObjectEditorUtils::SetPropertyValue<UCanvasPanelSlot, FAnchorData>(TemplateCanvasSlot, LayoutDataName, LayoutData); } }; return FReply::Handled(); } } return FReply::Unhandled(); }