// Copyright Epic Games, Inc. All Rights Reserved. #include "Widgets/UIExtensionPointWidget.h" #include "Editor/WidgetCompilerLog.h" #include "Misc/UObjectToken.h" #include "UIExtensionSystem.h" #include "CommonLocalPlayer.h" #include "GameFramework/PlayerState.h" #define LOCTEXT_NAMESPACE "UIExtension" ///////////////////////////////////////////////////// // UUIExtensionPointWidget UUIExtensionPointWidget::UUIExtensionPointWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } void UUIExtensionPointWidget::ReleaseSlateResources(bool bReleaseChildren) { ResetExtensionPoint(); Super::ReleaseSlateResources(bReleaseChildren); } TSharedRef UUIExtensionPointWidget::RebuildWidget() { if (!IsDesignTime() && ExtensionPointTag.IsValid()) { ResetExtensionPoint(); RegisterExtensionPoint(); FDelegateHandle Handle = GetOwningLocalPlayer()->CallAndRegister_OnPlayerStateSet( UCommonLocalPlayer::FPlayerStateSetDelegate::FDelegate::CreateUObject(this, &UUIExtensionPointWidget::RegisterExtensionPointForPlayerState) ); } if (IsDesignTime()) { auto GetExtensionPointText = [this]() { return FText::Format(LOCTEXT("DesignTime_ExtensionPointLabel", "Extension Point\n{0}"), FText::FromName(ExtensionPointTag.GetTagName())); }; TSharedRef MessageBox = SNew(SOverlay); MessageBox->AddSlot() .Padding(5.0f) .HAlign(HAlign_Center) .VAlign(VAlign_Center) [ SNew(STextBlock) .Justification(ETextJustify::Center) .Text_Lambda(GetExtensionPointText) ]; return MessageBox; } else { return Super::RebuildWidget(); } } void UUIExtensionPointWidget::ResetExtensionPoint() { ResetInternal(); ExtensionMapping.Reset(); for (FUIExtensionPointHandle& Handle : ExtensionPointHandles) { Handle.Unregister(); } ExtensionPointHandles.Reset(); } void UUIExtensionPointWidget::RegisterExtensionPoint() { if (UUIExtensionSubsystem* ExtensionSubsystem = GetWorld()->GetSubsystem()) { TArray AllowedDataClasses; AllowedDataClasses.Add(UUserWidget::StaticClass()); AllowedDataClasses.Append(DataClasses); ExtensionPointHandles.Add(ExtensionSubsystem->RegisterExtensionPoint( ExtensionPointTag, ExtensionPointTagMatch, AllowedDataClasses, FExtendExtensionPointDelegate::CreateUObject(this, &ThisClass::OnAddOrRemoveExtension) )); ExtensionPointHandles.Add(ExtensionSubsystem->RegisterExtensionPointForContext( ExtensionPointTag, GetOwningLocalPlayer(), ExtensionPointTagMatch, AllowedDataClasses, FExtendExtensionPointDelegate::CreateUObject(this, &ThisClass::OnAddOrRemoveExtension) )); } } void UUIExtensionPointWidget::RegisterExtensionPointForPlayerState(UCommonLocalPlayer* LocalPlayer, APlayerState* PlayerState) { if (UUIExtensionSubsystem* ExtensionSubsystem = GetWorld()->GetSubsystem()) { TArray AllowedDataClasses; AllowedDataClasses.Add(UUserWidget::StaticClass()); AllowedDataClasses.Append(DataClasses); ExtensionPointHandles.Add(ExtensionSubsystem->RegisterExtensionPointForContext( ExtensionPointTag, PlayerState, ExtensionPointTagMatch, AllowedDataClasses, FExtendExtensionPointDelegate::CreateUObject(this, &ThisClass::OnAddOrRemoveExtension) )); } } void UUIExtensionPointWidget::OnAddOrRemoveExtension(EUIExtensionAction Action, const FUIExtensionRequest& Request) { if (Action == EUIExtensionAction::Added) { UObject* Data = Request.Data; TSubclassOf WidgetClass(Cast(Data)); if (WidgetClass) { UUserWidget* Widget = CreateEntryInternal(WidgetClass); ExtensionMapping.Add(Request.ExtensionHandle, Widget); } else if (DataClasses.Num() > 0) { if (GetWidgetClassForData.IsBound()) { WidgetClass = GetWidgetClassForData.Execute(Data); // If the data is irrelevant they can just return no widget class. if (WidgetClass) { if (UUserWidget* Widget = CreateEntryInternal(WidgetClass)) { ExtensionMapping.Add(Request.ExtensionHandle, Widget); ConfigureWidgetForData.ExecuteIfBound(Widget, Data); } } } } } else { if (UUserWidget* Extension = ExtensionMapping.FindRef(Request.ExtensionHandle)) { RemoveEntryInternal(Extension); ExtensionMapping.Remove(Request.ExtensionHandle); } } } #if WITH_EDITOR void UUIExtensionPointWidget::ValidateCompiledDefaults(IWidgetCompilerLog& CompileLog) const { Super::ValidateCompiledDefaults(CompileLog); // We don't care if the CDO doesn't have a specific tag. if (!HasAnyFlags(RF_ClassDefaultObject)) { if (!ExtensionPointTag.IsValid()) { TSharedRef Message = CompileLog.Error(FText::Format(LOCTEXT("UUIExtensionPointWidget_NoTag", "{0} has no ExtensionPointTag specified - All extension points must specify a tag so they can be located."), FText::FromString(GetName()))); Message->AddToken(FUObjectToken::Create(this)); } } } #endif ///////////////////////////////////////////////////// #undef LOCTEXT_NAMESPACE