FReply STrack::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if (bDraggingBar && OnBarDrag.IsBound()) { /** Update drag bar position if we are dragging */ FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); float NewDataPos = FMath::Clamp( LocalToDataX(CursorPos.X, MyGeometry), TrackMinValue.Get(), TrackMaxValue.Get() ); OnBarDrag.Execute(DraggableBarIndex, NewDataPos); } else if(DraggableBars.IsBound()) { /** Update what bar is draggable if we arent already dragging */ UpdateDraggableBarIndex(MyGeometry, MouseEvent.GetScreenSpacePosition()); } return FReply::Unhandled(); }
// drag drop relationship FReply STrack::OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) { FVector2D CursorPos = MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()); float CusorDataPos = LocalToDataX(CursorPos.X, MyGeometry); // Handle TrackNodes that were dropped if ( DragDrop::IsTypeMatch<FTrackNodeDragDropOp>( DragDropEvent.GetOperation() ) ) { TSharedPtr<FTrackNodeDragDropOp> DragDropOp = StaticCastSharedPtr<FTrackNodeDragDropOp>(DragDropEvent.GetOperation()); TSharedPtr<STrackNode> TrackNode = DragDropOp->OriginalTrackNode.Pin(); float DataPos = GetNodeDragDropDataPos(MyGeometry, DragDropEvent); TrackNode->OnTrackNodeDragged.ExecuteIfBound( DataPos ); TrackNode->OnTrackNodeDropped.ExecuteIfBound(); } // Call delegate to handle anything else OnTrackDragDrop.ExecuteIfBound( DragDropEvent.GetOperation(), CusorDataPos ); return FReply::Unhandled(); }
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<SWidget> MenuContent; if(SummonedContextMenu) { MenuContent = MenuBuilder.MakeWidget(); FWidgetPath WidgetPath = MouseEvent.GetEventPath() != nullptr ? *MouseEvent.GetEventPath() : FWidgetPath(); FSlateApplication::Get().PushMenu(SharedThis(this), WidgetPath, MenuContent.ToSharedRef(), CursorPos, FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)); } return MenuContent; }
float STrack::GetSnappedPosForLocalPos( const FGeometry& MyGeometry, float TrackPos) const { float SnapPos = LocalToDataX(TrackPos, MyGeometry); if ( DraggableBars.IsBound() ) { float BestDist = 10.f; for (auto SnapIter = DraggableBars.Get().CreateConstIterator(); SnapIter; ++SnapIter) { // Snap in screen space - not sure if this is best but seems right since its a hardcoded value atm float ScreenDist = FMath::Abs(TrackPos - DataToLocalX( *SnapIter, MyGeometry )); if ( ScreenDist < BestDist ) { BestDist = ScreenDist; SnapPos = *SnapIter; } } } return SnapPos; }
float STrack::GetNodeDragDropDataPos( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) { float DataPos = 0.f; TSharedPtr<FTrackNodeDragDropOp> DragDropOp = StaticCastSharedPtr<FTrackNodeDragDropOp>(DragDropEvent.GetOperation()); if(DragDropOp.IsValid()) { TSharedPtr<STrackNode> TrackNode = DragDropOp->OriginalTrackNode.Pin(); if(TrackNode.IsValid()) { FVector2D CursorPos = MyGeometry.AbsoluteToLocal(TrackNode->GetDragDropScreenSpacePosition(MyGeometry, DragDropEvent)); DataPos = LocalToDataX(CursorPos.X, MyGeometry); if(TrackNode->SnapToDragBars()) { float OriginalX = DataPos; DataPos = GetSnappedPosForLocalPos(MyGeometry, CursorPos.X); TrackNode->OnSnapNodeDataPosition(OriginalX, DataPos); } } } return DataPos; }