unreal 自定义 Slate Style Sets

2016年12月06日 15:15 0 点赞 0 评论 更新于 2025-11-21 20:58

一、创建 xxStyle 类

首先,我们创建一个名为 TestStyles 的类,用于自定义 Slate Style Sets。这里没有使用 Unreal Editor 的创建向导,你也可以选择使用向导来创建。

1. TestStyles.h 文件内容

#pragma once
#include "SlateStyle.h"

class TestStyles
{
public:
static void Initialize();
static void Shutdown();
static const class ISlateStyle& Get();
static FName GetStyleSetName();

private:
static TSharedRef<class FSlateStyleSet> Create();
static TSharedPtr<class FSlateStyleSet> Instance;
};

2. TestStyles.cpp 文件内容

#include "Test05.h"
#include "TestStyles.h"
#include "SlateGameResources.h"

TSharedPtr<FSlateStyleSet> TestStyles::Instance = nullptr;

void TestStyles::Initialize()
{
if (!Instance.IsValid())
{
Instance = Create();
FSlateStyleRegistry::RegisterSlateStyle(*Instance);
}
}

void TestStyles::Shutdown()
{
FSlateStyleRegistry::UnRegisterSlateStyle(*Instance);
ensure(Instance.IsUnique());
Instance.Reset();
}

const class ISlateStyle& TestStyles::Get()
{
return *Instance;
}

FName TestStyles::GetStyleSetName()
{
static FName StyleSetName(TEXT("TestStyles"));
return StyleSetName;
}

TSharedRef<class FSlateStyleSet> TestStyles::Create()
{
return FSlateGameResources::New(TestStyles::GetStyleSetName(), "/game/ui", "/game/ui");
}

3. 资源路径注意事项

这里需要特别注意 FSlateGameResources 资源路径的相对位置。在 Unreal 中,/game 代替了 /context,存放在 /context 目录下的资源,在地址路径中要统一更名为 /game。这个路径非常重要,当遇到错误时,一定要检查该路径,看是否能找到 style 资源。

4. 初始化位置选择

在本文中,没有按照网页中作者的方式创建 GameModule,而是将 TestStyles 的初始化放在了自定义的 GameMode 中。实际上,只要能合理地让 TestStyles 初始化,放在哪里都可以,但可能需要考虑创建的时序性,目前暂不考虑这个问题。

AMyGameMode::AMyGameMode()
{
this->HUDClass = AMyHUD::StaticClass();
FSlateStyleRegistry::UnRegisterSlateStyle(TestStyles::GetStyleSetName()); // 参考网页的作者,只为防重复注册
TestStyles::Initialize();
}

二、创建由 Unreal Editor 向导生成的类

1. 操作步骤

在 Class 目录下创建 New Class,生成以下代码。

2. GlobalTestWidgetStyle.h 文件内容

#pragma once

#include "Styling/SlateWidgetStyle.h"
#include "SlateWidgetStyleContainerBase.h"

#include "GlobalTestWidgetStyle.generated.h"

/*
*
*/
USTRUCT()
struct TEST05_API FGlobalTestStyle : public FSlateWidgetStyle
{
GENERATED_USTRUCT_BODY()

public:
FGlobalTestStyle();
virtual ~FGlobalTestStyle();

// FSlateWidgetStyle
virtual void GetResources(TArray<const FSlateBrush*>& OutBrushes) const override;
static const FName TypeName;
virtual const FName GetTypeName() const override { return TypeName; }
static const FGlobalTestStyle& GetDefault();

UPROPERTY(EditAnywhere, Category = Appearance)
FTextBlockStyle textBlockStyle;
};

UCLASS(hidecategories = Object, MinimalAPI)
class UGlobalTestWidgetStyle : public USlateWidgetStyleContainerBase
{
GENERATED_BODY()

public:
/*
* The actual data describing the widget appearance.
*/
UPROPERTY(Category = Appearance, EditAnywhere, meta = (ShowOnlyInnerProperties))
FGlobalTestStyle WidgetStyle;

virtual const struct FSlateWidgetStyle* const GetStyle() const override
{
return static_cast<const struct FSlateWidgetStyle*>(&WidgetStyle);
}
};

3. GlobalTestWidgetStyle.cpp 文件内容

#include "Test05.h"
#include "GlobalTestWidgetStyle.h"

FGlobalTestStyle::FGlobalTestStyle()
{
}

FGlobalTestStyle::~FGlobalTestStyle()
{
}

const FName FGlobalTestStyle::TypeName(TEXT("FGlobalTestStyle"));

const FGlobalTestStyle& FGlobalTestStyle::GetDefault()
{
static FGlobalTestStyle Default;
return Default;
}

void FGlobalTestStyle::GetResources(TArray<const FSlateBrush*>& OutBrushes) const
{
}

三、创建和修改资源

1. 创建资源

在 Content 目录中创建 Style,地址要与之前 FSlateGameResources::New 中使用的地址一致,目前使用的是 /Game/ui 位置的地址,实际上该位置应替换为 /content/ui。创建后会得到一个资源,这个资源的名字很重要,后续需要对应上。

2. 修改资源内容

双击该资源修改里面的内容,由于自定义的 FSlateWidgetStyle 中定义了 FTextBlockStyle textBlockStyle,所以可以在这里修改字体和字体大小等属性。

UPROPERTY(EditAnywhere, Category = Appearance)
FTextBlockStyle textBlockStyle;

四、实例化显示

最后一步是实例化显示,以下是测试代码片段,写在 AMyHUD::BeginPlay 函数中。

void AMyHUD::BeginPlay()
{
// 注意,这里的 "TestButtonStyle01" 是资源的名字
auto ss = TestStyles::Get().GetWidgetStyle<FGlobalTestStyle>("TestButtonStyle01");
textBlock = SNew(STextBlock)
.TextStyle(&ss.textBlockStyle)
.Text(FText::FromString("Hello World !"));
GEngine->GameViewport->AddViewportWidgetContent(SNew(SWeakWidget).PossiblyNullContent(textBlock.ToSharedRef()));
}

完成以上所有步骤后,就可以看到显示效果了。

作者信息

孟子菇凉

孟子菇凉

共发布了 3994 篇文章