Beispiel #1
0
void FSlateDrawElement::MakeCustom( FSlateWindowElementList& ElementList, uint32 InLayer, TSharedPtr<ICustomSlateElement, ESPMode::ThreadSafe> CustomDrawer )
{
	FSlateDrawElement& DrawElt = ElementList.AddUninitialized();
	DrawElt.Init(InLayer, FPaintGeometry(), FSlateRect(1,1,1,1), ESlateDrawEffect::None);
	DrawElt.RenderTransform = FSlateRenderTransform();
	DrawElt.ElementType = ET_Custom;
	DrawElt.DataPayload.SetCustomDrawerPayloadProperties( CustomDrawer );
}
void FSlateDrawElement::MakeCustom( FSlateWindowElementList& ElementList, uint32 InLayer, TSharedPtr<ICustomSlateElement, ESPMode::ThreadSafe> CustomDrawer )
{
	FSlateDrawElement& DrawElt = ElementList.AddUninitialized();
	DrawElt.ElementType = ET_Custom;
	DrawElt.Layer = InLayer;
	DrawElt.DataPayload.SetCustomDrawerPayloadProperties( CustomDrawer );
	DrawElt.ClippingRect = FSlateRect(1,1,1,1);
}
FSlateRect SPaperEditorViewport::PanelRectToGraphRect( const FSlateRect& PanelSpaceRect ) const
{
	FVector2D UpperLeft = PanelCoordToGraphCoord( FVector2D(PanelSpaceRect.Left, PanelSpaceRect.Top) );
	FVector2D LowerRight = PanelCoordToGraphCoord(  FVector2D(PanelSpaceRect.Right, PanelSpaceRect.Bottom) );

	return FSlateRect(
		UpperLeft.X, UpperLeft.Y,
		LowerRight.X, LowerRight.Y );
}
/** 
 * Called when the mouse was moved during a drag and drop operation
 *
 * @param DragDropEvent    The event that describes this drag drop operation.
 */
