/** * This widget was created before render transforms existed for each widget, and it chose to apply the render transform AFTER the layout transform. * This means leveraging the render transform of FGeometry would be expensive, as we would need to use Concat(LayoutTransform, RenderTransform, Inverse(LayoutTransform). * Instead, we maintain the old way of doing it by modifying the AllottedGeometry only during rendering to append the widget's implied RenderTransform to the existing LayoutTransform. */ int32 SFxWidget::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { // Convert the 0..1 origin into local space extents. const FVector2D ScaleOrigin = RenderScaleOrigin.Get() * AllottedGeometry.Size; const FVector2D Offset = VisualOffset.Get() * AllottedGeometry.Size; // create the render transform as a scale around ScaleOrigin and offset it by Offset. const auto RenderTransform = Concatenate(Inverse(ScaleOrigin), RenderScale.Get(), ScaleOrigin, Offset); // This will append the render transform to the layout transform, and we only use it for rendering. FGeometry ModifiedGeometry = AllottedGeometry.MakeChild(AllottedGeometry.Size, RenderTransform); FArrangedChildren ArrangedChildren(EVisibility::Visible); this->ArrangeChildren(ModifiedGeometry, ArrangedChildren); // There may be zero elements in this array if our child collapsed/hidden if( ArrangedChildren.Num() > 0 ) { // We can only have one direct descendant. check( ArrangedChildren.Num() == 1 ); const FArrangedWidget& TheChild = ArrangedChildren[0]; // SFxWidgets are able to ignore parent clipping. const FSlateRect ChildClippingRect = (bIgnoreClipping.Get()) ? ModifiedGeometry.GetClippingRect() : MyClippingRect.IntersectionWith(ModifiedGeometry.GetClippingRect()); FWidgetStyle CompoundedWidgetStyle = FWidgetStyle(InWidgetStyle) .BlendColorAndOpacityTint(ColorAndOpacity.Get()) .SetForegroundColor( ForegroundColor ); return TheChild.Widget->Paint( Args.WithNewParent(this), TheChild.Geometry, ChildClippingRect, OutDrawElements, LayerId + 1, CompoundedWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); } return LayerId; }
int32 SBorder::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { const FSlateBrush* BrushResource = BorderImage.Get(); const bool bEnabled = ShouldBeEnabled(bParentEnabled); const bool bShowDisabledEffect = ShowDisabledEffect.Get(); ESlateDrawEffect::Type DrawEffects = bShowDisabledEffect && !bEnabled ? ESlateDrawEffect::DisabledEffect : ESlateDrawEffect::None; if ( BrushResource && BrushResource->DrawAs != ESlateBrushDrawType::NoDrawType ) { FSlateDrawElement::MakeBox( OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), BrushResource, MyClippingRect, DrawEffects, BrushResource->GetTint( InWidgetStyle ) * InWidgetStyle.GetColorAndOpacityTint() * BorderBackgroundColor.Get().GetColor( InWidgetStyle ) ); } FWidgetStyle CompoundedWidgetStyle = FWidgetStyle(InWidgetStyle) .BlendColorAndOpacityTint(ColorAndOpacity.Get()) .SetForegroundColor( ForegroundColor.Get() ); return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyClippingRect.IntersectionWith( AllottedGeometry.GetClippingRect() ), OutDrawElements, LayerId, CompoundedWidgetStyle, bEnabled ); }
/** * The widget should respond by populating the OutDrawElements array with FDrawElements * that represent it and any of its children. * * @param AllottedGeometry The FGeometry that describes an area in which the widget should appear. * @param MyClippingRect The clipping rectangle allocated for this widget and its children. * @param OutDrawElements A list of FDrawElements to populate with the output. * @param LayerId The Layer onto which this widget should be rendered. * @param InColorAndOpacity Color and Opacity to be applied to all the descendants of the widget being painted * @param bParentEnabled True if the parent of this widget is enabled. * * @return The maximum layer ID attained by this widget or any of its children. */ int32 SCompoundWidget::OnPaint( const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { // A CompoundWidget just draws its children FArrangedChildren ArrangedChildren(EVisibility::Visible); { #if SLATE_HD_STATS SCOPE_CYCLE_COUNTER( STAT_SlateOnPaint_SCompoundWidget ); #endif this->ArrangeChildren(AllottedGeometry, ArrangedChildren); } // There may be zero elements in this array if our child collapsed/hidden if( ArrangedChildren.Num() > 0 ) { check( ArrangedChildren.Num() == 1 ); FArrangedWidget& TheChild = ArrangedChildren(0); const FSlateRect ChildClippingRect = AllottedGeometry.GetClippingRect().InsetBy( ChildSlot.SlotPadding.Get() * AllottedGeometry.Scale ).IntersectionWith(MyClippingRect); FWidgetStyle CompoundedWidgetStyle = FWidgetStyle(InWidgetStyle) .BlendColorAndOpacityTint(ColorAndOpacity.Get()) .SetForegroundColor( ForegroundColor ); return TheChild.Widget->OnPaint( TheChild.Geometry, ChildClippingRect, OutDrawElements, LayerId + 1, CompoundedWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); } return LayerId; }
int32 SPopup::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const { FArrangedChildren ArrangedChildren(EVisibility::Visible); this->ArrangeChildren(AllottedGeometry, ArrangedChildren); // There may be zero elements in this array if our child collapsed/hidden if (ArrangedChildren.Num() > 0) { check(ArrangedChildren.Num() == 1); FArrangedWidget& TheChild = ArrangedChildren[0]; FWidgetStyle CompoundedWidgetStyle = FWidgetStyle(InWidgetStyle) .BlendColorAndOpacityTint(ColorAndOpacity.Get()) .SetForegroundColor(GetForegroundColor()); // An SPopup just queues up its children to be painted after everything in this window is done painting. OutDrawElements.QueueDeferredPainting( FSlateWindowElementList::FDeferredPaint(TheChild.Widget, Args.WithNewParent(this), TheChild.Geometry, MyClippingRect, CompoundedWidgetStyle, ShouldBeEnabled(bParentEnabled)) ); } return LayerId; }
void FWidgetRenderer::DrawWindow( UTextureRenderTarget2D* RenderTarget, TSharedRef<FHittestGrid> HitTestGrid, TSharedRef<SWindow> Window, FGeometry WindowGeometry, FSlateRect WindowClipRect, float DeltaTime) { #if !UE_SERVER if (!IsRunningDedicatedServer()) { if ( GUsingNullRHI ) { return; } if ( !bFoldTick ) { Window->TickWidgetsRecursively(WindowGeometry, FApp::GetCurrentTime(), DeltaTime); } if ( bPrepassNeeded ) { // Ticking can cause geometry changes. Recompute Window->SlatePrepass(WindowGeometry.Scale); } // Prepare the test grid HitTestGrid->ClearGridForNewFrame(WindowClipRect); // Get the free buffer & add our virtual window FSlateDrawBuffer& DrawBuffer = Renderer->GetDrawBuffer(); FSlateWindowElementList& WindowElementList = DrawBuffer.AddWindowElementList(Window); int32 MaxLayerId = 0; { FPaintArgs PaintArgs(Window.Get(), HitTestGrid.Get(), FVector2D::ZeroVector, FApp::GetCurrentTime(), DeltaTime); // Paint the window MaxLayerId = Window->Paint( PaintArgs, WindowGeometry, WindowClipRect, WindowElementList, 0, FWidgetStyle(), Window->IsEnabled()); } Renderer->DrawWindow_GameThread(DrawBuffer); struct FRenderThreadContext { FSlateDrawBuffer* DrawBuffer; FTextureRenderTarget2DResource* RenderTargetResource; TSharedPtr<ISlate3DRenderer, ESPMode::ThreadSafe> Renderer; }; FRenderThreadContext Context = { &DrawBuffer, static_cast<FTextureRenderTarget2DResource*>(RenderTarget->GameThread_GetRenderTargetResource()), Renderer }; // Enqueue a command to unlock the draw buffer after all windows have been drawn ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FWidgetRenderer_DrawWindow, FRenderThreadContext, InContext, Context, { InContext.Renderer->DrawWindowToTarget_RenderThread(RHICmdList, InContext.RenderTargetResource, *InContext.DrawBuffer); });
void SSection::DrawSectionBorders( const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId ) const { UMovieSceneSection* SectionObject = SectionInterface->GetSectionObject(); FSequencerSelection& Selection = ParentSectionArea->GetSequencer().GetSelection(); const bool bSelected = Selection.IsSelected(SectionObject); const bool bActive = Selection.GetActiveSelection() == FSequencerSelection::EActiveSelection::KeyAndSection; static const FName SelectionColorName("SelectionColor"); static const FName SelectionInactiveColorName("SelectionColorInactive"); FLinearColor SelectionColor = FEditorStyle::GetSlateColor(SelectionColorName).GetColor(FWidgetStyle()); FLinearColor SelectionInactiveColor = FEditorStyle::GetSlateColor(SelectionInactiveColorName).GetColor(FWidgetStyle()); FLinearColor TransparentSelectionColor = SelectionColor; static const FName SectionGripLeftName("Sequencer.SectionGripLeft"); static const FName SectionGripRightName("Sequencer.SectionGripRight"); // Left Grip FSlateDrawElement::MakeBox( OutDrawElements, LayerId, // Center the key along Y. Ensure the middle of the key is at the actual key time AllottedGeometry.ToPaintGeometry( FVector2D( 0.0f, 0.0f ), FVector2D( SequencerSectionConstants::SectionGripSize, AllottedGeometry.GetDrawSize().Y) ) , FEditorStyle::GetBrush(SectionGripLeftName), MyClippingRect, ESlateDrawEffect::None, (bLeftEdgePressed || bLeftEdgeHovered) ? TransparentSelectionColor : FLinearColor::White ); // Right Grip FSlateDrawElement::MakeBox( OutDrawElements, LayerId, // Center the key along Y. Ensure the middle of the key is at the actual key time AllottedGeometry.ToPaintGeometry( FVector2D( AllottedGeometry.Size.X-SequencerSectionConstants::SectionGripSize, 0.0f), FVector2D(SequencerSectionConstants::SectionGripSize, AllottedGeometry.GetDrawSize().Y)), FEditorStyle::GetBrush(SectionGripRightName), MyClippingRect, ESlateDrawEffect::None, (bRightEdgePressed || bRightEdgeHovered) ? TransparentSelectionColor : FLinearColor::White ); // draw selection box if(bSelected) { static const FName SelectionBorder("Sequencer.Section.SelectionBorder"); FSlateDrawElement::MakeBox( OutDrawElements, LayerId+1, AllottedGeometry.ToPaintGeometry(), FEditorStyle::GetBrush(SelectionBorder), MyClippingRect, ESlateDrawEffect::None, bActive ? SelectionColor : SelectionInactiveColor ); } }