174 lines
5.1 KiB
C++
174 lines
5.1 KiB
C++
|
// 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<SWidget> UUIExtensionPointWidget::RebuildWidget()
|
||
|
{
|
||
|
if (!IsDesignTime() && ExtensionPointTag.IsValid())
|
||
|
{
|
||
|
ResetExtensionPoint();
|
||
|
RegisterExtensionPoint();
|
||
|
|
||
|
FDelegateHandle Handle = GetOwningLocalPlayer<UCommonLocalPlayer>()->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<SOverlay> 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<UUIExtensionSubsystem>())
|
||
|
{
|
||
|
TArray<UClass*> 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<UUIExtensionSubsystem>())
|
||
|
{
|
||
|
TArray<UClass*> 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<UUserWidget> WidgetClass(Cast<UClass>(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<FTokenizedMessage> 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
|