FSelectedKey SSection::GetKeyUnderMouse( const FVector2D& MousePosition, const FGeometry& AllottedGeometry ) const { UMovieSceneSection& Section = *SectionInterface->GetSectionObject(); // Search every key area until we find the one under the mouse for( int32 KeyAreaIndex = 0; KeyAreaIndex < KeyAreas.Num(); ++KeyAreaIndex ) { const FKeyAreaElement& Element = KeyAreas[KeyAreaIndex]; TSharedRef<IKeyArea> KeyArea = Element.KeyAreaNode.GetKeyArea( SectionIndex ); // Compute the current key area geometry FGeometry KeyAreaGeometryPadded = GetKeyAreaGeometry( Element, AllottedGeometry ); // Is the key area under the mouse if( KeyAreaGeometryPadded.IsUnderLocation( MousePosition ) ) { FGeometry SectionGeometry = AllottedGeometry.MakeChild(FVector2D(SequencerSectionConstants::SectionGripSize, 0), AllottedGeometry.GetDrawSize() - FVector2D(SequencerSectionConstants::SectionGripSize*2, 0.0f)); FGeometry KeyAreaGeometry = GetKeyAreaGeometry( Element, SectionGeometry ); FVector2D LocalSpaceMousePosition = KeyAreaGeometry.AbsoluteToLocal( MousePosition ); FTimeToPixel TimeToPixelConverter = Section.IsInfinite() ? FTimeToPixel( ParentGeometry, GetSequencer().GetViewRange()) : FTimeToPixel( KeyAreaGeometry, TRange<float>( Section.GetStartTime(), Section.GetEndTime() ) ); // Check each key until we find one under the mouse (if any) TArray<FKeyHandle> KeyHandles = KeyArea->GetUnsortedKeyHandles(); for( int32 KeyIndex = 0; KeyIndex < KeyHandles.Num(); ++KeyIndex ) { FKeyHandle KeyHandle = KeyHandles[KeyIndex]; float KeyPosition = TimeToPixelConverter.TimeToPixel( KeyArea->GetKeyTime(KeyHandle) ); FGeometry KeyGeometry = KeyAreaGeometry.MakeChild( FVector2D( KeyPosition - FMath::TruncToFloat(SequencerSectionConstants::KeySize.X/2.0f), ((KeyAreaGeometry.Size.Y*.5f)-(SequencerSectionConstants::KeySize.Y*.5f)) ), SequencerSectionConstants::KeySize ); if( KeyGeometry.IsUnderLocation( MousePosition ) ) { // The current key is under the mouse return FSelectedKey( Section, KeyArea, KeyHandle ); } } // no key was selected in the current key area but the mouse is in the key area so it cannot possibly be in any other key area return FSelectedKey(); } } // No key was selected in any key area return FSelectedKey(); }
virtual int32 OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const override { float Alpha = Sequencer.Pin()->GetOverlayFadeCurve(); if (Alpha > 0.f) { FTimeToPixel TimeToPixelConverter = FTimeToPixel(AllottedGeometry, ViewRange.Get()); TRange<float> TimeBounds = TRange<float>(TimeToPixelConverter.PixelToTime(0), TimeToPixelConverter.PixelToTime(AllottedGeometry.Size.X)); TArray< TRange<float> > OverlayRanges = ComputeOverlayRanges(TimeBounds, CachedFilteredRanges); for (int32 i = 0; i < OverlayRanges.Num(); ++i) { float LowerBound = TimeToPixelConverter.TimeToPixel(OverlayRanges[i].GetLowerBoundValue()); float UpperBound = TimeToPixelConverter.TimeToPixel(OverlayRanges[i].GetUpperBoundValue()); FSlateDrawElement::MakeBox( OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(FVector2D(LowerBound, 0), FVector2D(UpperBound - LowerBound, AllottedGeometry.Size.Y)), FEditorStyle::GetBrush("Sequencer.ShotFilter"), MyClippingRect, ESlateDrawEffect::None, FLinearColor(1.f, 1.f, 1.f, Alpha) ); } } return LayerId; }
FTimeToPixel SSequencerSectionAreaView::GetTimeToPixel( const FGeometry& AllottedGeometry ) const { return FTimeToPixel( AllottedGeometry, ViewRange.Get() ); }
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(); }
void SSection::PaintKeys( const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle ) const { UMovieSceneSection& SectionObject = *SectionInterface->GetSectionObject(); FSequencer& Sequencer = ParentSectionArea->GetSequencer(); static const FName BackgroundBrushName("Sequencer.SectionArea.Background"); static const FName KeyBrushName("Sequencer.Key"); const FSlateBrush* BackgroundBrush = FEditorStyle::GetBrush(BackgroundBrushName); const FSlateBrush* KeyBrush = FEditorStyle::GetBrush(KeyBrushName); static const FName SelectionColorName("SelectionColor"); static const FName SelectionInactiveColorName("SelectionColorInactive"); static const FName SelectionColorPressedName("SelectionColor_Pressed"); const FLinearColor PressedKeyColor = FEditorStyle::GetSlateColor(SelectionColorPressedName).GetColor( InWidgetStyle ); const FLinearColor SelectedKeyColor = FEditorStyle::GetSlateColor(SelectionColorName).GetColor( InWidgetStyle ); const FLinearColor SelectedInactiveColor = FEditorStyle::GetSlateColor(SelectionInactiveColorName).GetColor( InWidgetStyle ) * FLinearColor(.25, .25, .25, 1); // Make the color a little darker since it's not very visible next to white keyframes. // @todo Sequencer temp color, make hovered brighter than selected. FLinearColor HoveredKeyColor = SelectedKeyColor * FLinearColor(1.5,1.5,1.5,1.0f); // Draw all keys in each key area for( int32 KeyAreaIndex = 0; KeyAreaIndex < KeyAreas.Num(); ++KeyAreaIndex ) { const FKeyAreaElement& Element = KeyAreas[KeyAreaIndex]; // Get the key area at the same index of the section. Each section in this widget has the same layout and the same number of key areas const TSharedRef<IKeyArea>& KeyArea = Element.KeyAreaNode.GetKeyArea( SectionIndex ); FGeometry KeyAreaGeometry = GetKeyAreaGeometry( Element, AllottedGeometry ); FTimeToPixel TimeToPixelConverter = SectionObject.IsInfinite() ? FTimeToPixel( ParentGeometry, GetSequencer().GetViewRange()) : FTimeToPixel( KeyAreaGeometry, TRange<float>( SectionObject.GetStartTime(), SectionObject.GetEndTime() ) ); // Draw a box for the key area // @todo Sequencer - Allow the IKeyArea to do this FSlateDrawElement::MakeBox( OutDrawElements, LayerId, KeyAreaGeometry.ToPaintGeometry(), BackgroundBrush, MyClippingRect, ESlateDrawEffect::None, FLinearColor( .1f, .1f, .1f, 0.7f ) ); int32 KeyLayer = LayerId + 1; TArray<FKeyHandle> KeyHandles = KeyArea->GetUnsortedKeyHandles(); for( int32 KeyIndex = 0; KeyIndex < KeyHandles.Num(); ++KeyIndex ) { FKeyHandle KeyHandle = KeyHandles[KeyIndex]; float KeyTime = KeyArea->GetKeyTime(KeyHandle); // Omit keys which would not be visible if( SectionObject.IsTimeWithinSection( KeyTime ) ) { FLinearColor KeyColor( 1.0f, 1.0f, 1.0f, 1.0f ); // Where to start drawing the key (relative to the section) float KeyPosition = TimeToPixelConverter.TimeToPixel( KeyTime ); FSelectedKey TestKey( SectionObject, KeyArea, KeyHandle ); bool bSelected = Sequencer.GetSelection().IsSelected( TestKey ); bool bActive = Sequencer.GetSelection().GetActiveSelection() == FSequencerSelection::EActiveSelection::KeyAndSection; if( TestKey == PressedKey ) { KeyColor = PressedKeyColor; } else if( TestKey == HoveredKey ) { KeyColor = HoveredKeyColor; } else if( bSelected ) { if (bActive) { KeyColor = SelectedKeyColor; } else { KeyColor = SelectedInactiveColor; } } // Draw the key FSlateDrawElement::MakeBox( OutDrawElements, // always draw selected keys on top of other keys bSelected ? KeyLayer+1 : KeyLayer, // Center the key along Y. Ensure the middle of the key is at the actual key time KeyAreaGeometry.ToPaintGeometry( FVector2D( KeyPosition - FMath::CeilToFloat(SequencerSectionConstants::KeySize.X/2.0f), ((KeyAreaGeometry.Size.Y*.5f)-(SequencerSectionConstants::KeySize.Y*.5f)) ), SequencerSectionConstants::KeySize ), KeyBrush, MyClippingRect, ESlateDrawEffect::None, KeyColor ); } } } }