遊戲裏需要超鏈接,比如點擊文字或圖片然後會彈出tips。需要實現的是文字的可點擊和超鏈接內容的讀取。
如格式<a itemId="001">物品1</>
顯示文字 物品1 然後點擊後我們能夠知道是itemId=“001”
代碼如下:
頭文件:
#pragma once
#include "Components/RichTextBlockDecorator.h"
#include "CoreMinimal.h"
#include "HyperLinkRichTextBlockDecorator.generated.h"
class FRichHyperLinkData
{
public:
FRichHyperLinkData(UHyperLinkRichTextBlockDecorator* decorator, TMap<FString, FString> metaData);
FSimpleDelegate m_LinkDelegate;
};
class FRichInlineHyperLinkDecorator : public FRichTextDecorator
{
public:
FRichInlineHyperLinkDecorator(URichTextBlock* InOwner, UHyperLinkRichTextBlockDecorator* decorator);
virtual bool Supports(const FTextRunParseResults& RunParseResult, const FString& Text) const override;
protected:
virtual TSharedPtr<SWidget> CreateDecoratorWidget(const FTextRunInfo& RunInfo, const FTextBlockStyle& TextStyle) const override;
void ExplodeTextStyleInfo(TMap<FString, FString>& MetaData, FSlateFontInfo& OutFont, FLinearColor& OutFontColor) const;
UHyperLinkRichTextBlockDecorator* m_Decorator;
mutable FHyperlinkStyle m_Linkstyle;
mutable FSlateFontInfo m_DefaultFont;
mutable FSlateColor m_DefaultColor;
mutable TArray<FRichHyperLinkData> m_LinkData;
mutable uint8 m_curLinkIndex;
mutable FString m_Content;
};
//////////////////////////////////////////////////////////////////////////
UCLASS()
class RICHTEXTBLOCKDECORATOR_API UHyperLinkRichTextBlockDecorator : public URichTextBlockDecorator
{
GENERATED_BODY()
public:
UHyperLinkRichTextBlockDecorator(const FObjectInitializer& ObjectInitializer);
virtual TSharedPtr<ITextDecorator> CreateDecorator(URichTextBlock* InOwner) override;
UPROPERTY(EditAnywhere, Category = Appearance)
FHyperlinkStyle m_Style;
UFUNCTION(BlueprintNativeEvent)
void ClickFun(const TMap<FString, FString>& metaData);
};
cpp文件:
#include "HyperLinkRichTextBlockDecorator.h"
#include "Components/RichTextBlockDecorator.h"
#include "Widgets/Input/SRichTextHyperlink.h"
FRichHyperLinkData::FRichHyperLinkData(UHyperLinkRichTextBlockDecorator* decorator, TMap<FString, FString> metaData)
{
// m_Decorator = decorator;
// m_MetaData = metaData;
m_LinkDelegate.BindLambda([=]() {
if (decorator)
{
decorator->ClickFun(metaData);
}
});
}
UHyperLinkRichTextBlockDecorator::UHyperLinkRichTextBlockDecorator(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer)
{
}
FRichInlineHyperLinkDecorator::FRichInlineHyperLinkDecorator(URichTextBlock* InOwner, UHyperLinkRichTextBlockDecorator* decorator) :
FRichTextDecorator(InOwner)
{
m_Decorator = decorator;
m_Linkstyle = decorator->m_Style;
m_DefaultFont = m_Linkstyle.TextStyle.Font;
m_DefaultColor = m_Linkstyle.TextStyle.ColorAndOpacity;
}
bool FRichInlineHyperLinkDecorator::Supports(const FTextRunParseResults& RunParseResult, const FString& Text) const
{
if (RunParseResult.Name == TEXT("a"))
{
/*ExplodeTextStyleInfo(RunParseResult.MetaData)*/
TMap<FString, FString> metaData;
TArray<FString> keys;
RunParseResult.MetaData.GetKeys(keys);
for (int i = 0; i < keys.Num(); i++)
{
const FTextRange& curRange = RunParseResult.MetaData[keys[i]];
FString valueString = Text.Mid(curRange.BeginIndex, curRange.EndIndex - curRange.BeginIndex);
metaData.Add(keys[i], valueString);
}
if (metaData.Contains("font") || metaData.Contains("size") || metaData.Contains("style") || metaData.Contains("color"))
{
FSlateFontInfo OutFont;
FLinearColor OutColor;
ExplodeTextStyleInfo(metaData, OutFont, OutColor);
m_Linkstyle.TextStyle.SetFont(OutFont);
FSlateColor color = FSlateColor(OutColor);
m_Linkstyle.TextStyle.ColorAndOpacity = color;
}
else
{
m_Linkstyle.TextStyle.SetFont(m_DefaultFont);
m_Linkstyle.TextStyle.ColorAndOpacity = m_DefaultColor;
}
m_LinkData.Add(FRichHyperLinkData(m_Decorator, metaData));
m_curLinkIndex = m_LinkData.Num() - 1;
m_Content = Text.Mid(
RunParseResult.ContentRange.BeginIndex, RunParseResult.ContentRange.EndIndex - RunParseResult.ContentRange.BeginIndex);
return true;
}
return false;
}
void FRichInlineHyperLinkDecorator::ExplodeTextStyleInfo(
TMap<FString, FString>& MetaData, FSlateFontInfo& OutFont, FLinearColor& OutFontColor) const
{
OutFont = m_DefaultFont;
const FString* const FontFamilyString = MetaData.Find(TEXT("font"));
const FString* const FontSizeString = MetaData.Find(TEXT("size"));
const FString* const FontStyleString = MetaData.Find(TEXT("style"));
const FString* const FontColorString = MetaData.Find(TEXT("color"));
if (FontFamilyString)
{
FSoftObjectPath Font(**FontFamilyString);
if (UObject* FontAsset = Font.TryLoad())
{
OutFont.FontObject = FontAsset;
}
MetaData.Remove("font");
}
if (FontSizeString)
{
OutFont.Size = static_cast<uint8>(FPlatformString::Atoi(**FontSizeString));
MetaData.Remove("size");
}
if (FontStyleString)
{
OutFont.TypefaceFontName = FName(**FontStyleString);
MetaData.Remove("style");
}
OutFontColor = m_DefaultColor.GetSpecifiedColor();
if (FontColorString)
{
const FString& FontColorStringRef = *FontColorString;
// Is Hex color?
if (!FontColorStringRef.IsEmpty() && FontColorStringRef[0] == TCHAR('#'))
{
OutFontColor = FLinearColor(FColor::FromHex(FontColorStringRef));
}
else if (OutFontColor.InitFromString(*FontColorString))
{
// Initialized
}
else
{
OutFontColor = m_DefaultColor.GetSpecifiedColor();
}
MetaData.Remove("color");
}
}
TSharedPtr<SWidget> FRichInlineHyperLinkDecorator::CreateDecoratorWidget(
const FTextRunInfo& RunInfo, const FTextBlockStyle& TextStyle) const
{
const bool bWarnIfMissing = true;
TSharedPtr<FSlateHyperlinkRun::FWidgetViewModel> model = MakeShareable(new FSlateHyperlinkRun::FWidgetViewModel);
TSharedPtr<SRichTextHyperlink> link = SNew(SRichTextHyperlink, model.ToSharedRef())
.Text(FText::FromString(m_Content))
.Style(&m_Linkstyle)
.OnNavigate(m_LinkData[m_curLinkIndex].m_LinkDelegate);
return link;
}
//////////////////////////////////////////////////////////////////////////
TSharedPtr<ITextDecorator> UHyperLinkRichTextBlockDecorator::CreateDecorator(URichTextBlock* InOwner)
{
return MakeShareable(new FRichInlineHyperLinkDecorator(InOwner, this));
}
void UHyperLinkRichTextBlockDecorator::ClickFun_Implementation(const TMap<FString, FString>& metaData)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Red, "click link");
}
}
外部新建藍圖繼承UHyperLinkRichTextBlockDecorator然後重載ClickFun就可以在藍圖處理超鏈接的具體內容和邏輯
如果有圖片點擊的需求參考這個和引擎自身的URichTextBlockImageDecorator寫就行了
如果有文字顯示不了的問題,看一下是不是沒有設置字體
參考:
1.https://answers.unrealengine.com/questions/920385/umg-richtextblock-hyperlink-href-markup.html