void FDockingDragOperation::OnDragged( const FDragDropEvent& DragDropEvent )
{
	const bool bPreviewingTarget = HoveredDockTarget.TargetNode.IsValid();
	if ( !bPreviewingTarget )
	{
		// The tab is being dragged. Move the the decorator window to match the cursor position.
		FVector2D TargetPosition = DragDropEvent.GetScreenSpacePosition() - GetDecoratorOffsetFromCursor();
		CursorDecoratorWindow->UpdateMorphTargetShape( FSlateRect(TargetPosition.X, TargetPosition.Y, TargetPosition.X + LastContentSize.X, TargetPosition.Y + LastContentSize.Y) );	
		CursorDecoratorWindow->MoveWindowTo( TargetPosition );
	}
}
Beispiel #5
0
void SMenuAnchor::Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime )
{
	SPanel::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	TSharedPtr<SWindow> PopupWindow = PopupWindowPtr.Pin();
	if ( PopupWindow.IsValid() && Method == CreateNewWindow )
	{
		// Figure out where our attached pop-up window should be placed.				
		const FVector2D PopupContentDesiredSize = PopupWindow->GetContent()->GetDesiredSize();
		FGeometry PopupGeometry = ComputeMenuPlacement( AllottedGeometry, PopupContentDesiredSize, Placement.Get( ) );
		const FVector2D NewPosition = PopupGeometry.AbsolutePosition;
		const FVector2D NewSize = PopupGeometry.GetDrawSize( );

		const FSlateRect NewShape = FSlateRect( NewPosition.X, NewPosition.Y, NewPosition.X + NewSize.X, NewPosition.Y + NewSize.Y );

		// We made a window for showing the popup.
		// Update the window's position!
		if( PopupWindow->IsMorphing() )
		{
			if( NewShape != PopupWindow->GetMorphTargetShape() )
			{
				// Update the target shape
				PopupWindow->UpdateMorphTargetShape( NewShape );
				// Set size immediately if not morphing size
				if(!PopupWindow->IsMorphingSize())
				{
					PopupWindow->ReshapeWindow( PopupWindow->GetPositionInScreen(), NewSize );
				}
			}
		}
		else
		{
			const FVector2D WindowPosition = PopupWindow->GetPositionInScreen();
			const FVector2D WindowSize = PopupWindow->GetSizeInScreen();
			if ( NewPosition != WindowPosition || NewSize != WindowSize )
			{
#if PLATFORM_LINUX
				// @FIXME: for some reason, popups reshaped here do not trigger OnWindowMoved() callback,
				// so we manually set cached position to where we expect it to be. Note the order of operations - (before Reshape) - 
				// still giving the callback a chance to change it.
				// This needs to be investigated (tracked as TTP #347674).
				PopupWindow->SetCachedScreenPosition( NewPosition );
#endif // PLATFORM_LINUX
				PopupWindow->ReshapeWindow( NewShape );
			}
		}
	}

	/** The tick is ending, so the window was not dismissed this tick. */
	bDismissedThisTick = false;
}
// !!! WRH 2014/08/25 - this is a brute-force, not efficient implementation, uses a bunch of extra conditionals.
FSlateRect FSlateRotatedRect::ToBoundingRect() const
{
	FVector2D Points[4] = 
	{
		TopLeft,
		TopLeft + ExtentX,
		TopLeft + ExtentY,
		TopLeft + ExtentX + ExtentY
	};
	return FSlateRect(
		FMath::Min(Points[0].X, FMath::Min3(Points[1].X, Points[2].X, Points[3].X)),
		FMath::Min(Points[0].Y, FMath::Min3(Points[1].Y, Points[2].Y, Points[3].Y)),
		FMath::Max(Points[0].X, FMath::Max3(Points[1].X, Points[2].X, Points[3].X)),
		FMath::Max(Points[0].Y, FMath::Max3(Points[1].Y, Points[2].Y, Points[3].Y))
		);
}
void IHeadMountedDisplay::PopPreFullScreenRect(FSlateRect& OutPreFullScreenRect)
{
	OutPreFullScreenRect = PreFullScreenRect;
	PreFullScreenRect = FSlateRect(-1.f, -1.f, -1.f, -1.f);
}
IHeadMountedDisplay::IHeadMountedDisplay()
{
	PreFullScreenRect = FSlateRect(-1.f, -1.f, -1.f, -1.f);
}
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
		);
	}
}
Beispiel #11
0
bool FGeometry::IsUnderLocation(const FVector2D& AbsoluteCoordinate) const
{
	// this render transform invert is a little expensive. We might consider caching it.
	return FSlateRect(FVector2D(0.0f, 0.0f), Size).ContainsPoint(TransformPoint(Inverse(GetAccumulatedRenderTransform()), AbsoluteCoordinate));
}
Beispiel #12
0
FSlateRect FGeometry::GetClippingRect() const
{
	return TransformRect(GetAccumulatedLayoutTransform(), FSlateRect(FVector2D(0.0f,0.0f), Size));
}
Beispiel #13
0
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;
}
FSlateRect FSlateRect::InsetBy( const FMargin& InsetAmount ) const
{
	return FSlateRect( Left + InsetAmount.Left, Top + InsetAmount.Top, Right - InsetAmount.Right, Bottom - InsetAmount.Bottom );
}
Beispiel #15
0
void SMenuAnchor::Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime )
{
	TSharedPtr<SWindow> PopupWindow = PopupWindowPtr.Pin();
	if ( PopupWindow.IsValid() && IsOpenViaCreatedWindow() )
	{
		// Figure out where our attached pop-up window should be placed.
		const FVector2D PopupContentDesiredSize = PopupWindow->GetContent()->GetDesiredSize();
		FGeometry PopupGeometry = ComputeMenuPlacement( AllottedGeometry, PopupContentDesiredSize, Placement.Get() );
		const FVector2D NewPosition = PopupGeometry.LocalToAbsolute(FVector2D::ZeroVector);
		// For the CreateWindow case, don't transform the size; it will always use the ApplicationScale
		const FVector2D NewSize = PopupGeometry.GetLocalSize();

		const FSlateRect NewShape = FSlateRect( NewPosition.X, NewPosition.Y, NewPosition.X + NewSize.X, NewPosition.Y + NewSize.Y );

		// We made a window for showing the popup.
		// Update the window's position!
		if (false /*PopupWindow->IsMorphing()*/ )
		{
			if( NewShape != PopupWindow->GetMorphTargetShape() )
			{
				// Update the target shape
				PopupWindow->UpdateMorphTargetShape( NewShape );
				// Set size immediately if not morphing size
				if(!PopupWindow->IsMorphingSize())
				{
					PopupWindow->ReshapeWindow( PopupWindow->GetPositionInScreen(), NewSize );
				}
			}
		}
		else
		{
			const FVector2D WindowPosition = PopupWindow->GetPositionInScreen();
			const FVector2D WindowSize = PopupWindow->GetSizeInScreen();
			if ( NewPosition != WindowPosition || NewSize != WindowSize )
			{
#if PLATFORM_LINUX
				// @FIXME: for some reason, popups reshaped here do not trigger OnWindowMoved() callback,
				// so we manually set cached position to where we expect it to be. Note the order of operations - (before Reshape) - 
				// still giving the callback a chance to change it.
				// This needs to be investigated (tracked as TTP #347674).
				PopupWindow->SetCachedScreenPosition( NewPosition );
#endif // PLATFORM_LINUX
				PopupWindow->ReshapeWindow( NewShape );
			}
		}
	}
	else if (PopupWindow.IsValid() && IsOpenAndReusingWindow())
	{
		// Ideally, do this in OnArrangeChildren(); currently not possible because OnArrangeChildren()
		// can be called in DesktopSpace or WindowSpace, and we will not know which version of the Window
		// geometry to use. Tick() is always in DesktopSpace, so cache the solution here and just use
		// it in OnArrangeChildren().
		const FPopupPlacement LocalPlacement(AllottedGeometry, Children[1].GetWidget()->GetDesiredSize(), Placement.Get());
		const FSlateRect WindowRectLocalSpace = TransformRect(Inverse(AllottedGeometry.GetAccumulatedLayoutTransform()), PopupWindow->GetClientRectInScreen());
		const FVector2D FittedPlacement = ComputePopupFitInRect(
			LocalPlacement.AnchorLocalSpace,
			FSlateRect(LocalPlacement.LocalPopupOffset, LocalPlacement.LocalPopupOffset + LocalPlacement.LocalPopupSize),
			LocalPlacement.Orientation, WindowRectLocalSpace);

		LocalPopupPosition = FittedPlacement;
		ScreenPopupPosition = AllottedGeometry.GetAccumulatedLayoutTransform().TransformPoint(LocalPopupPosition);
	}

	/** The tick is ending, so the window was not dismissed this tick. */
	bDismissedThisTick = false;
}