UE4: How to get UMG widget position in screen space

Today the task in hand was to create an animation feedback of coins when the player collect coins while playing, or when he gets free coins.

The image show the feedback animation concept:

When the player hit the button Free Gift, coins will be spawned at the center of the button and play an animation as shown in the image, each coin will follow its curve till it arrives to the destination (End Location)

A problem I confronted while programming the coins animation is how to get absolute widgets locations regardless of the hierarchy they belongs to, or what layout panel are under it.

So in this tutorial we will see how to solve the problem and get absolute widgets locations.

As you see in the image bellow, we have two widgets that represent the start position and the end position of the animation, but you can clearly see that are nested inside different layout panels.

CollecteFeedbackUI_BP is the widget blueprint that will be spawned each time we want to play collect feedback animation.

CollecteFeedbackUI_BP, the canvas panel and the two images (that exist just for testing) have an anchor set to TopLeft

CollecteFeedbackUI_BP will contain a function that we call from GameOverUI_BP at the widget blueprint creation step when the player click on FreeGift button. The function sets the StartWidget, EndWidget and the ParentWidget of the spawner.

InitializeTargetWidgets sets the widgets that represent the start and end positions.

Below is the C++ implementation of InitializeTargetWidgets(…):

void UGDWCollecteFeedbackUI::InitializeTargetWidgets(class UWidget* InStartWidget, class UWidget* InEndWidget, class UWidget* InParentWidget)
 {
     StartWidget = InStartWidget;
     EndWidget = InEndWidget;
     ParentWidget = InParentWidget;
 }

The function SetCollecteFeedbackLocations() bellow sets the position of tho images Image_A (Start) and Image_B (End), these two images are for testing purposes only.

Note: To not confuse you, Image_A and Image_B are c++ references to PosImage_A_BP and PosImage_B_BP which are created in the blueprint.

void UGDWCollecteFeedbackUI::SetCollecteFeedbackLocations()
{
	FVector2D Pos_S =   GetWidgetCenterLocation(StartWidget);
	FVector2D Pos_E =   GetWidgetCenterLocation(EndWidget);

	if (Image_A && Image_A->Slot)
	{
		UCanvasPanelSlot* Slot = Cast<UCanvasPanelSlot>(Image_A->Slot);
		Slot->SetPosition(Pos_S);
	}
	if (Image_B && Image_B->Slot)
	{
		UCanvasPanelSlot* Slot = Cast<UCanvasPanelSlot>(Image_B->Slot);
		Slot->SetPosition(Pos_E);
	}
}

The last function GetWidgetCenterLocation(UWidget * Widget) gets a UWidget object reference as input and calculate the absolute position, the final result is a position of the center of that widget.

FVector2D UGDWCollecteFeedbackUI::GetWidgetCenterLocation(UWidget * Widget)
{
	FGeometry Geometry = ParentWidget->GetCachedGeometry();
	FVector2D Position = Geometry.AbsoluteToLocal(Widget->GetCachedGeometry().GetAbsolutePosition()) + Widget->GetCachedGeometry().GetLocalSize() / 2.0f;
	return Position;
}

I used cached geometry of the widgets to calculate the positions. First I get the absolute position of the widget:

Widget->GetCachedGeometry().GetAbsolutePosition()

Second, I convert the position from absolute to local relative to the root ParentWidget:

Geometry.AbsoluteToLocal(Widget->GetCachedGeometry().GetAbsolutePosition())

Lastly, I add the half of the size of the widget to get the center position:

FVector2D Position = Geometry.AbsoluteToLocal(Widget->GetCachedGeometry().GetAbsolutePosition()) + Widget->GetCachedGeometry().GetLocalSize() / 2.0f
The two target images are Image_A and Image_B, I create them to help me visualize the positions I calculated.

I hope this tutorial helped you. if you have any further questions leave me a comment.

Leave a Reply