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 ); }
int32 SARResourceBarWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const { const FSlateBrush* BrushResource = new FSlateBrush(); FSlateDrawElement::MakeBox( OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), BrushResource, MyClippingRect, ESlateDrawEffect::None, FLinearColor::Gray * 0.35f ); if (MyAttrComp.IsValid()) { FVector2D WidgetSize = MyClippingRect.GetSize(); //float HealthWidth = (MyAttrComp->Health * WidgetSize.X) / MyAttrComp->MaxHealth; float HealthWidth = (CurrentValue.Get() * WidgetSize.X) / MaxValue.Get(); // Draw current health FSlateDrawElement::MakeBox( OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(FVector2D::ZeroVector, FVector2D(HealthWidth, WidgetSize.Y)), BrushResource, MyClippingRect, ESlateDrawEffect::None, FLinearColor::Red *.9f ); } return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled); }
/** SWidget Interface */ int32 SSequencerSectionAreaView::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { FArrangedChildren ArrangedChildren(EVisibility::Visible); ArrangeChildren(AllottedGeometry, ArrangedChildren); if( SectionAreaNode.IsValid() ) { // Draw a region around the entire section area FSlateDrawElement::MakeBox( OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), BackgroundBrush, MyClippingRect, ESlateDrawEffect::None, SequencerSectionAreaConstants::BackgroundColor ); } for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex) { FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; FSlateRect ChildClipRect = MyClippingRect.IntersectionWith( CurWidget.Geometry.GetClippingRect() ); const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint( Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, LayerId+1, InWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); } return LayerId+1; }
int32 SPanel::PaintArrangedChildren( const FPaintArgs& Args, const FArrangedChildren& ArrangedChildren, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { // Because we paint multiple children, we must track the maximum layer id that they produced in case one of our parents // wants to an overlay for all of its contents. int32 MaxLayerId = LayerId; const FPaintArgs NewArgs = Args.WithNewParent(this); for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex) { const FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; bool bWereOverlapping; FSlateRect ChildClipRect = MyClippingRect.IntersectionWith(CurWidget.Geometry.GetClippingRect(), bWereOverlapping); if ( bWereOverlapping ) { const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint(NewArgs, CurWidget.Geometry, ChildClipRect, OutDrawElements, LayerId, InWidgetStyle, ShouldBeEnabled(bParentEnabled)); MaxLayerId = FMath::Max(MaxLayerId, CurWidgetsMaxLayerId); } } return MaxLayerId; }
/** * 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 SDockingTabWell::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { // When we are dragging a tab, it must be painted on top of the other tabs, so we cannot // just reuse the Panel's default OnPaint. // The TabWell has no visualization of its own; it just visualizes its child tabs. FArrangedChildren ArrangedChildren(EVisibility::Visible); this->ArrangeChildren(AllottedGeometry, ArrangedChildren); // Because we paint multiple children, we must track the maximum layer id that they produced in case one of our parents // wants to an overlay for all of its contents. int32 MaxLayerId = LayerId; TSharedPtr<SDockTab> ForegroundTab = GetForegroundTab(); FArrangedWidget* ForegroundTabGeometry = NULL; // Draw all inactive tabs first for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex) { FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; if (CurWidget.Widget == ForegroundTab) { ForegroundTabGeometry = &CurWidget; } else { FSlateRect ChildClipRect = MyClippingRect.IntersectionWith( CurWidget.Geometry.GetClippingRect() ); const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint( Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, MaxLayerId, InWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); MaxLayerId = FMath::Max( MaxLayerId, CurWidgetsMaxLayerId ); } } // Draw active tab in front if (ForegroundTab != TSharedPtr<SDockTab>()) { FSlateRect ChildClipRect = MyClippingRect.IntersectionWith( ForegroundTabGeometry->Geometry.GetClippingRect() ); const int32 CurWidgetsMaxLayerId = ForegroundTabGeometry->Widget->Paint( Args.WithNewParent(this), ForegroundTabGeometry->Geometry, ChildClipRect, OutDrawElements, MaxLayerId, InWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); MaxLayerId = FMath::Max( MaxLayerId, CurWidgetsMaxLayerId ); } return MaxLayerId; }
int32 SGridPanel::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { FArrangedChildren ArrangedChildren(EVisibility::All); this->ArrangeChildren(AllottedGeometry, ArrangedChildren); // Because we paint multiple children, we must track the maximum layer id that they produced in case one of our parents // wants to an overlay for all of its contents. int32 MaxLayerId = LayerId; // We need to iterate over slots, because slots know the GridLayers. This isn't available in the arranged children. // Some slots do not show up (they are hidden/collapsed). We need a 2nd index to skip over them. // // GridLayers must ensure that everything in LayerN is below LayerN+1. In other words, // every grid layer group must start at the current MaxLayerId (similar to how SOverlay works). int32 LastGridLayer = 0; for (int32 ChildIndex = 0; ChildIndex < Slots.Num(); ++ChildIndex) { FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; if (CurWidget.Widget->GetVisibility().IsVisible()) { const FSlot& CurSlot = Slots[ChildIndex]; FSlateRect ChildClipRect = MyClippingRect.IntersectionWith( CurWidget.Geometry.GetClippingRect() ); if ( LastGridLayer != CurSlot.LayerParam ) { // We starting a new grid layer group? LastGridLayer = CurSlot.LayerParam; // Ensure that everything here is drawn on top of // previously drawn grid content. LayerId = MaxLayerId+1; } const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint( Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, LayerId, InWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); MaxLayerId = FMath::Max( MaxLayerId, CurWidgetsMaxLayerId ); } } //#define LAYOUT_DEBUG #ifdef LAYOUT_DEBUG LayerId = LayoutDebugPaint( AllottedGeometry, MyClippingRect, OutDrawElements, LayerId ); #endif return MaxLayerId; }
int32 FHittestGrid::InsertWidget( const int32 ParentHittestIndex, const EVisibility& Visibility, const FArrangedWidget& Widget, const FVector2D InWindowOffset, const FSlateRect& InClippingRect ) { check( ParentHittestIndex < WidgetsCachedThisFrame->Num() ); // Update the FGeometry to transform into desktop space. FArrangedWidget WindowAdjustedWidget(Widget); WindowAdjustedWidget.Geometry.AppendTransform(FSlateLayoutTransform(InWindowOffset)); const FSlateRect WindowAdjustedRect = InClippingRect.OffsetBy(InWindowOffset); // Remember this widget, its geometry, and its place in the logical hierarchy. const int32 WidgetIndex = WidgetsCachedThisFrame->Add( FCachedWidget( ParentHittestIndex, WindowAdjustedWidget, WindowAdjustedRect ) ); check( WidgetIndex < WidgetsCachedThisFrame->Num() ); if (ParentHittestIndex != INDEX_NONE) { (*WidgetsCachedThisFrame)[ParentHittestIndex].AddChild( WidgetIndex ); } if (Visibility.IsHitTestVisible()) { // Mark any cell that is overlapped by this widget. // Compute the render space clipping rect, and compute it's aligned bounds so we can insert conservatively into the hit test grid. FSlateRect GridRelativeBoundingClipRect = TransformRect( Concatenate( Inverse(WindowAdjustedWidget.Geometry.GetAccumulatedLayoutTransform()), WindowAdjustedWidget.Geometry.GetAccumulatedRenderTransform() ), FSlateRotatedRect(WindowAdjustedWidget.Geometry.GetClippingRect().IntersectionWith(WindowAdjustedRect)) ) .ToBoundingRect() .OffsetBy(-GridOrigin); // Starting and ending cells covered by this widget. const FIntPoint UpperLeftCell = FIntPoint( FMath::Max(0, FMath::FloorToInt(GridRelativeBoundingClipRect.Left / CellSize.X)), FMath::Max(0, FMath::FloorToInt(GridRelativeBoundingClipRect.Top / CellSize.Y))); const FIntPoint LowerRightCell = FIntPoint( FMath::Min( NumCells.X-1, FMath::FloorToInt(GridRelativeBoundingClipRect.Right / CellSize.X)), FMath::Min( NumCells.Y-1, FMath::FloorToInt(GridRelativeBoundingClipRect.Bottom / CellSize.Y))); for (int32 XIndex=UpperLeftCell.X; XIndex <= LowerRightCell.X; ++ XIndex ) { for(int32 YIndex=UpperLeftCell.Y; YIndex <= LowerRightCell.Y; ++YIndex) { CellAt(XIndex, YIndex).CachedWidgetIndexes.Add( WidgetIndex ); } } } return WidgetIndex; }
int32 SSplitter::GetHandleBeingResizedFromMousePosition( float PhysicalSplitterHandleSize, float HitDetectionSplitterHandleSize, FVector2D LocalMousePos, const TArray<FLayoutGeometry>& ChildGeometries ) { const int32 AxisIndex = (SplitterOrientation == Orient_Horizontal) ? 0 : 1; const float HalfHitDetectionSplitterHandleSize = ( HitDetectionSplitterHandleSize / 2 ); const float HalfPhysicalSplitterHandleSize = ( PhysicalSplitterHandleSize / 2 ); // Search for the two widgets between which the cursor currently resides. for ( int32 ChildIndex = 1; ChildIndex < ChildGeometries.Num(); ++ChildIndex ) { FSlateRect PrevChildRect = ChildGeometries[ChildIndex - 1].GetRectInParentSpace(); FVector2D NextChildOffset = ChildGeometries[ChildIndex].GetOffsetInParentSpace(); float PrevBound = PrevChildRect.GetTopLeft().Component(AxisIndex) + PrevChildRect.GetSize().Component(AxisIndex) - HalfHitDetectionSplitterHandleSize + HalfPhysicalSplitterHandleSize; float NextBound = NextChildOffset.Component(AxisIndex) + HalfHitDetectionSplitterHandleSize - HalfPhysicalSplitterHandleSize; if ( LocalMousePos.Component(AxisIndex) > PrevBound && LocalMousePos.Component(AxisIndex) < NextBound ) { return ChildIndex - 1; } } return INDEX_NONE; }
int32 SConstraintCanvas::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); // Because we paint multiple children, we must track the maximum layer id that they produced in case one of our parents // wants to an overlay for all of its contents. int32 MaxLayerId = LayerId; for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex) { FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; FSlateRect ChildClipRect = MyClippingRect.IntersectionWith(CurWidget.Geometry.GetClippingRect()); const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint( Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, MaxLayerId + 1, InWidgetStyle, ShouldBeEnabled(bParentEnabled)); MaxLayerId = FMath::Max(MaxLayerId, CurWidgetsMaxLayerId); } return MaxLayerId; }
int32 SSequencerTrackArea::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { FArrangedChildren ArrangedChildren(EVisibility::Visible); ArrangeChildren(AllottedGeometry, ArrangedChildren); for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex) { FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; FSlateRect ChildClipRect = MyClippingRect.IntersectionWith( CurWidget.Geometry.GetClippingRect() ); const int32 ThisWidgetLayerId = CurWidget.Widget->Paint( Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, LayerId + 1, InWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); LayerId = FMath::Max(LayerId, ThisWidgetLayerId); } auto SequencerPin = SequencerWidget.Pin(); if (SequencerPin.IsValid()) { return SequencerPin->GetEditTool().OnPaint(AllottedGeometry, MyClippingRect, OutDrawElements, LayerId + 1); } return LayerId; }
int32 SResponsiveGridPanel::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { FArrangedChildren ArrangedChildren(EVisibility::All); this->ArrangeChildren(AllottedGeometry, ArrangedChildren); // Because we paint multiple children, we must track the maximum layer id that they produced in case one of our parents // wants to an overlay for all of its contents. int32 MaxLayerId = LayerId; // We need to iterate over slots, because slots know the GridLayers. This isn't available in the arranged children. // Some slots do not show up (they are hidden/collapsed). We need a 2nd index to skip over them. for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex) { FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex]; if (CurWidget.Widget->GetVisibility().IsVisible()) { FSlateRect ChildClipRect = MyClippingRect.IntersectionWith( CurWidget.Geometry.GetClippingRect() ); const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint( Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, LayerId, InWidgetStyle, ShouldBeEnabled( bParentEnabled ) ); MaxLayerId = FMath::Max( MaxLayerId, CurWidgetsMaxLayerId ); } } #ifdef LAYOUT_DEBUG LayerId = LayoutDebugPaint( AllottedGeometry, MyClippingRect, OutDrawElements, LayerId ); #endif return MaxLayerId; }
void SProfilerThreadView::DrawUIStackNodes() const { // SCOPE_LOG_TIME_FUNC(); check( PaintState ); const double ThreadViewOffsetPx = PositionXMS*NumPixelsPerMillisecond; PaintState->LayerId++; static const FSlateBrush* BorderBrush = FEditorStyle::GetBrush( "Profiler.ThreadView.SampleBorder" ); const FColor GameThreadColor = FColorList::Red; const FColor RenderThreadColor = FColorList::Blue; const FColor ThreadColors[2] = {GameThreadColor, RenderThreadColor}; // Draw nodes. for( const auto& RowOfNodes : ProfilerUIStream.LinearRowsOfNodes ) { int32 NodeIndex = 0; for( const auto& UIStackNode : RowOfNodes ) { NodeIndex++; // Check if the node is visible. //if( UIStackNode->IsVisible() ) { const FVector2D PositionPx = UIStackNode->GetLocalPosition( ThreadViewOffsetPx, PositionY ) * FVector2D( 1.0f, NUM_PIXELS_PER_ROW ); const FVector2D SizePx = FVector2D( FMath::Max( UIStackNode->WidthPx - 1.0, 0.0 ), NUM_PIXELS_PER_ROW ); const FSlateRect ClippedNodeRect = PaintState->LocalClippingRect.IntersectionWith( FSlateRect( PositionPx, PositionPx + SizePx ) ); // Check if this node is inside the visible area. if( ClippedNodeRect.IsEmpty() ) { continue; } FColor NodeColor = UIStackNode->bIsCombined ? ThreadColors[UIStackNode->ThreadIndex].WithAlpha( 64 ) : ThreadColors[UIStackNode->ThreadIndex].WithAlpha( 192 ); NodeColor.G += NodeIndex % 2 ? 0 : 64; // Draw a cycle counter for this profiler UI stack node. FSlateDrawElement::MakeBox ( PaintState->OutDrawElements, PaintState->LayerId, PaintState->AllottedGeometry.ToPaintGeometry( ClippedNodeRect.GetTopLeft(), ClippedNodeRect.GetSize() ), BorderBrush, PaintState->AbsoluteClippingRect, PaintState->DrawEffects, NodeColor ); } } } // @TODO yrx 2014-04-29 Separate layer for makebox, makeshadowtext, maketext. PaintState->LayerId++; const float MarkerPosYOffsetPx = ((float)NUM_PIXELS_PER_ROW - PaintState->SummaryFont8Height)*0.5f; // Draw nodes' descriptions. for( const auto& RowOfNodes : ProfilerUIStream.LinearRowsOfNodes ) { for( const auto& UIStackNode : RowOfNodes ) { const FVector2D PositionPx = UIStackNode->GetLocalPosition( ThreadViewOffsetPx, PositionY ) * FVector2D( 1.0f, NUM_PIXELS_PER_ROW ); const FVector2D SizePx = FVector2D( UIStackNode->WidthPx, NUM_PIXELS_PER_ROW ); const FSlateRect ClippedNodeRect = PaintState->LocalClippingRect.IntersectionWith( FSlateRect( PositionPx, PositionPx + SizePx ) ); // Check if this node is inside the visible area. if( ClippedNodeRect.IsEmpty() ) { continue; } FString StringStatName = UIStackNode->StatName.GetPlainNameString(); FString StringStatNameWithTime = StringStatName + FString::Printf( TEXT( " (%.4f MS)" ), UIStackNode->GetDurationMS() ); if( UIStackNode->bIsCulled ) { StringStatName += TEXT( " [C]" ); StringStatNameWithTime += TEXT( " [C]" ); } // Update position of the text to be always visible and try to center it. const float StatNameWidthPx = PaintState->FontMeasureService->Measure( StringStatName, PaintState->SummaryFont8 ).X; const float StatNameWithTimeWidthPx = PaintState->FontMeasureService->Measure( StringStatNameWithTime, PaintState->SummaryFont8 ).X; const float TextAreaWidthPx = ClippedNodeRect.GetSize().X; bool bUseShortVersion = true; FVector2D AdjustedPositionPx; // Center the stat name with timing if we can. if( TextAreaWidthPx > StatNameWithTimeWidthPx ) { AdjustedPositionPx = FVector2D( ClippedNodeRect.Left + (TextAreaWidthPx - StatNameWithTimeWidthPx)*0.5f, PositionPx.Y + MarkerPosYOffsetPx ); bUseShortVersion = false; } // Center the stat name. else if( TextAreaWidthPx > StatNameWidthPx ) { AdjustedPositionPx = FVector2D( ClippedNodeRect.Left + (TextAreaWidthPx - StatNameWidthPx)*0.5f, PositionPx.Y + MarkerPosYOffsetPx ); } // Move to the edge. else { AdjustedPositionPx = FVector2D( ClippedNodeRect.Left, PositionPx.Y + MarkerPosYOffsetPx ); } const FVector2D AbsolutePositionPx = PaintState->AllottedGeometry.LocalToAbsolute( ClippedNodeRect.GetTopLeft() ); const FSlateRect AbsoluteClippingRect = FSlateRect( AbsolutePositionPx, AbsolutePositionPx + ClippedNodeRect.GetSize() ); DrawText( bUseShortVersion ? StringStatName : StringStatNameWithTime, PaintState->SummaryFont8, AdjustedPositionPx, FColorList::White, FColorList::Black, FVector2D( 1.0f, 1.0f ), &AbsoluteClippingRect ); } } }
void SProfilerThreadView::DrawFramesBackgroundAndTimelines() const { static const FSlateColorBrush SolidWhiteBrush = FSlateColorBrush( FColorList::White ); check( PaintState ); const double ThreadViewOffsetPx = PositionXMS*NumPixelsPerMillisecond; PaintState->LayerId++; TArray<FVector2D> LinePoints; // Draw frames background for easier reading. for( const auto& ThreadNode : ProfilerUIStream.ThreadNodes ) { if( ThreadNode.StatName == NAME_GameThread ) { const FVector2D PositionPx = ThreadNode.GetLocalPosition( ThreadViewOffsetPx, -1.0f ); const FVector2D SizePx = FVector2D( ThreadNode.WidthPx, PaintState->Size2D().Y ); const FSlateRect ClippedFrameBackgroundRect = PaintState->LocalClippingRect.IntersectionWith( FSlateRect( PositionPx, PositionPx + SizePx ) ); FSlateDrawElement::MakeBox ( PaintState->OutDrawElements, PaintState->LayerId, PaintState->AllottedGeometry.ToPaintGeometry( ClippedFrameBackgroundRect.GetTopLeft(), ClippedFrameBackgroundRect.GetSize() ), &SolidWhiteBrush, PaintState->AbsoluteClippingRect, PaintState->DrawEffects, ThreadNode.FrameIndex % 2 ? FColorList::White.WithAlpha( 64 ) : FColorList::White.WithAlpha( 128 ) ); // Check if this frame time marker is inside the visible area. const float LocalPositionXPx = PositionPx.X + SizePx.X; if( LocalPositionXPx < 0.0f || LocalPositionXPx > PaintState->Size2D().X ) { continue; } LinePoints.Reset( 2 ); LinePoints.Add( FVector2D( LocalPositionXPx, 0.0f ) ); LinePoints.Add( FVector2D( LocalPositionXPx, PaintState->Size2D().Y ) ); // Draw frame time marker. FSlateDrawElement::MakeLines ( PaintState->OutDrawElements, PaintState->LayerId, PaintState->AllottedGeometry.ToPaintGeometry(), LinePoints, PaintState->AbsoluteClippingRect, PaintState->DrawEffects, PaintState->WidgetStyle.GetColorAndOpacityTint() * FColorList::SkyBlue, false ); } } PaintState->LayerId++; const double PositionXStartPx = FMath::TruncToFloat( PositionXMS*NumPixelsPerMillisecond / (double)NUM_PIXELS_BETWEEN_TIMELINE )*(double)NUM_PIXELS_BETWEEN_TIMELINE; const double PositionXEndPx = PositionXStartPx + RangeXMS*NumPixelsPerMillisecond; for( double TimelinePosXPx = PositionXStartPx; TimelinePosXPx < PositionXEndPx; TimelinePosXPx += (double)NUM_PIXELS_BETWEEN_TIMELINE ) { LinePoints.Reset( 2 ); LinePoints.Add( FVector2D( TimelinePosXPx - ThreadViewOffsetPx, 0.0f ) ); LinePoints.Add( FVector2D( TimelinePosXPx - ThreadViewOffsetPx, PaintState->Size2D().Y ) ); // Draw time line. FSlateDrawElement::MakeLines ( PaintState->OutDrawElements, PaintState->LayerId, PaintState->AllottedGeometry.ToPaintGeometry(), LinePoints, PaintState->AbsoluteClippingRect, PaintState->DrawEffects, PaintState->WidgetStyle.GetColorAndOpacityTint() * FColorList::LimeGreen, false ); } }
void FMainFrameHandler::ShutDownEditor() { FEditorDelegates::OnShutdownPostPackagesSaved.Broadcast(); // Any pending autosaves should not happen. A tick will go by before the editor shuts down and we want to avoid auto-saving during this time. GUnrealEd->GetPackageAutoSaver().ResetAutoSaveTimer(); GEditor->RequestEndPlayMap(); // End any play on console/PC games still happening GEditor->EndPlayOnLocalPc(); // Cancel any current Launch On in progress GEditor->CancelPlayingViaLauncher(); TSharedPtr<SWindow> RootWindow = RootWindowPtr.Pin(); // Save root window placement so we can restore it. if (RootWindow.IsValid()) { FSlateRect WindowRect = RootWindow->GetNonMaximizedRectInScreen(); FRootWindowLocation RootWindowLocation(FVector2D(WindowRect.Left, WindowRect.Top), WindowRect.GetSize(), RootWindow->IsWindowMaximized()); RootWindowLocation.SaveToIni(); } // Save the visual state of the editor before we even // ask whether we can shut down. TSharedRef<FGlobalTabmanager> GlobalTabManager = FGlobalTabmanager::Get(); if (FUnrealEdMisc::Get().IsSavingLayoutOnClosedAllowed()) { GlobalTabManager->SaveAllVisualState(); } else { GConfig->EmptySection(TEXT("EditorLayouts"), *GEditorLayoutIni); } // Clear the callback for destructionfrom the main tab; otherwise it will re-enter this shutdown function. if (MainTabPtr.IsValid()) { MainTabPtr.Pin()->SetOnTabClosed(SDockTab::FOnTabClosedCallback()); } // Inform the AssetEditorManager that the editor is exiting so that it may save open assets // and report usage stats FAssetEditorManager::Get().OnExit(); if (RootWindow.IsValid()) { RootWindow->SetRequestDestroyWindowOverride(FRequestDestroyWindowOverride()); RootWindow->RequestDestroyWindow(); } // Save out any config settings for the editor so they don't get lost GEditor->SaveConfig(); GLevelEditorModeTools().SaveConfig(); // Delete user settings, if requested if (FUnrealEdMisc::Get().IsDeletePreferences()) { IFileManager::Get().Delete(*GEditorPerProjectIni); } // Take a screenshot of this project for the project browser if (FApp::HasGameName()) { const FString ExistingBaseFilename = FString(FApp::GetGameName()) + TEXT(".png"); const FString ExistingScreenshotFilename = FPaths::Combine(*FPaths::GameDir(), *ExistingBaseFilename); // If there is already a screenshot, no need to take an auto screenshot if (!FPaths::FileExists(ExistingScreenshotFilename)) { const FString ScreenShotFilename = FPaths::Combine(*FPaths::GameSavedDir(), TEXT("AutoScreenshot.png")); FViewport* Viewport = GEditor->GetActiveViewport(); if (Viewport) { UThumbnailManager::CaptureProjectThumbnail(Viewport, ScreenShotFilename, false); } } } // Shut down the editor // NOTE: We can't close the editor from within this stack frame as it will cause various DLLs // (such as MainFrame) to become unloaded out from underneath the code pointer. We'll shut down // as soon as it's safe to do so. // Note this is the only place in slate that should be calling QUIT_EDITOR GEngine->DeferredCommands.Add(TEXT("QUIT_EDITOR")); }
void FSceneViewport::ResizeFrame(uint32 NewSizeX, uint32 NewSizeY, EWindowMode::Type NewWindowMode, int32 InPosX, int32 InPosY) { // Resizing the window directly is only supported in the game if( FApp::IsGame() && NewSizeX > 0 && NewSizeY > 0 ) { FWidgetPath WidgetPath; TSharedPtr<SWindow> WindowToResize = FSlateApplication::Get().FindWidgetWindow( ViewportWidget.Pin().ToSharedRef(), WidgetPath ); if( WindowToResize.IsValid() ) { int32 CVarValue = GetBoundFullScreenModeCVar(); EWindowMode::Type DesiredWindowMode = GetWindowModeType(NewWindowMode); // Avoid resizing if nothing changes. bool bNeedsResize = SizeX != NewSizeX || SizeY != NewSizeY || NewWindowMode != DesiredWindowMode || DesiredWindowMode != WindowToResize->GetWindowMode(); if (bNeedsResize) { if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDEnabled()) { // Resize & move only if moving to a fullscreen mode if (NewWindowMode != EWindowMode::Windowed) { FSlateRect PreFullScreenRect = WindowToResize->GetRectInScreen(); IHeadMountedDisplay::MonitorInfo MonitorInfo; if (GEngine->HMDDevice->GetHMDMonitorInfo(MonitorInfo)) { NewSizeX = MonitorInfo.ResolutionX; NewSizeY = MonitorInfo.ResolutionY; if (GEngine->HMDDevice->IsFullScreenAllowed()) { WindowToResize->ReshapeWindow(FVector2D(MonitorInfo.DesktopX, MonitorInfo.DesktopY), FVector2D(MonitorInfo.ResolutionX, MonitorInfo.ResolutionY)); } else { WindowToResize->Resize(FVector2D(MonitorInfo.ResolutionX, MonitorInfo.ResolutionY)); DesiredWindowMode = EWindowMode::WindowedMirror; } } GEngine->HMDDevice->PushPreFullScreenRect(PreFullScreenRect); } } // Toggle fullscreen and resize WindowToResize->SetWindowMode(DesiredWindowMode); if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDEnabled()) { if (NewWindowMode == EWindowMode::Windowed) { FSlateRect PreFullScreenRect; GEngine->HMDDevice->PopPreFullScreenRect(PreFullScreenRect); if (PreFullScreenRect.GetSize().X > 0 && PreFullScreenRect.GetSize().Y > 0 && GEngine->HMDDevice->IsFullScreenAllowed()) { NewSizeX = PreFullScreenRect.GetSize().X; NewSizeY = PreFullScreenRect.GetSize().Y; WindowToResize->MoveWindowTo (FVector2D(PreFullScreenRect.Left, PreFullScreenRect.Top)); } } if (NewWindowMode != WindowMode) { // Only notify the HMD if we've actually changed modes GEngine->HMDDevice->OnScreenModeChange(NewWindowMode); } } LockMouseToViewport(!CurrentReplyState.ShouldReleaseMouseLock()); int32 NewWindowSizeX = NewSizeX; int32 NewWindowSizeY = NewSizeY; WindowToResize->Resize( FVector2D(NewWindowSizeX, NewWindowSizeY) ); ResizeViewport(NewWindowSizeX, NewWindowSizeY, NewWindowMode, InPosX, InPosY); } UCanvas::UpdateAllCanvasSafeZoneData(); } } }
void FSceneViewport::ResizeFrame(uint32 NewSizeX, uint32 NewSizeY, EWindowMode::Type NewWindowMode, int32 InPosX, int32 InPosY) { // Resizing the window directly is only supported in the game if( FApp::IsGame() && NewSizeX > 0 && NewSizeY > 0 ) { FWidgetPath WidgetPath; TSharedPtr<SWindow> WindowToResize = FSlateApplication::Get().FindWidgetWindow( ViewportWidget.Pin().ToSharedRef(), WidgetPath ); if( WindowToResize.IsValid() ) { EWindowMode::Type DesiredWindowMode = GetWindowModeType(NewWindowMode); // If we're going into windowed fullscreen mode, we always want the window to fill the entire screen. // When we calculate the scene view, we'll check the fullscreen mode and configure the screen percentage // scaling so we actual render to the resolution we've been asked for. if (DesiredWindowMode == EWindowMode::WindowedFullscreen) { FDisplayMetrics DisplayMetrics; FSlateApplication::Get().GetInitialDisplayMetrics(DisplayMetrics); NewSizeX = DisplayMetrics.PrimaryDisplayWidth;; NewSizeY = DisplayMetrics.PrimaryDisplayHeight;; } uint32 ViewportSizeX = NewSizeX; uint32 ViewportSizeY = NewSizeY; if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDConnected()) { WindowToResize->SetViewportSizeDrivenByWindow(true); // Resize & move only if moving to a fullscreen mode if (NewWindowMode != EWindowMode::Windowed) { IHeadMountedDisplay::MonitorInfo MonitorInfo; if (GEngine->HMDDevice->GetHMDMonitorInfo(MonitorInfo)) { ViewportSizeX = MonitorInfo.ResolutionX; ViewportSizeY = MonitorInfo.ResolutionY; if (GEngine->HMDDevice->IsFullscreenAllowed()) { NewSizeX = MonitorInfo.ResolutionX; NewSizeY = MonitorInfo.ResolutionY; } else { if (MonitorInfo.WindowSizeX != 0 && MonitorInfo.WindowSizeY != 0) { NewSizeX = MonitorInfo.WindowSizeX; NewSizeY = MonitorInfo.WindowSizeY; } NewWindowMode = DesiredWindowMode = EWindowMode::WindowedMirror; WindowToResize->SetIndependentViewportSize(FVector2D(ViewportSizeX, ViewportSizeY)); } } } } // Avoid resizing if nothing changes. bool bNeedsResize = SizeX != ViewportSizeX || SizeY != ViewportSizeY || NewWindowMode != DesiredWindowMode || DesiredWindowMode != WindowToResize->GetWindowMode(); if (bNeedsResize) { if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDConnected()) { // Resize & move only if moving to a fullscreen mode if (NewWindowMode != EWindowMode::Windowed) { FSlateRect PreFullScreenRect = WindowToResize->GetRectInScreen(); IHeadMountedDisplay::MonitorInfo MonitorInfo; if (GEngine->HMDDevice->GetHMDMonitorInfo(MonitorInfo)) { if (GEngine->HMDDevice->IsFullscreenAllowed()) { WindowToResize->ReshapeWindow(FVector2D(MonitorInfo.DesktopX, MonitorInfo.DesktopY), FVector2D(MonitorInfo.ResolutionX, MonitorInfo.ResolutionY)); } } GEngine->HMDDevice->PushPreFullScreenRect(PreFullScreenRect); } } // Toggle fullscreen and resize WindowToResize->SetWindowMode(DesiredWindowMode); if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDEnabled()) { if (NewWindowMode == EWindowMode::Windowed) { FSlateRect PreFullScreenRect; GEngine->HMDDevice->PopPreFullScreenRect(PreFullScreenRect); if (PreFullScreenRect.GetSize().X > 0 && PreFullScreenRect.GetSize().Y > 0 && GEngine->HMDDevice->IsFullscreenAllowed()) { NewSizeX = PreFullScreenRect.GetSize().X; NewSizeY = PreFullScreenRect.GetSize().Y; WindowToResize->MoveWindowTo(FVector2D(PreFullScreenRect.Left, PreFullScreenRect.Top)); } ViewportSizeX = NewSizeX; ViewportSizeY = NewSizeY; WindowToResize->SetViewportSizeDrivenByWindow(true); } if (NewWindowMode != WindowMode) { // Only notify the HMD if we've actually changed modes GEngine->HMDDevice->OnScreenModeChange(NewWindowMode); } } LockMouseToViewport(!CurrentReplyState.ShouldReleaseMouseLock()); WindowToResize->Resize(FVector2D(NewSizeX, NewSizeY)); ResizeViewport(ViewportSizeX, ViewportSizeY, NewWindowMode, InPosX, InPosY); } UCanvas::UpdateAllCanvasSafeZoneData(); } } }
int32 SProgressBar::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { // Used to track the layer ID we will return. int32 RetLayerId = LayerId; bool bEnabled = ShouldBeEnabled( bParentEnabled ); const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; const FSlateBrush* CurrentFillImage = GetFillImage(); const FLinearColor FillColorAndOpacitySRGB(InWidgetStyle.GetColorAndOpacityTint() * FillColorAndOpacity.Get().GetColor(InWidgetStyle) * CurrentFillImage->GetTint(InWidgetStyle)); const FLinearColor ColorAndOpacitySRGB = InWidgetStyle.GetColorAndOpacityTint(); TOptional<float> ProgressFraction = Percent.Get(); // Paint inside the border only. // Pre-snap the clipping rect to try and reduce common jitter, since the padding is typically only a single pixel. FSlateRect SnappedClippingRect = FSlateRect(FMath::RoundToInt(MyClippingRect.Left), FMath::RoundToInt(MyClippingRect.Top), FMath::RoundToInt(MyClippingRect.Right), FMath::RoundToInt(MyClippingRect.Bottom)); const FSlateRect ForegroundClippingRect = SnappedClippingRect.InsetBy(FMargin(BorderPadding.Get().X, BorderPadding.Get().Y)); const FSlateBrush* CurrentBackgroundImage = GetBackgroundImage(); FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry(), CurrentBackgroundImage, SnappedClippingRect, DrawEffects, InWidgetStyle.GetColorAndOpacityTint() * CurrentBackgroundImage->GetTint( InWidgetStyle ) ); if( ProgressFraction.IsSet() ) { const float ClampedFraction = FMath::Clamp(ProgressFraction.GetValue(), 0.0f, 1.0f); switch (BarFillType) { case EProgressBarFillType::RightToLeft: { FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Left = ClippedAllotedGeometry.Right - ClippedAllotedGeometry.GetSize().X * ClampedFraction; // Draw Fill FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), CurrentFillImage, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); break; } case EProgressBarFillType::FillFromCenter: { // Draw Fill FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D( (AllottedGeometry.Size.X * 0.5f) - ((AllottedGeometry.Size.X * ( ClampedFraction ))*0.5), 0.0f), FVector2D( AllottedGeometry.Size.X * ( ClampedFraction ) , AllottedGeometry.Size.Y )), CurrentFillImage, ForegroundClippingRect, DrawEffects, FillColorAndOpacitySRGB ); break; } case EProgressBarFillType::TopToBottom: { FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Bottom = ClippedAllotedGeometry.Top + ClippedAllotedGeometry.GetSize().Y * ClampedFraction; // Draw Fill FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), CurrentFillImage, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); break; } case EProgressBarFillType::BottomToTop: { FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Top = ClippedAllotedGeometry.Bottom - ClippedAllotedGeometry.GetSize().Y * ClampedFraction; // Draw Fill FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), CurrentFillImage, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); break; } case EProgressBarFillType::LeftToRight: default: { FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Right = ClippedAllotedGeometry.Left + ClippedAllotedGeometry.GetSize().X * ClampedFraction; // Draw Fill FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), CurrentFillImage, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); break; } } } else { const FSlateBrush* CurrentMarqueeImage = GetMarqueeImage(); // Draw Marquee const float MarqueeAnimOffset = CurrentMarqueeImage->ImageSize.X * MarqueeOffset; const float MarqueeImageSize = CurrentMarqueeImage->ImageSize.X; FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D( MarqueeAnimOffset - MarqueeImageSize, 0.0f ), FVector2D( AllottedGeometry.Size.X + MarqueeImageSize, AllottedGeometry.Size.Y )), CurrentMarqueeImage, ForegroundClippingRect, DrawEffects, ColorAndOpacitySRGB ); } return RetLayerId - 1; }
int32 FSlateTextLayout::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { const FSlateRect ClippingRect = AllottedGeometry.GetClippingRect().IntersectionWith(MyClippingRect); const ESlateDrawEffect::Type DrawEffects = bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; static bool ShowDebug = false; FLinearColor BlockHue( 0, 1.0f, 1.0f, 0.5 ); int32 HighestLayerId = LayerId; for (const FTextLayout::FLineView& LineView : LineViews) { // Is this line visible? const FSlateRect LineViewRect(AllottedGeometry.AbsolutePosition + LineView.Offset, AllottedGeometry.AbsolutePosition + LineView.Offset + LineView.Size); const FSlateRect VisibleLineView = ClippingRect.IntersectionWith(LineViewRect); if (VisibleLineView.IsEmpty()) { continue; } // Render any underlays for this line const int32 HighestUnderlayLayerId = OnPaintHighlights( Args, LineView, LineView.UnderlayHighlights, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled ); const int32 BlockDebugLayer = HighestUnderlayLayerId; const int32 TextLayer = BlockDebugLayer + 1; int32 HighestBlockLayerId = TextLayer; // Render every block for this line for (const TSharedRef< ILayoutBlock >& Block : LineView.Blocks) { if ( ShowDebug ) { BlockHue.R += 50.0f; // The block size and offset values are pre-scaled, so we need to account for that when converting the block offsets into paint geometry const float InverseScale = Inverse(AllottedGeometry.Scale); FSlateDrawElement::MakeBox( OutDrawElements, BlockDebugLayer, AllottedGeometry.ToPaintGeometry(TransformVector(InverseScale, Block->GetSize()), FSlateLayoutTransform(TransformPoint(InverseScale, Block->GetLocationOffset()))), &DefaultTextStyle.HighlightShape, ClippingRect, DrawEffects, InWidgetStyle.GetColorAndOpacityTint() * BlockHue.HSVToLinearRGB() ); } const TSharedRef< ISlateRun > Run = StaticCastSharedRef< ISlateRun >( Block->GetRun() ); int32 HighestRunLayerId = TextLayer; const TSharedPtr< ISlateRunRenderer > RunRenderer = StaticCastSharedPtr< ISlateRunRenderer >( Block->GetRenderer() ); if ( RunRenderer.IsValid() ) { HighestRunLayerId = RunRenderer->OnPaint( Args, LineView, Run, Block, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, TextLayer, InWidgetStyle, bParentEnabled ); } else { HighestRunLayerId = Run->OnPaint( Args, LineView, Block, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, TextLayer, InWidgetStyle, bParentEnabled ); } HighestBlockLayerId = FMath::Max( HighestBlockLayerId, HighestRunLayerId ); } // Render any overlays for this line const int32 HighestOverlayLayerId = OnPaintHighlights( Args, LineView, LineView.OverlayHighlights, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, HighestBlockLayerId, InWidgetStyle, bParentEnabled ); HighestLayerId = FMath::Max( HighestLayerId, HighestOverlayLayerId ); } return HighestLayerId; }
void FSlateRemoteServer::ProcessTouchMessage( const FSlateRemoteServerMessage& Message ) { // @todo This should be some global value or something in slate?? static FVector2D LastTouchPositions[EKeys::NUM_TOUCH_KEYS]; if (Message.Handle < EKeys::NUM_TOUCH_KEYS) { FSlateApplication& SlateApplication = FSlateApplication::Get(); // convert from 0..1 to window coordinates to screen coordinates // @todo: Put this into a function in SlateApplication if (SlateApplication.GetActiveTopLevelWindow().IsValid()) { FVector2D ScreenPosition; // The remote is interested in finding the game viewport for the user and mapping the input in to it TSharedPtr<SViewport> GameViewport = SlateApplication.GetGameViewport(); if (GameViewport.IsValid()) { FWidgetPath WidgetPath; WidgetPath = GameViewportWidgetPath.ToWidgetPath(); if (WidgetPath.Widgets.Num() == 0 || WidgetPath.Widgets.Last().Widget != GameViewport) { SlateApplication.FindPathToWidget(GameViewport.ToSharedRef(), WidgetPath); GameViewportWidgetPath = WidgetPath; } const FGeometry& GameViewportGeometry = WidgetPath.Widgets.Last().Geometry; ScreenPosition = GameViewportGeometry.LocalToAbsolute(FVector2D(Message.Data[0], Message.Data[1]) * GameViewportGeometry.Size); } else { const FSlateRect WindowScreenRect = SlateApplication.GetActiveTopLevelWindow()->GetRectInScreen(); const FVector2D WindowPosition = WindowScreenRect.GetSize() * FVector2D(Message.Data[0], Message.Data[1]); ScreenPosition = FVector2D(WindowScreenRect.Left, WindowScreenRect.Top) + WindowPosition; } // for up/down messages, we need to let the cursor go in the same location // (mouse up with a delta confuses things) if (Message.DataType == DT_TouchBegan || Message.DataType == DT_TouchEnded) { LastTouchPositions[Message.Handle] = ScreenPosition; } // create the event struct FPointerEvent Event(0, Message.Handle, ScreenPosition, LastTouchPositions[Message.Handle], Message.DataType != DT_TouchEnded); LastTouchPositions[Message.Handle] = ScreenPosition; // send input to handler if (Message.DataType == DT_TouchBegan) { SlateApplication.ProcessTouchStartedEvent(nullptr, Event); } else if (Message.DataType == DT_TouchEnded) { SlateApplication.ProcessTouchEndedEvent(Event); } else { SlateApplication.ProcessTouchMovedEvent(Event); } } } else { //checkf(Message.Handle < ARRAY_COUNT(LastTouchPositions), TEXT("Received handle %d, but it's too big for our array"), Message.Handle); } }