How to get the position of the widget relative to the viewport center in Unreal Engine

Jul, 17 2021— #advanced

Here I will explain how to get the position of the widget so that the value "0" is the center of the screen (or parent widget). Accordingly, if the widget is to the left, then the value of its position will be negative, if to the right - positive.

This can be useful for creating your own scroller or scrollbox, or in other cases when the coordinates of the center of the parent widget (or viewport) relative to the center of the child widget are important.

An illustration of how this can work (the width of the parent widget is 1000, 0 is the center, -500 is the left edge, 500 is the right edge. Calculated relative to the center of the child and parent widget)

An illustration of how this can work (the width of the parent widget is 1000, 0 is the center, -500 is the left edge, 500 is the right edge. Calculated relative to the center of the child and parent widget)

First, we need to get the cached geometry (or geometry obtained on a tick) of the child widget.

Then call the "Local to Viewport" function to convert the local coordinates of the geometry to coordinates in the Viewport.

Next, we need to call "Get Local Size" on the geometry to get the size of the widget in local space, and divide by two (to get half the size of the widget, which means its center).

Then you need to add the value obtained from "Local to Viewport" with the value obtained in the paragraph with "Get Local Size". That's all for the mathematics of working with a child widget.

Next is the parent widget. You need to get the cached geometry and then call "Get Local Size" to get the size in local coordinates. Then just divide by two to get half the screen (parent widget) size.

At the end, you need to subtract the value obtained when calculating the child widget from the value obtained in the parent widget.

This screenshot shows how it looks like. In this example, I was only interested in the X-axis (since I was implementing a horizontal scrollbox), but you can use the Y-axis as well, or even two axes.

Here's the same thing, but in C++:

float UWidgetDefinition::GetWidgetXDistanceBetweenCenter(UObject* WorldContextObject, UWidget* ParentWidgetRef,
                                                         UWidget* ChildWidgetRef)
{
	const FGeometry ParentGeometry = ParentWidgetRef->GetCachedGeometry();
	const FGeometry ChildGeometry = ChildWidgetRef->GetCachedGeometry();

	FVector2D UnusedChildPixelPosition, ChildViewportPosition;
	USlateBlueprintLibrary::LocalToViewport(WorldContextObject, ChildGeometry, FVector2D(0),
	                                        UnusedChildPixelPosition, ChildViewportPosition);
	const float ChildHalfSize = ChildGeometry.GetLocalSize().X / 2.0f;

	const float ChildXPositionWithSize = ChildViewportPosition.X + ChildHalfSize;
	const float ParentHalfSize = ParentGeometry.GetLocalSize().X / 2.0f;

	return ChildXPositionWithSize - ParentHalfSize;
}

However, if you are using C++, you can simplify your code using "GetAbsolutePosition", which is not available in Blueprints:

float UWidgetDefinition::GetWidgetXDistanceBetweenCenter(UWidget* ParentWidgetRef, UWidget* ChildWidgetRef)
{
	const FGeometry ParentGeometry = ParentWidgetRef->GetCachedGeometry();
	const FGeometry ChildGeometry = ChildWidgetRef->GetCachedGeometry();
	
	const float ChildPosition = (ParentGeometry.AbsoluteToLocal(ChildGeometry.GetAbsolutePosition()) + (ChildGeometry.GetLocalSize() / 2)).X;
	const float ParentPosition = (ParentGeometry.GetLocalSize() * FVector2D(0.5f, 0.5f)).X;
	
	const float ChildRelativePosition = ChildPosition - ParentPosition;
	
	return ChildRelativePosition;
}
By Georgy Treshchev

Unreal Engine Developer. Contact for any questions. Telegram chat, e-mail, Github.