I’m seeing RetainerBox returning a lower layer id than the one passed to it by its parent when its child has 0 size. widgets later in the tree use this lower layerId, and are thus drawn incorrectly.
[Image Removed]
The low LayerIdOut seems to come from this TextureSizeZero case in SRetainerWidget::OnPaint. Is there any reason the TextureSizeZero case shouldn’t also do the TextureSizeTooBig case?
int32 SRetainerWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
if (PaintResult == EPaintRetainedContentResult::TextureSizeTooBig)
{
return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
}
else if (PaintResult == EPaintRetainedContentResult::TextureSizeZero)
{
return GetCachedMaxLayerId();
}
}
Steps to Reproduce
Create a new WBP and inside it, put an Overlay with three children:
1. A red Image
2. A Retainer Box containing a size 0 child (e.g. a Collapsed image)
3. A blue Image
Expected: blue image renders on top
Actual: red image renders on top
Hi [Xiaohan [Content removed]
Sorry about the delay. I am looking into this now and should get back to you soon.
Best regards,
Vitor
Hi Xiaohan Zhang,
Thank you for the report and minimal repro steps, which were extremely helpful. I was able to reproduce this behavior here in all 5.x versions, including the latest source build, and it does seem to be a bug.
I just filed an internal bug report about this, you should be able to track progress on it here once the engine devs mark it as public: UE-352267.
If you are able to make changes to the engine source code, you can fix this by changing the return value of the SRetainerWidget::OnPaint() function when the condition (PaintResult == EPaintRetainedContentResult::TextureSizeZero) is true, as you noted. However, instead of calling SCompoundWidget::OnPaint() like in the “TextureSizeTooBig” case (which would attempt to draw the RetainerBox contents in unretained mode), I’d recommend simply returning the same LayerId that was passed into the function:
else if (PaintResult == EPaintRetainedContentResult::TextureSizeZero)
{
return LayerId;
}
The change above seems to resolve the issue on my end here. Please let me know if it works for you, and do not hesitate to ask if you need any further assistance.
Best regards,
Vitor