Description

Editor Utility Widgets (EUW) can be used to script editor behavior. One use case is the automation of asset creation.

A licensee has reported that when an EUW is used to create an asset, for as long as the EUW is still running attempting to delete the asset displays a general warning that the asset is still in use:

Some of the assets being deleted are still referenced in memory.

[Image Removed]

Upon reproducing the problem, this is because the running EUW blueprint's UberGraph (i.e. persistent event graph) is referencing the created asset. When assets are created in an EUW with a blueprint node that of the following format where the created asset reference is returned this reference is included in the asset deletion warning. Currently at least three blueprint function library functions provided by the engine can cause this when called from an EUW's uber graph:

[Image Removed]

This can be confirmed by manually finding references using FReferenceChainSearch in the same way that the asset deletion model does to choose to display the warning, see ObjectTools::GatherObjectReferencersForDeletion for usage of FReferenceChainSearch. See attached callstack for where the output of that is used to choose to display the asset deletion warning.

Current workaround:

  1. Editor Utility Widget creators can work around this by moving the asset creating node into a blueprint function graph. Since functions graphs don't have persistent state, their pins don't cause a persistent reference.
  2. Users can choose to force delete the referenced assets.

Requested behavior

Since the asset being referenced is a warning that users tend to take seriously and because currently no information is provided that the running EUW UberGraph is causing the reference, user friendliness of EUWs can be improved if:

  1. The state of a disconnected output pins isn't considered for an asset deletion warning. As an idea: FEditorDelegates::OnAssetsPreDelete is used for this in places in the engine code like FBlueprintActionDatabase.
  2. Or: display more information to the user via Log or in the asset deletion popup about what is causing the reference.
  3. Or: since ObjectTools::GatherObjectReferencersForDeletion is called specifically for deletion use cases, we could ignoring UFunctions as referencers that cause the warning to be displayed. The downside would be that if the EUW attempts to access the reference later, it becomes invalid. It may be more correct to actually show the warning. Specifically the disconnected pin situation was confusing to the reporter.

 

Steps to Reproduce

A clean repro project has been attached.

Repro steps in clean project:

  • Create an Editor Utility Widget (EUW) with a button
  • In its Event Graph, create a handler for that button that either:
    • calls Create New Control Rig Asset, output path = /Game/MyAsset, or
    • calls Render Target 2D Create Static Texture 2D Editor Only, output path = /Game/MyAsset
  • Run the EUW and click the button to create the asset
  • Browse to the created asset and try to delete it
  • Observe: The asset deletion modal shows the warning "Some of the assets being deleted are still referenced in memory."
  • Expected: The message is not displayed.

Repro steps in attached repro project (internal only):

  • Run the EUW: EU_ReproWidget
  • Click the "Create Reference" button. This create two assets in the Content folder.
  • Attempt to delete either of the two assets.
  • Observe: The asset deletion modal shows the warning "Some of the assets being deleted are still referenced in memory."
  • Expected: The message is not displayed.
Callstack

Non-fatal callstack

This callstack is how you can confirm that the Ubergraph UFunction is what causes the asset's pending delete warning. See local variable PendingDelete->MemoryReferences.ExternalReferences.

