Files
UnrealEngine/Engine/Source/Editor/UnrealEd/Private/BaseWidgetBlueprint.cpp
2025-05-18 13:04:45 +08:00

108 lines
3.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "BaseWidgetBlueprint.h"
#include "Components/Widget.h"
#include "Blueprint/WidgetTree.h"
#include "UObject/UObjectHash.h"
UBaseWidgetBlueprint::UBaseWidgetBlueprint(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
WidgetTree = CreateDefaultSubobject<UWidgetTree>(TEXT("WidgetTree"));
WidgetTree->SetFlags(RF_Transactional | RF_ArchetypeObject);
}
void UBaseWidgetBlueprint::PostLoad()
{
Super::PostLoad();
// Update any older widget trees that don't have the same flags.
WidgetTree->SetFlags(RF_Transactional | RF_ArchetypeObject);
// Clean up named slot content that somehow still refers to a parent widget. Nothing
// hosted inside of a named slot should have a Slot property set to anything.
// This shouldn't be the case, but has happened in the past due to various paste bugs
// so clean it up.
ForEachSourceWidget([&](UWidget* InWidget) {
if (INamedSlotInterface* NamedSlotHost = Cast<INamedSlotInterface>(InWidget))
{
TArray<FName> SlotNames;
NamedSlotHost->GetSlotNames(SlotNames);
for (FName SlotName : SlotNames)
{
if (UWidget* SlotContent = NamedSlotHost->GetContentForSlot(SlotName))
{
if (SlotContent->Slot)
{
SlotContent->Slot = nullptr;
}
}
}
}
});
// Clean up any cases where the root widget some how still has a valid reference to a non-existent
// slot parent. This shouldn't be the case, but has happened in the past due to various paste bugs
// so clean it up.
if (WidgetTree->RootWidget && WidgetTree->RootWidget->Slot)
{
WidgetTree->RootWidget->Slot = nullptr;
}
}
TArray<UWidget*> UBaseWidgetBlueprint::GetAllSourceWidgets()
{
TArray<UWidget*> Ret;
ForEachSourceWidgetImpl([&Ret](UWidget* Inner) {
Ret.Push(Inner);
});
return Ret;
}
TArray<const UWidget*> UBaseWidgetBlueprint::GetAllSourceWidgets() const
{
TArray<const UWidget*> Ret;
ForEachSourceWidgetImpl([&Ret](UWidget* Inner) {
Ret.Push(Inner);
});
return Ret;
}
void UBaseWidgetBlueprint::ForEachSourceWidget(TFunctionRef<void(UWidget*)> Fn)
{
ForEachSourceWidgetImpl(Fn);
}
void UBaseWidgetBlueprint::ForEachSourceWidget(TFunctionRef<void(UWidget*)> Fn) const
{
ForEachSourceWidgetImpl(Fn);
}
void UBaseWidgetBlueprint::ForEachSourceWidgetImpl(TFunctionRef<void(UWidget*)> Fn) const
{
// This exists in order to facilitate working with collections of UWidgets wo/
// relying on user implemented UWidget virtual functions. During blueprint compilation
// it is bad practice to call those virtual functions until the class is fully formed
// and reinstancing has finished. For instance, GetDefaultObject() calls in those user
// functions may create a CDO before the class has been linked, or even before
// all member variables have been generated:
UWidgetTree* WidgetTreeForCapture = WidgetTree;
bool bIncludeNestedObjects = true;
ForEachObjectWithOuter(
WidgetTree,
[Fn, WidgetTreeForCapture](UObject* Inner)
{
if (UWidget* AsWidget = Cast<UWidget>(Inner))
{
Fn(AsWidget);
}
},
!bIncludeNestedObjects,// Reject nested objects
RF_NoFlags,
EInternalObjectFlags::Garbage // Exclude Pending Kills
);
}