int32 FSequencerTimeSliderController::OnPaintTimeSlider( bool bMirrorLabels, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { const bool bEnabled = bParentEnabled; const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); const float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); const float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); const float LocalSequenceLength = LocalViewRangeMax-LocalViewRangeMin; FVector2D Scale = FVector2D(1.0f,1.0f); if ( LocalSequenceLength > 0) { FScrubRangeToScreen RangeToScreen( LocalViewRange, AllottedGeometry.Size ); const float MajorTickHeight = 9.0f; FDrawTickArgs Args; Args.AllottedGeometry = AllottedGeometry; Args.bMirrorLabels = bMirrorLabels; Args.bOnlyDrawMajorTicks = false; Args.TickColor = FLinearColor::White; Args.ClippingRect = MyClippingRect; Args.DrawEffects = DrawEffects; Args.StartLayer = LayerId; Args.TickOffset = bMirrorLabels ? 0.0f : FMath::Abs( AllottedGeometry.Size.Y - MajorTickHeight ); Args.MajorTickHeight = MajorTickHeight; DrawTicks( OutDrawElements, RangeToScreen, Args ); const float HandleSize = 13.0f; float HalfSize = FMath::TruncToFloat(HandleSize/2.0f); // Draw the scrub handle const float XPos = RangeToScreen.InputToLocalX( TimeSliderArgs.ScrubPosition.Get() ); // Should draw above the text const int32 ArrowLayer = LayerId + 2; FPaintGeometry MyGeometry = AllottedGeometry.ToPaintGeometry( FVector2D( XPos-HalfSize, 0 ), FVector2D( HandleSize, AllottedGeometry.Size.Y ) ); FLinearColor ScrubColor = InWidgetStyle.GetColorAndOpacityTint(); // @todo Sequencer this color should be specified in the style ScrubColor.A = ScrubColor.A*0.5f; ScrubColor.B *= 0.1f; ScrubColor.G *= 0.2f; FSlateDrawElement::MakeBox( OutDrawElements, ArrowLayer, MyGeometry, bMirrorLabels ? ScrubHandleUp : ScrubHandleDown, MyClippingRect, DrawEffects, ScrubColor ); return ArrowLayer; } return LayerId; }
int32 FSequencerTimeSliderController::OnPaintSectionView( const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, bool bEnabled, bool bDisplayTickLines, bool bDisplayScrubPosition ) const { const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); float LocalScrubPosition = TimeSliderArgs.ScrubPosition.Get(); float ViewRange = LocalViewRange.Size<float>(); float PixelsPerInput = ViewRange > 0 ? AllottedGeometry.Size.X / ViewRange : 0; float LinePos = (LocalScrubPosition - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput; FScrubRangeToScreen RangeToScreen( LocalViewRange, AllottedGeometry.Size ); if( bDisplayTickLines ) { // Draw major tick lines in the section area FDrawTickArgs Args; Args.AllottedGeometry = AllottedGeometry; Args.bMirrorLabels = false; Args.bOnlyDrawMajorTicks = true; Args.TickColor = FLinearColor( 0.3f, 0.3f, 0.3f, 0.3f ); Args.ClippingRect = MyClippingRect; Args.DrawEffects = DrawEffects; // Draw major ticks under sections Args.StartLayer = LayerId-1; // Draw the tick the entire height of the section area Args.TickOffset = 0.0f; Args.MajorTickHeight = AllottedGeometry.Size.Y; DrawTicks( OutDrawElements, RangeToScreen, Args ); } if( bDisplayScrubPosition ) { // Draw a line for the scrub position TArray<FVector2D> LinePoints; LinePoints.AddUninitialized(2); LinePoints[0] = FVector2D( 1.0f, 0.0f ); LinePoints[1] = FVector2D( 1.0f, FMath::RoundToFloat( AllottedGeometry.Size.Y ) ); FSlateDrawElement::MakeLines( OutDrawElements, LayerId+1, AllottedGeometry.ToPaintGeometry( FVector2D(LinePos, 0.0f ), FVector2D(1.0f,1.0f) ), LinePoints, MyClippingRect, DrawEffects, FLinearColor::White, false ); } return LayerId; }
FReply FSequencerTimeSliderController::OnMouseButtonUp( TSharedRef<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) { // 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( bDraggingScrubber ) { TimeSliderArgs.OnEndScrubberMovement.ExecuteIfBound(); } else { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); float NewValue = RangeToScreen.LocalXToInput(CursorPos.X); const USequencerSnapSettings* SnapSettings = GetDefault<USequencerSnapSettings>(); if ( SnapSettings->GetIsSnapEnabled() && SnapSettings->GetSnapPlayTimeToInterval() ) { NewValue = SnapSettings->SnapToInterval( NewValue ); } CommitScrubPosition( NewValue, /*bIsScrubbing=*/false ); } bDraggingScrubber = false; return FReply::Handled().ReleaseMouseCapture(); } return FReply::Unhandled(); }
FCursorReply FSequencerTimeSliderController::OnCursorQuery( TSharedRef<const SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& CursorEvent ) const { FScrubRangeToScreen RangeToScreen(TimeSliderArgs.ViewRange.Get(), MyGeometry.Size); TRange<float> PlaybackRange = TimeSliderArgs.PlaybackRange.Get(); const float ScrubPosition = TimeSliderArgs.ScrubPosition.Get(); // Use L/R resize cursor if we're dragging or hovering a playback range bound float HitTestPosition = MyGeometry.AbsoluteToLocal(CursorEvent.GetScreenSpacePosition()).X; if (MouseDragType == DRAG_END_RANGE || MouseDragType == DRAG_START_RANGE || HitTestPlaybackStart(RangeToScreen, PlaybackRange, HitTestPosition, ScrubPosition) || HitTestPlaybackEnd(RangeToScreen, PlaybackRange, HitTestPosition, ScrubPosition) ) { return FCursorReply::Cursor(EMouseCursor::ResizeLeftRight); } return FCursorReply::Unhandled(); }
FReply FVisualLoggerTimeSliderController::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) { // return unhandled in case our parent wants to use our right mouse button to open a context menu return FReply::Unhandled().ReleaseMouseCapture(); } bPanning = false; FReply::Handled().CaptureMouse(WidgetOwner.AsShared()).UseHighPrecisionMouseMovement(WidgetOwner.AsShared()); return FReply::Handled().ReleaseMouseCapture(); } else if ( bHandleLeftMouseButton ) { if( bDraggingScrubber ) { TimeSliderArgs.OnEndScrubberMovement.ExecuteIfBound(); } else { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); float NewValue = RangeToScreen.LocalXToInput(CursorPos.X); CommitScrubPosition( NewValue, /*bIsScrubbing=*/false ); } bDraggingScrubber = false; return FReply::Handled().ReleaseMouseCapture(); } return FReply::Unhandled(); }
FReply FSequencerTimeSliderController::OnMouseButtonDown( SWidget& WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { bool bHandleLeftMouseButton = MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton; bool bHandleRightMouseButton = MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && TimeSliderArgs.AllowZoom; DistanceDragged = 0; FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); MouseDownRange[0] = RangeToScreen.LocalXToInput(MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()).X); MouseDownRange[1] = MouseDownRange[0]; if ( bHandleLeftMouseButton ) { return FReply::Handled().CaptureMouse( WidgetOwner.AsShared() ).PreventThrottling(); } else if ( bHandleRightMouseButton ) { // Always capture mouse if we left or right click on the widget return FReply::Handled().CaptureMouse( WidgetOwner.AsShared() ); } return FReply::Unhandled(); }
FReply FVisualLoggerTimeSliderController::OnMouseButtonDown( TSharedRef<SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { bool bHandleLeftMouseButton = MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton; bool bHandleRightMouseButton = MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && TimeSliderArgs.AllowZoom; DistanceDragged = 0; if ( bHandleLeftMouseButton ) { // Always capture mouse if we left or right click on the widget FScrubRangeToScreen RangeToScreen(TimeSliderArgs.ViewRange.Get(), MyGeometry.Size); FVector2D CursorPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); float NewValue = RangeToScreen.LocalXToInput(CursorPos.X); CommitScrubPosition(NewValue, /*bIsScrubbing=*/false); return FReply::Handled().CaptureMouse( WidgetOwner ).PreventThrottling(); } else if ( bHandleRightMouseButton ) { return FReply::Handled().CaptureMouse(WidgetOwner); } return FReply::Unhandled(); }
FReply FSequencerTimeSliderController::OnMouseMove( SWidget& WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if ( WidgetOwner.HasMouseCapture() ) { if (MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton )) { if (!bPanning) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistance() ) { bPanning = true; } } else { TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); FScrubRangeToScreen ScaleInfo( LocalViewRange, MyGeometry.Size ); FVector2D ScreenDelta = MouseEvent.GetCursorDelta(); FVector2D InputDelta; InputDelta.X = ScreenDelta.X/ScaleInfo.PixelsPerInput; float NewViewOutputMin = LocalViewRangeMin - InputDelta.X; float NewViewOutputMax = LocalViewRangeMax - InputDelta.X; ClampViewRange(NewViewOutputMin, NewViewOutputMax); SetViewRange(NewViewOutputMin, NewViewOutputMax, EViewRangeInterpolation::Immediate); } } else if (MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton )) { TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( MouseDragType == DRAG_NONE ) { if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistance() ) { FScrubRangeToScreen RangeToScreen(LocalViewRange, MyGeometry.Size); const float ScrubPosition = TimeSliderArgs.ScrubPosition.Get(); TRange<float> PlaybackRange = TimeSliderArgs.PlaybackRange.Get(); float LocalMouseDownPos = RangeToScreen.InputToLocalX(MouseDownRange[0]); // Favor dragging the end position if (HitTestPlaybackEnd(RangeToScreen, PlaybackRange, LocalMouseDownPos, ScrubPosition)) { MouseDragType = DRAG_END_RANGE; TimeSliderArgs.OnBeginPlaybackRangeDrag.ExecuteIfBound(); } else if (HitTestPlaybackStart(RangeToScreen, PlaybackRange, LocalMouseDownPos, ScrubPosition)) { MouseDragType = DRAG_START_RANGE; TimeSliderArgs.OnBeginPlaybackRangeDrag.ExecuteIfBound(); } else if (FSlateApplication::Get().GetModifierKeys().AreModifersDown(EModifierKey::Control)) { MouseDragType = DRAG_SETTING_RANGE; } else { MouseDragType = DRAG_SCRUBBING_TIME; TimeSliderArgs.OnBeginScrubberMovement.ExecuteIfBound(); } } } else { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetLastScreenSpacePosition() ); float NewValue = RangeToScreen.LocalXToInput( CursorPos.X ); // Set the start range time? if (MouseDragType == DRAG_START_RANGE) { if (TimeSliderArgs.Settings->GetIsSnapEnabled()) { NewValue = TimeSliderArgs.Settings->SnapTimeToInterval(NewValue); } SetPlaybackRangeStart(NewValue); } // Set the end range time? else if(MouseDragType == DRAG_END_RANGE) { if (TimeSliderArgs.Settings->GetIsSnapEnabled()) { NewValue = TimeSliderArgs.Settings->SnapTimeToInterval(NewValue); } SetPlaybackRangeEnd(NewValue); } else if (MouseDragType == DRAG_SCRUBBING_TIME) { if ( TimeSliderArgs.Settings->GetIsSnapEnabled() && TimeSliderArgs.Settings->GetSnapPlayTimeToInterval() ) { NewValue = TimeSliderArgs.Settings->SnapTimeToInterval(NewValue); } // Delegate responsibility for clamping to the current viewrange to the client CommitScrubPosition( NewValue, /*bIsScrubbing=*/true ); } else if (MouseDragType == DRAG_SETTING_RANGE) { MouseDownRange[1] = NewValue; } } } return FReply::Handled(); } 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(); }
int32 FSequencerTimeSliderController::OnPaintTimeSlider( bool bMirrorLabels, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { const bool bEnabled = bParentEnabled; const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); const float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); const float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); const float LocalSequenceLength = LocalViewRangeMax-LocalViewRangeMin; FVector2D Scale = FVector2D(1.0f,1.0f); if ( LocalSequenceLength > 0) { FScrubRangeToScreen RangeToScreen( LocalViewRange, AllottedGeometry.Size ); const float MajorTickHeight = 9.0f; FDrawTickArgs Args; Args.AllottedGeometry = AllottedGeometry; Args.bMirrorLabels = bMirrorLabels; Args.bOnlyDrawMajorTicks = false; Args.TickColor = FLinearColor::White; Args.ClippingRect = MyClippingRect; Args.DrawEffects = DrawEffects; Args.StartLayer = LayerId; Args.TickOffset = bMirrorLabels ? 0.0f : FMath::Abs( AllottedGeometry.Size.Y - MajorTickHeight ); Args.MajorTickHeight = MajorTickHeight; DrawTicks( OutDrawElements, RangeToScreen, Args ); FPaintPlaybackRangeArgs PlaybackRangeArgs( bMirrorLabels ? FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_Bottom_L") : FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_Top_L"), bMirrorLabels ? FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_Bottom_R") : FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_Top_R"), 6.f ); LayerId = DrawPlaybackRange(AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, RangeToScreen, PlaybackRangeArgs); float HalfSize = FMath::CeilToFloat(ScrubHandleSize/2.0f); // Draw the scrub handle float XPos = RangeToScreen.InputToLocalX( TimeSliderArgs.ScrubPosition.Get() ); // Should draw above the text const int32 ArrowLayer = LayerId + 2; FPaintGeometry MyGeometry = AllottedGeometry.ToPaintGeometry( FVector2D( XPos-HalfSize, 0 ), FVector2D( ScrubHandleSize, AllottedGeometry.Size.Y ) ); FLinearColor ScrubColor = InWidgetStyle.GetColorAndOpacityTint(); // @todo Sequencer this color should be specified in the style ScrubColor.A = ScrubColor.A*0.75f; ScrubColor.B *= 0.1f; ScrubColor.G *= 0.2f; FSlateDrawElement::MakeBox( OutDrawElements, ArrowLayer, MyGeometry, bMirrorLabels ? ScrubHandleUp : ScrubHandleDown, MyClippingRect, DrawEffects, ScrubColor ); // Draw the current time next to the scrub handle float Time = TimeSliderArgs.ScrubPosition.Get(); FString FrameString; if (SequencerSnapValues::IsTimeSnapIntervalFrameRate(TimeSliderArgs.Settings->GetTimeSnapInterval()) && TimeSliderArgs.Settings->GetShowFrameNumbers()) { float FrameRate = 1.0f/TimeSliderArgs.Settings->GetTimeSnapInterval(); float FrameTime = Time * FrameRate; int32 Frame = SequencerHelpers::TimeToFrame(Time, FrameRate); const float FrameTolerance = 0.001f; if (FMath::IsNearlyEqual(FrameTime, (float)Frame, FrameTolerance)) { FrameString = FString::Printf( TEXT("%d"), TimeToFrame(Time)); } else { FrameString = FString::Printf( TEXT("%.3f"), FrameTime); } } else { FrameString = FString::Printf( TEXT("%.2f"), Time ); } FSlateFontInfo SmallLayoutFont( FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Regular.ttf"), 10 ); const TSharedRef< FSlateFontMeasure > FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService(); FVector2D TextSize = FontMeasureService->Measure(FrameString, SmallLayoutFont); // Flip the text position if getting near the end of the view range if ((AllottedGeometry.Size.X - XPos) < (TextSize.X + 14.f)) { XPos = XPos - TextSize.X - 12.f; } else { XPos = XPos + 10.f; } FVector2D TextOffset( XPos, Args.bMirrorLabels ? TextSize.Y-6.f : Args.AllottedGeometry.Size.Y - (Args.MajorTickHeight+TextSize.Y) ); FSlateDrawElement::MakeText( OutDrawElements, Args.StartLayer+1, Args.AllottedGeometry.ToPaintGeometry( TextOffset, TextSize ), FrameString, SmallLayoutFont, Args.ClippingRect, Args.DrawEffects, Args.TickColor ); if (MouseDragType == DRAG_SETTING_RANGE) { float MouseStartPosX = RangeToScreen.InputToLocalX(MouseDownRange[0]); float MouseEndPosX = RangeToScreen.InputToLocalX(MouseDownRange[1]); float RangePosX = MouseStartPosX < MouseEndPosX ? MouseStartPosX : MouseEndPosX; float RangeSizeX = FMath::Abs(MouseStartPosX - MouseEndPosX); FSlateDrawElement::MakeBox( OutDrawElements, LayerId+1, AllottedGeometry.ToPaintGeometry( FVector2D(RangePosX, 0.f), FVector2D(RangeSizeX, AllottedGeometry.Size.Y) ), bMirrorLabels ? ScrubHandleDown : ScrubHandleUp, MyClippingRect, DrawEffects, MouseStartPosX < MouseEndPosX ? FLinearColor(0.5f, 0.5f, 0.5f) : FLinearColor(0.25f, 0.3f, 0.3f) ); } return ArrowLayer; } return LayerId; }
FReply FVisualLoggerTimeSliderController::OnMouseMove( TSharedRef<SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if ( WidgetOwner->HasMouseCapture() ) { if (MouseEvent.IsMouseButtonDown(EKeys::RightMouseButton)) { if (!bPanning) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistance() ) { FReply::Handled().CaptureMouse(WidgetOwner).UseHighPrecisionMouseMovement(WidgetOwner); SoftwareCursorPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); bPanning = true; } } else { SoftwareCursorPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetLastScreenSpacePosition()); TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); FScrubRangeToScreen ScaleInfo( LocalViewRange, MyGeometry.Size ); FVector2D ScreenDelta = MouseEvent.GetCursorDelta(); FVector2D InputDelta; InputDelta.X = ScreenDelta.X/ScaleInfo.PixelsPerInput; float NewViewOutputMin = LocalViewRangeMin - InputDelta.X; float NewViewOutputMax = LocalViewRangeMax - InputDelta.X; float LocalClampMin = TimeSliderArgs.ClampRange.Get().GetLowerBoundValue(); float LocalClampMax = TimeSliderArgs.ClampRange.Get().GetUpperBoundValue(); // Clamp the range if ( NewViewOutputMin < LocalClampMin ) { NewViewOutputMin = LocalClampMin; } if ( NewViewOutputMax > LocalClampMax ) { NewViewOutputMax = LocalClampMax; } TimeSliderArgs.OnViewRangeChanged.ExecuteIfBound(TRange<float>(NewViewOutputMin, NewViewOutputMax), EViewRangeInterpolation::Immediate, false); if (Scrollbar.IsValid()) { float InOffsetFraction = (NewViewOutputMin - LocalClampMin) / (LocalClampMax - LocalClampMin); float InThumbSizeFraction = (NewViewOutputMax - NewViewOutputMin) / (LocalClampMax - LocalClampMin); Scrollbar->SetState(InOffsetFraction, InThumbSizeFraction); } if( !TimeSliderArgs.ViewRange.IsBound() ) { // The output is not bound to a delegate so we'll manage the value ourselves TimeSliderArgs.ViewRange.Set( TRange<float>( NewViewOutputMin, NewViewOutputMax ) ); } } } else if (MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton )) { if ( !bDraggingScrubber ) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > 0/*FSlateApplication::Get().GetDragTriggerDistance()*/ ) { bDraggingScrubber = true; TimeSliderArgs.OnBeginScrubberMovement.ExecuteIfBound(); } } else { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetLastScreenSpacePosition() ); float NewValue = RangeToScreen.LocalXToInput( CursorPos.X ); float LocalClampMin = TimeSliderArgs.ClampRange.Get().GetLowerBoundValue(); float LocalClampMax = TimeSliderArgs.ClampRange.Get().GetUpperBoundValue(); if (NewValue < LocalClampMin) { NewValue = LocalClampMin; } if (NewValue > LocalClampMax) { NewValue = LocalClampMax; } CommitScrubPosition(NewValue, /*bIsScrubbing=*/true); } } return FReply::Handled(); } return FReply::Unhandled(); }
FReply FSequencerTimeSliderController::OnMouseMove( TSharedRef<SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if ( WidgetOwner->HasMouseCapture() ) { if (MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton )) { if (!bPanning) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistnace() ) { bPanning = true; } } else { TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); FScrubRangeToScreen ScaleInfo( LocalViewRange, MyGeometry.Size ); FVector2D ScreenDelta = MouseEvent.GetCursorDelta(); FVector2D InputDelta; InputDelta.X = ScreenDelta.X/ScaleInfo.PixelsPerInput; float NewViewOutputMin = LocalViewRangeMin - InputDelta.X; float NewViewOutputMax = LocalViewRangeMax - InputDelta.X; TOptional<float> LocalClampMin = TimeSliderArgs.ClampMin.Get(); TOptional<float> LocalClampMax = TimeSliderArgs.ClampMax.Get(); // Clamp the range if clamp values are set if ( LocalClampMin.IsSet() && NewViewOutputMin < LocalClampMin.GetValue() ) { NewViewOutputMin = LocalClampMin.GetValue(); } if ( LocalClampMax.IsSet() && NewViewOutputMax > LocalClampMax.GetValue() ) { NewViewOutputMax = LocalClampMax.GetValue(); } TimeSliderArgs.OnViewRangeChanged.ExecuteIfBound(TRange<float>(NewViewOutputMin, NewViewOutputMax)); if( !TimeSliderArgs.ViewRange.IsBound() ) { // The output is not bound to a delegate so we'll manage the value ourselves TimeSliderArgs.ViewRange.Set( TRange<float>( NewViewOutputMin, NewViewOutputMax ) ); } } } else if (MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton )) { if ( !bDraggingScrubber ) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistnace() ) { bDraggingScrubber = true; TimeSliderArgs.OnBeginScrubberMovement.ExecuteIfBound(); } } else { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetLastScreenSpacePosition() ); float NewValue = RangeToScreen.LocalXToInput( CursorPos.X ); const USequencerSnapSettings* SnapSettings = GetDefault<USequencerSnapSettings>(); if ( SnapSettings->GetIsSnapEnabled() && SnapSettings->GetSnapPlayTimeToInterval() ) { NewValue = SnapSettings->SnapToInterval(NewValue); } CommitScrubPosition( NewValue, /*bIsScrubbing=*/true ); } } return FReply::Handled(); } return FReply::Unhandled(); }
FReply FSequencerTimeSliderController::OnMouseMove( TSharedRef<SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if ( WidgetOwner->HasMouseCapture() ) { if (MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton )) { if (!bPanning) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistance() ) { bPanning = true; } } else { TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); FScrubRangeToScreen ScaleInfo( LocalViewRange, MyGeometry.Size ); FVector2D ScreenDelta = MouseEvent.GetCursorDelta(); FVector2D InputDelta; InputDelta.X = ScreenDelta.X/ScaleInfo.PixelsPerInput; float NewViewOutputMin = LocalViewRangeMin - InputDelta.X; float NewViewOutputMax = LocalViewRangeMax - InputDelta.X; SetViewRange(NewViewOutputMin, NewViewOutputMax, EViewRangeInterpolation::Immediate); } } else if (MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton )) { if ( !bDraggingScrubber ) { DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X ); if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistance() ) { bDraggingScrubber = true; TimeSliderArgs.OnBeginScrubberMovement.ExecuteIfBound(); } } else { FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size ); FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetLastScreenSpacePosition() ); float NewValue = RangeToScreen.LocalXToInput( CursorPos.X ); const USequencerSettings* Settings = GetDefault<USequencerSettings>(); if ( Settings->GetIsSnapEnabled() && Settings->GetSnapPlayTimeToInterval() ) { NewValue = Settings->SnapTimeToInterval(NewValue); } CommitScrubPosition( NewValue, /*bIsScrubbing=*/true ); } } return FReply::Handled(); } return FReply::Unhandled(); }