>    UnrealEditor-UnrealEd.dll!FAssetDeleteModel::Tick(const float InDeltaTime) Line 138    C++
     UnrealEditor-UnrealEd.dll!SDeleteAssetsDialog::TickDeleteModel(double InCurrentTime, float InDeltaTime) Line 606    C++
     [Inline Frame] UnrealEditor-UnrealEd.dll!Invoke(EActiveTimerReturnType(SDeleteAssetsDialog::*)(double, float)) Line 66    C++
     [Inline Frame] UnrealEditor-UnrealEd.dll!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(EActiveTimerReturnType(SDeleteAssetsDialog::*)(double, float) &) Line 317    C++
     UnrealEditor-UnrealEd.dll!TBaseSPMethodDelegateInstance<0,SDeleteAssetsDialog,1,enum EActiveTimerReturnType __cdecl(double,float),FDefaultDelegateUserPolicy>::Execute(double <Params_0>, float <Params_1>) Line 282    C++
     [Inline Frame] UnrealEditor-SlateCore.dll!TDelegate<enum EActiveTimerReturnType __cdecl(double,float),FDefaultDelegateUserPolicy>::Execute(double) Line 613    C++
     UnrealEditor-SlateCore.dll!FActiveTimerHandle::ExecuteIfPending(double CurrentTime, float DeltaTime) Line 48    C++
     UnrealEditor-SlateCore.dll!SWidget::ExecuteActiveTimers(double CurrentTime, float DeltaTime) Line 1865    C++
     UnrealEditor-SlateCore.dll!SWidget::Paint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 1436    C++
     UnrealEditor-SlateCore.dll!SPanel::PaintArrangedChildren(const FPaintArgs & Args, const FArrangedChildren & ArrangedChildren, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 34    C++
     UnrealEditor-SlateCore.dll!SPanel::OnPaint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 15    C++
     UnrealEditor-SlateCore.dll!SWidget::Paint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 1579    C++
     UnrealEditor-SlateCore.dll!SPanel::PaintArrangedChildren(const FPaintArgs & Args, const FArrangedChildren & ArrangedChildren, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 34    C++
     UnrealEditor-SlateCore.dll!SPanel::OnPaint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 15    C++
     UnrealEditor-SlateCore.dll!SWidget::Paint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 1579    C++
     UnrealEditor-SlateCore.dll!SOverlay::OnPaint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 209    C++
     UnrealEditor-SlateCore.dll!SWidget::Paint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 1579    C++
     UnrealEditor-SlateCore.dll!SCompoundWidget::OnPaint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 46    C++
     UnrealEditor-SlateCore.dll!SWidget::Paint(const FPaintArgs & Args, const FGeometry & AllottedGeometry, const FSlateRect & MyCullingRect, FSlateWindowElementList & OutDrawElements, int LayerId, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 1579    C++
     UnrealEditor-SlateCore.dll!SWindow::PaintSlowPath(const FSlateInvalidationContext & Context) Line 2085    C++
     UnrealEditor-SlateCore.dll!FSlateInvalidationRoot::PaintInvalidationRoot(const FSlateInvalidationContext & Context) Line 411    C++
     UnrealEditor-SlateCore.dll!SWindow::PaintWindow(double CurrentTime, float DeltaTime, FSlateWindowElementList & OutDrawElements, const FWidgetStyle & InWidgetStyle, bool bParentEnabled) Line 2119    C++
     UnrealEditor-Slate.dll!FSlateApplication::DrawWindowAndChildren(const TSharedRef<SWindow,1> & WindowToDraw, FDrawWindowArgs & DrawWindowArgs) Line 1176    C++
     UnrealEditor-Slate.dll!FSlateApplication::PrivateDrawWindows(TSharedPtr<SWindow,1> DrawOnlyThisWindow) Line 1383    C++
     UnrealEditor-Slate.dll!FSlateApplication::DrawWindows() Line 1120    C++
     UnrealEditor-Slate.dll!FSlateApplication::TickAndDrawWidgets(float DeltaTime) Line 1723    C++
     UnrealEditor-Slate.dll!FSlateApplication::AddModalWindow(TSharedRef<SWindow,1> InSlateWindow, const TSharedPtr<SWidget const ,1> InParentWidget, bool bSlowTaskWindow) Line 2166    C++
     UnrealEditor-UnrealEd.dll!UEditorEngine::EditorAddModalWindow(TSharedRef<SWindow,1> InModalWindow) Line 3899    C++
     UnrealEditor-UnrealEd.dll!ObjectTools::DeleteObjects(const TArray<UObject *,TSizedDefaultAllocator<32>> & InObjectsToDelete, bool bShowConfirmation, ObjectTools::EAllowCancelDuringDelete AllowCancelDuringDelete) Line 2915    C++
     UnrealEditor-UnrealEd.dll!ObjectTools::DeleteAssets(const TArray<FAssetData,TSizedDefaultAllocator<32>> & AssetsToDelete, bool bShowConfirmation) Line 2672    C++
     UnrealEditor-ContentBrowserAssetDataSource.dll!ContentBrowserAssetData::DeleteItems(IAssetTools * InAssetTools, IAssetRegistry * InAssetRegistry, const UContentBrowserDataSource * InOwnerDataSource, TArrayView<FContentBrowserItemData const ,int> InItems) Line 877    C++
     UnrealEditor-ContentBrowserAssetDataSource.dll!UContentBrowserAssetDataSource::BulkDeleteItems(TArrayView<FContentBrowserItemData const ,int> InItems) Line 2753    C++
     UnrealEditor-ContentBrowser.dll!FAssetContextMenu::ExecuteDelete() Line 1117    C++
     UnrealEditor-ContentBrowser.dll!SContentBrowser::HandleDeleteCommandExecute() Line 3898    C++
     [Inline Frame] UnrealEditor-ContentBrowser.dll!Invoke(void(SContentBrowser::*)()) Line 66    C++
     [Inline Frame] UnrealEditor-ContentBrowser.dll!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(SContentBrowser::*)() &) Line 317    C++
     UnrealEditor-ContentBrowser.dll!TBaseSPMethodDelegateInstance<0,SContentBrowser,1,void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfSafe() Line 299    C++
     [Inline Frame] UnrealEditor-Slate.dll!TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound() Line 634    C++
     UnrealEditor-Slate.dll!FUIAction::Execute() Line 139    C++
     UnrealEditor-Slate.dll!FUICommandList::ConditionalProcessCommandBindings(const FKey Key, bool bCtrl, bool bAlt, bool bShift, bool bCmd, bool bRepeat) Line 235    C++
     UnrealEditor-Slate.dll!FUICommandList::ProcessCommandBindings(const FKeyEvent & InKeyEvent) Line 179    C++
     UnrealEditor-ContentBrowser.dll!SContentBrowser::OnKeyDown(const FGeometry & MyGeometry, const FKeyEvent & InKeyEvent) Line 2407    C++
     [Inline Frame] UnrealEditor-Slate.dll!FSlateApplication::ProcessKeyDownEvent::__l22::<lambda_2>::operator()(const FArrangedWidget &) Line 4827    C++
     UnrealEditor-Slate.dll!FEventRouter::Route<FReply,FEventRouter::FBubblePolicy,FKeyEvent,`FSlateApplication::ProcessKeyDownEvent'::`22'::<lambda_2>>(FSlateApplication * ThisApplication, FEventRouter::FBubblePolicy RoutingPolicy, FKeyEvent EventCopy, const FSlateApplication::ProcessKeyDownEvent::__l22::<lambda_2> & Lambda, ESlateDebuggingInputEvent DebuggingInputEvent) Line 461    C++
     [Inline Frame] UnrealEditor-Slate.dll!FEventRouter::RouteAlongFocusPath(FSlateApplication *) Line 430    C++
     UnrealEditor-Slate.dll!FSlateApplication::ProcessKeyDownEvent(const FKeyEvent & InKeyEvent) Line 4823    C++
     UnrealEditor-Slate.dll!FSlateApplication::OnKeyDown(const int KeyCode, const unsigned int CharacterCode, const bool IsRepeat) Line 4734    C++
     UnrealEditor-ApplicationCore.dll!FWindowsApplication::ProcessDeferredMessage(const FDeferredWindowsMessage & DeferredMessage) Line 2105    C++
     UnrealEditor-ApplicationCore.dll!FWindowsApplication::DeferMessage(TSharedPtr<FWindowsWindow,1> & NativeWindow, HWND__ * InHWnd, unsigned int InMessage, unsigned __int64 InWParam, __int64 InLParam, int MouseX, int MouseY, unsigned int RawInputFlags) Line 2783    C++
     UnrealEditor-ApplicationCore.dll!FWindowsApplication::ProcessMessage(HWND__ * hwnd, unsigned int msg, unsigned __int64 wParam, __int64 lParam) Line 1944    C++
     [Inline Frame] UnrealEditor-ApplicationCore.dll!WindowsApplication_WndProc(HWND__ *) Line 939    C++
     UnrealEditor-ApplicationCore.dll!FWindowsApplication::AppWndProc(HWND__ * hwnd, unsigned int msg, unsigned __int64 wParam, __int64 lParam) Line 945    C++

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-226920 in the post.

1
Login to Vote

Unresolved
ComponentUE - Gameplay - Blueprint Runtime
Affects Versions5.4
Target Fix5.6
CreatedOct 8, 2024
UpdatedOct 9, 2024
View Jira Issue