/** * Gets the geometry of a section, optionally inflated by some margin * * @param AllottedGeometry The geometry of the area where sections are located * @param NodeHeight The height of the section area (and its children) * @param SectionInterface Interface to the section to get geometry for * @param TimeToPixelConverter Converts time to pixels and vice versa */ FGeometry GetSectionGeometry( const FGeometry& AllottedGeometry, int32 RowIndex, int32 MaxTracks, float NodeHeight, TSharedPtr<ISequencerSection> SectionInterface, const FTimeToPixel& TimeToPixelConverter ) { const UMovieSceneSection* Section = SectionInterface->GetSectionObject(); float StartX, EndX = 0; // If the section is infinite, occupy the entire width of the geometry where the section is located. if (Section->IsInfinite()) { StartX = AllottedGeometry.Position.X; EndX = AllottedGeometry.Position.X + AllottedGeometry.Size.X; } else { StartX = TimeToPixelConverter.TimeToPixel( Section->GetStartTime() ); EndX = TimeToPixelConverter.TimeToPixel( Section->GetEndTime() ); } // Actual section length without grips. float SectionLengthActual = EndX-StartX; float SectionLengthWithGrips = SectionLengthActual+SequencerSectionConstants::SectionGripSize*2; float ActualHeight = NodeHeight / MaxTracks; // Compute allotted geometry area that can be used to draw the section return AllottedGeometry.MakeChild( FVector2D( StartX-SequencerSectionConstants::SectionGripSize, ActualHeight * RowIndex ), FVector2D( SectionLengthWithGrips, ActualHeight ) ); }
bool FSequencerDragOperation::SnapToTimes(TArray<float> InitialTimes, const TArray<float>& SnapTimes, const FTimeToPixel& TimeToPixelConverter, float& OutInitialTime, float& OutSnapTime) { bool bSuccess = false; float ClosestTimePixelDistance = PixelSnapWidth; for (int32 InitialTimeIndex = 0; InitialTimeIndex < InitialTimes.Num(); ++InitialTimeIndex) { float InitialTime = InitialTimes[InitialTimeIndex]; float PixelXOfTime = TimeToPixelConverter.TimeToPixel(InitialTime); for (int32 SnapTimeIndex = 0; SnapTimeIndex < SnapTimes.Num(); ++SnapTimeIndex) { float SnapTime = SnapTimes[SnapTimeIndex]; float PixelXOfSnapTime = TimeToPixelConverter.TimeToPixel(SnapTime); float PixelDistance = FMath::Abs(PixelXOfTime - PixelXOfSnapTime); if (PixelDistance < ClosestTimePixelDistance) { ClosestTimePixelDistance = PixelDistance; OutInitialTime = InitialTime; OutSnapTime = SnapTime; bSuccess = true; } } } return bSuccess; }
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; }
/** * Gets the geometry of a section, optionally inflated by some margin * * @param AllottedGeometry The geometry of the area where sections are located * @param NodeHeight The height of the section area (and its children) * @param SectionInterface Interface to the section to get geometry for * @param TimeToPixelConverter Converts time to pixels and vice versa */ FGeometry GetSectionGeometry( const FGeometry& AllottedGeometry, int32 RowIndex, int32 MaxTracks, float NodeHeight, TSharedPtr<ISequencerSection> SectionInterface, const FTimeToPixel& TimeToPixelConverter ) { const UMovieSceneSection* Section = SectionInterface->GetSectionObject(); // Where to start drawing the section float StartX = TimeToPixelConverter.TimeToPixel( Section->GetStartTime() ); // Where to stop drawing the section float EndX = TimeToPixelConverter.TimeToPixel( Section->GetEndTime() ); // Actual section length without grips. float SectionLengthActual = EndX-StartX; float SectionLengthWithGrips = SectionLengthActual+SequencerSectionConstants::SectionGripSize*2; float ActualHeight = NodeHeight / MaxTracks; // Compute allotted geometry area that can be used to draw the section return AllottedGeometry.MakeChild( FVector2D( StartX-SequencerSectionConstants::SectionGripSize, ActualHeight * RowIndex ), FVector2D( SectionLengthWithGrips, ActualHeight ) ); }
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(); }
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 ); } } } }