Files
UnrealEngine/Engine/Source/Runtime/UMG/Private/Components/TextBlock.cpp
2025-05-18 13:04:45 +08:00

519 lines
13 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Components/TextBlock.h"
#include "UObject/ConstructorHelpers.h"
#include "Engine/Font.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/SInvalidationPanel.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Widgets/SOverlay.h"
#include "Widgets/Images/SImage.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(TextBlock)
#define LOCTEXT_NAMESPACE "UMG"
/////////////////////////////////////////////////////
// UTextBlock
UTextBlock::UTextBlock(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bIsVariable = false;
bWrapWithInvalidationPanel = false;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
ShadowOffset = FVector2D(1.0f, 1.0f);
ColorAndOpacity = FLinearColor::White;
ShadowColorAndOpacity = FLinearColor::Transparent;
TextTransformPolicy = ETextTransformPolicy::None;
TextOverflowPolicy = ETextOverflowPolicy::Clip;
if (!IsRunningDedicatedServer())
{
static ConstructorHelpers::FObjectFinder<UFont> RobotoFontObj(*UWidget::GetDefaultFontName());
Font = FSlateFontInfo(RobotoFontObj.Object, 24, FName("Bold"));
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
#if WITH_EDITORONLY_DATA
AccessibleBehavior = ESlateAccessibleBehavior::Auto;
bCanChildrenBeAccessible = false;
#endif
}
void UTextBlock::ReleaseSlateResources(bool bReleaseChildren)
{
Super::ReleaseSlateResources(bReleaseChildren);
MyTextBlock.Reset();
}
PRAGMA_DISABLE_DEPRECATION_WARNINGS
FSlateColor UTextBlock::GetColorAndOpacity() const
{
if (ColorAndOpacityDelegate.IsBound() && !IsDesignTime())
{
return ColorAndOpacityDelegate.Execute();
}
else
{
return ColorAndOpacity;
}
}
void UTextBlock::SetColorAndOpacity(FSlateColor InColorAndOpacity)
{
ColorAndOpacity = InColorAndOpacity;
if( MyTextBlock.IsValid() )
{
MyTextBlock->SetColorAndOpacity( InColorAndOpacity );
}
}
void UTextBlock::SetOpacity(float InOpacity)
{
FLinearColor CurrentColor = ColorAndOpacity.GetSpecifiedColor();
CurrentColor.A = InOpacity;
SetColorAndOpacity(FSlateColor(CurrentColor));
}
FLinearColor UTextBlock::GetShadowColorAndOpacity() const
{
if (ShadowColorAndOpacityDelegate.IsBound() && !IsDesignTime())
{
return ShadowColorAndOpacityDelegate.Execute();
}
else
{
return ShadowColorAndOpacity;
}
}
void UTextBlock::SetShadowColorAndOpacity(FLinearColor InShadowColorAndOpacity)
{
ShadowColorAndOpacity = InShadowColorAndOpacity;
if( MyTextBlock.IsValid() )
{
MyTextBlock->SetShadowColorAndOpacity(InShadowColorAndOpacity);
}
}
FVector2D UTextBlock::GetShadowOffset() const
{
return ShadowOffset;
}
void UTextBlock::SetShadowOffset(FVector2D InShadowOffset)
{
ShadowOffset = InShadowOffset;
if( MyTextBlock.IsValid() )
{
MyTextBlock->SetShadowOffset(ShadowOffset);
}
}
const FSlateFontInfo& UTextBlock::GetFont() const
{
return Font;
}
void UTextBlock::SetFont(FSlateFontInfo InFontInfo)
{
Font = InFontInfo;
if (MyTextBlock.IsValid())
{
MyTextBlock->SetFont(Font);
}
OnFontChanged();
}
const FSlateBrush& UTextBlock::GetStrikeBrush() const
{
return StrikeBrush;
}
void UTextBlock::SetStrikeBrush(FSlateBrush InStrikeBrush)
{
StrikeBrush = InStrikeBrush;
if (MyTextBlock.IsValid())
{
MyTextBlock->SetStrikeBrush(&StrikeBrush);
}
}
void UTextBlock::OnShapedTextOptionsChanged(FShapedTextOptions InShapedTextOptions)
{
Super::OnShapedTextOptionsChanged(InShapedTextOptions);
if (MyTextBlock.IsValid())
{
InShapedTextOptions.SynchronizeShapedTextProperties(*MyTextBlock);
}
}
void UTextBlock::OnJustificationChanged(ETextJustify::Type InJustification)
{
Super::OnJustificationChanged(InJustification);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetJustification(InJustification);
}
}
void UTextBlock::OnWrappingPolicyChanged(ETextWrappingPolicy InWrappingPolicy)
{
Super::OnWrappingPolicyChanged(InWrappingPolicy);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetWrappingPolicy(InWrappingPolicy);
}
}
void UTextBlock::OnAutoWrapTextChanged(bool InAutoWrapText)
{
Super::OnAutoWrapTextChanged(InAutoWrapText);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetAutoWrapText(InAutoWrapText);
}
}
void UTextBlock::OnWrapTextAtChanged(float InWrapTextAt)
{
Super::OnWrapTextAtChanged(InWrapTextAt);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetWrapTextAt(InWrapTextAt);
}
}
void UTextBlock::OnLineHeightPercentageChanged(float InLineHeightPercentage)
{
Super::OnLineHeightPercentageChanged(InLineHeightPercentage);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetLineHeightPercentage(InLineHeightPercentage);
}
}
void UTextBlock::OnApplyLineHeightToBottomLineChanged(bool InApplyLineHeightToBottomLine)
{
Super::OnApplyLineHeightToBottomLineChanged(InApplyLineHeightToBottomLine);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetApplyLineHeightToBottomLine(InApplyLineHeightToBottomLine);
}
}
void UTextBlock::OnMarginChanged(const FMargin& InMargin)
{
Super::OnMarginChanged(InMargin);
if (MyTextBlock.IsValid())
{
MyTextBlock->SetMargin(InMargin);
}
}
float UTextBlock::GetMinDesiredWidth() const
{
return MinDesiredWidth;
}
void UTextBlock::SetMinDesiredWidth(float InMinDesiredWidth)
{
MinDesiredWidth = InMinDesiredWidth;
if (MyTextBlock.IsValid())
{
MyTextBlock->SetMinDesiredWidth(MinDesiredWidth);
}
}
void UTextBlock::SetAutoWrapText(bool InAutoWrapText)
{
AutoWrapText = InAutoWrapText;
if(MyTextBlock.IsValid())
{
MyTextBlock->SetAutoWrapText(InAutoWrapText);
}
}
ETextTransformPolicy UTextBlock::GetTextTransformPolicy() const
{
return TextTransformPolicy;
}
void UTextBlock::SetTextTransformPolicy(ETextTransformPolicy InTransformPolicy)
{
TextTransformPolicy = InTransformPolicy;
if(MyTextBlock.IsValid())
{
MyTextBlock->SetTransformPolicy(TextTransformPolicy);
}
}
ETextOverflowPolicy UTextBlock::GetTextOverflowPolicy() const
{
return TextOverflowPolicy;
}
void UTextBlock::SetTextOverflowPolicy(ETextOverflowPolicy InOverflowPolicy)
{
TextOverflowPolicy = InOverflowPolicy;
SynchronizeProperties();
}
void UTextBlock::SetFontMaterial(UMaterialInterface* InMaterial)
{
Font.FontMaterial = InMaterial;
SetFont(Font);
}
void UTextBlock::SetFontOutlineMaterial(UMaterialInterface* InMaterial)
{
Font.OutlineSettings.OutlineMaterial = InMaterial;
SetFont(Font);
}
UMaterialInstanceDynamic* UTextBlock::GetDynamicFontMaterial()
{
if (Font.FontMaterial)
{
UMaterialInterface* Material = CastChecked<UMaterialInterface>(Font.FontMaterial);
UMaterialInstanceDynamic* DynamicMaterial = Cast<UMaterialInstanceDynamic>(Material);
if (!DynamicMaterial)
{
DynamicMaterial = UMaterialInstanceDynamic::Create(Material, this);
Font.FontMaterial = DynamicMaterial;
SetFont(Font);
}
return DynamicMaterial;
}
return nullptr;
}
UMaterialInstanceDynamic* UTextBlock::GetDynamicOutlineMaterial()
{
if (Font.OutlineSettings.OutlineMaterial)
{
UMaterialInterface* Material = CastChecked<UMaterialInterface>(Font.OutlineSettings.OutlineMaterial);
UMaterialInstanceDynamic* DynamicMaterial = Cast<UMaterialInstanceDynamic>(Material);
if (!DynamicMaterial)
{
DynamicMaterial = UMaterialInstanceDynamic::Create(Material, this);
Font.OutlineSettings.OutlineMaterial = DynamicMaterial;
SetFont(Font);
}
return DynamicMaterial;
}
return nullptr;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
TSharedRef<SWidget> UTextBlock::RebuildWidget()
{
if (bWrapWithInvalidationPanel && !IsDesignTime())
{
TSharedPtr<SWidget> RetWidget = SNew(SInvalidationPanel)
[
SAssignNew(MyTextBlock, STextBlock)
.SimpleTextMode(bSimpleTextMode)
];
return RetWidget.ToSharedRef();
}
else
{
MyTextBlock =
SNew(STextBlock)
.SimpleTextMode(bSimpleTextMode);
//if (IsDesignTime())
//{
// return SNew(SOverlay)
// + SOverlay::Slot()
// [
// MyTextBlock.ToSharedRef()
// ]
// + SOverlay::Slot()
// .VAlign(VAlign_Top)
// .HAlign(HAlign_Right)
// [
// SNew(SImage)
// .Image(FCoreStyle::Get().GetBrush("Icons.Warning"))
// .Visibility_UObject(this, &ThisClass::GetTextWarningImageVisibility)
// .ToolTipText(LOCTEXT("TextNotLocalizedWarningToolTip", "This text is marked as 'culture invariant' and won't be gathered for localization.\nYou can change this by editing the advanced text settings."))
// ];
//}
return MyTextBlock.ToSharedRef();
}
}
PRAGMA_DISABLE_DEPRECATION_WARNINGS
EVisibility UTextBlock::GetTextWarningImageVisibility() const
{
return Text.IsCultureInvariant() ? EVisibility::Visible : EVisibility::Collapsed;
}
#if WITH_ACCESSIBILITY
TSharedPtr<SWidget> UTextBlock::GetAccessibleWidget() const
{
return MyTextBlock;
}
#endif
void UTextBlock::OnBindingChanged(const FName& Property)
{
Super::OnBindingChanged(Property);
if ( MyTextBlock.IsValid() )
{
static const FName TextProperty(TEXT("TextDelegate"));
static const FName ColorAndOpacityProperty(TEXT("ColorAndOpacityDelegate"));
static const FName ShadowColorAndOpacityProperty(TEXT("ShadowColorAndOpacityDelegate"));
if ( Property == TextProperty )
{
TAttribute<FText> TextBinding = GetDisplayText();
MyTextBlock->SetText(TextBinding);
}
else if ( Property == ColorAndOpacityProperty )
{
TAttribute<FSlateColor> ColorAndOpacityBinding = PROPERTY_BINDING(FSlateColor, ColorAndOpacity);
MyTextBlock->SetColorAndOpacity(ColorAndOpacityBinding);
}
else if ( Property == ShadowColorAndOpacityProperty )
{
TAttribute<FLinearColor> ShadowColorAndOpacityBinding = PROPERTY_BINDING(FLinearColor, ShadowColorAndOpacity);
MyTextBlock->SetShadowColorAndOpacity(ShadowColorAndOpacityBinding);
}
}
}
void UTextBlock::SynchronizeProperties()
{
Super::SynchronizeProperties();
TAttribute<FText> TextBinding = GetDisplayText();
TAttribute<FSlateColor> ColorAndOpacityBinding = PROPERTY_BINDING(FSlateColor, ColorAndOpacity);
TAttribute<FLinearColor> ShadowColorAndOpacityBinding = PROPERTY_BINDING(FLinearColor, ShadowColorAndOpacity);
if ( MyTextBlock.IsValid() )
{
MyTextBlock->SetText( TextBinding );
MyTextBlock->SetFont( Font );
MyTextBlock->SetStrikeBrush( &StrikeBrush );
MyTextBlock->SetColorAndOpacity( ColorAndOpacityBinding );
MyTextBlock->SetShadowOffset( ShadowOffset );
MyTextBlock->SetShadowColorAndOpacity( ShadowColorAndOpacityBinding );
MyTextBlock->SetMinDesiredWidth( MinDesiredWidth );
MyTextBlock->SetTransformPolicy( TextTransformPolicy );
MyTextBlock->SetOverflowPolicy(TextOverflowPolicy);
Super::SynchronizeTextLayoutProperties( *MyTextBlock );
}
}
/// @cond DOXYGEN_WARNINGS
FText UTextBlock::GetText() const
{
if (MyTextBlock.IsValid())
{
return MyTextBlock->GetText();
}
return Text;
}
/// @endcond
void UTextBlock::SetText(FText InText)
{
Text = InText;
TextDelegate.Unbind();
if ( MyTextBlock.IsValid() )
{
MyTextBlock->SetText(GetDisplayText());
}
OnTextChanged();
}
TAttribute<FText> UTextBlock::GetDisplayText()
{
return PROPERTY_BINDING(FText, Text);
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
#if WITH_EDITOR
FString UTextBlock::GetLabelMetadata() const
{
const int32 MaxSampleLength = 15;
FString TextStr = GetText().ToString().Replace(TEXT("\n"), TEXT(" "));
TextStr = TextStr.Len() <= MaxSampleLength ? TextStr : TextStr.Left(MaxSampleLength - 2) + TEXT("..");
return TEXT(" \"") + TextStr + TEXT("\"");
}
void UTextBlock::HandleTextCommitted(const FText& InText, ETextCommit::Type CommitteType)
{
//TODO UMG How will this migrate to the template? Seems to me we need the previews to have access to their templates!
//TODO UMG How will the user click the editable area? There is an overlay blocking input so that other widgets don't get them.
// Need a way to recognize one particular widget and forward things to them!
}
const FText UTextBlock::GetPaletteCategory()
{
return LOCTEXT("Common", "Common");
}
void UTextBlock::OnCreationFromPalette()
{
SetText(LOCTEXT("TextBlockDefaultValue", "Text Block"));
}
bool UTextBlock::CanEditChange(const FProperty* InProperty) const
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if (bSimpleTextMode && InProperty)
{
static TArray<FName> InvalidPropertiesInSimpleMode =
{
GET_MEMBER_NAME_CHECKED(UTextBlock, ShapedTextOptions),
GET_MEMBER_NAME_CHECKED(UTextBlock, Justification),
GET_MEMBER_NAME_CHECKED(UTextBlock, WrappingPolicy),
GET_MEMBER_NAME_CHECKED(UTextBlock, AutoWrapText),
GET_MEMBER_NAME_CHECKED(UTextBlock, WrapTextAt),
GET_MEMBER_NAME_CHECKED(UTextBlock, Margin),
GET_MEMBER_NAME_CHECKED(UTextBlock, LineHeightPercentage),
GET_MEMBER_NAME_CHECKED(UTextBlock, AutoWrapText),
};
return !InvalidPropertiesInSimpleMode.Contains(InProperty->GetFName());
}
return Super::CanEditChange(InProperty);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
#endif //if WITH_EDITOR
/////////////////////////////////////////////////////
#undef LOCTEXT_NAMESPACE