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.
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;
}