[4.16] Change in 4.16 causes asynch loading to never complete during certain editor actions

4.16 broke some DetailsCustomization code I had which worked fine in 4.15, and it looks like the cause may have more widespread repercussions.

In my project, there is a DetailsCustomization which adds a SComboButton to the details panel of a certain component. When the combo button is clicked, the contents generates a custom asset picker built around an SListView. The SListView includes an image preview thumbnail for the asset.

However, because of the large number of assets, this caused an annoying hitch when opening the combobox. Therefore, the asset images are loaded asynchronously. The items draw the same synchronously loaded “loading” thumbnail, with a callback which is called by the FStreamableManager notifying the object when the load has completed, causing it to update its image to point to the proper, now loaded asset.

This worked fine until 4.16. Now, the preview images never load while the combo button is open, but as soon as the combo button closes all of the callbacks suddenly fire at once. I believe the culprit is the FStreamableDelegateDelayHelper which was added as part of an integration of Fortnite stuff in this commit: https://github.com/EpicGames/UnrealEngine/commit/33c9ba59f2c7af57bab2a03bcea762d0a9e7ffec

The FStreamableDelegateDelayHelper basically delays the delegate (that in this case is the “OnComplete” event from the asynch load) by one frame. It does this by ticking, and only firing the callbacks on the tick after the load is marked as complete.

While the FStreamableDelegateDelayHelper is set to tick in editor, and while the game is paused, etc, I suspect what is happening is that the tick is getting suspended while the ComboButton is open. As a result, while the asynch load is completing, the FStreamableDelegateDelayHelper is causing the notification that it’s done to not fire until the combo box closes. (Which, in my case, makes it completely pointless to do since you no longer need the preview images.)

I don’t know whether this would happen in-game or not if the game has ComboButtons as part of the game UI, but it seems likely and is probably worth checking.

I should note that this doesn’t appear to be focus related. (Setting bIsFocusable=false on the SComboButton still prevents the FStreamableDelegateDelayHelper from ticking)

Anyhow, my workaround was to stop using the delegate notifications from the FStreamableManager at all. Instead, I changed the TAttribute provided to the SImage’s .Image Slate Property to poll the FStreamableHandle’s HasLoadcompleted() method and then return the preview FSlateBrush instead of the default “loading…” FSlateBrush if loading has completed. So I’m polling the streaming manager for completion as long as the preview is being drawn rather than waiting for it to notify me that it’s done on a tick that never happens.

This is a less than ideal solution since the .Image TAttribute only accepts const functions, so my workaround involved a const_cast. But it’s good enough for now.