首先创建 xxStyle, 我这里测试就以 Test命名。
1 #pragma once 2 #include "SlateStyle.h" 3 4 class TestStyles 5 { 6 public: 7 static void Initialize(); 8 9 static void Shutdown(); 10 11 static const class ISlateStyle& Get(); 12 13 static FName GetStyleSetName(); 14 15 private: 16 17 static TSharedRef<class FSlateStyleSet> Create(); 18 19 static TSharedPtr<class FSlateStyleSet> Instance; 20 };
这个类是自己创建的,没有经过 UnrealEditor 的创建向导。(当然你也可以使用向导)
1 #include "Test05.h" 2 #include "TestStyles.h" 3 #include "SlateGameResources.h" 4 5 6 TSharedPtr<FSlateStyleSet> TestStyles::Instance = nullptr; 7 8 9 void TestStyles::Initialize() 10 { 11 if (!Instance.IsValid()) 12 { 13 Instance = Create(); 14 15 FSlateStyleRegistry::RegisterSlateStyle(*Instance); 16 } 17 } 18 19 void TestStyles::Shutdown() 20 { 21 FSlateStyleRegistry::UnRegisterSlateStyle(*Instance); 22 ensure(Instance.IsUnique()); 23 Instance.Reset(); 24 } 25 26 const class ISlateStyle& TestStyles::Get() 27 { 28 return *Instance; 29 } 30 31 FName TestStyles::GetStyleSetName() 32 { 33 static FName StyleSetName(TEXT("TestStyles")); 34 return StyleSetName; 35 } 36 37 TSharedRef<class FSlateStyleSet> TestStyles::Create() 38 { 39 return FSlateGameResources::New(TestStyles::GetStyleSetName(), "/game/ui", "/game/ui"); 40 }
这里需要注意:FSlateGameResources 资源路径的相对位置。 /game 代替了 /context, 存放在 /context 目录下的资源,统一在地址路径中更名为 /game。
这个路径很重要!遇到错误的时候,一定要回来看看这个路径,看看能否找到 style 资源。
在这里,我没有按照网页中作者的方式创建 GameModule。(事实上我尝试了,但我失败了,暂时不想在此花费时间,所以改路。我放在了自定义的GameMode中)。
我认为只要能合理化的让 TestStyles 初始化,放哪都不是问题,(当然或许需要考虑创建的时序性,但目前我还没此顾虑)。
1 AMyGameMode::AMyGameMode() 2 { 3 this->HUDClass = AMyHUD::StaticClass(); 4 FSlateStyleRegistry::UnRegisterSlateStyle(TestStyles::GetStyleSetName());// 参考网页的作者。只为防重复注册。 5 TestStyles::Initialize(); 6 }
下面这个类,是由 UnrealEditor 向导生成的,操作如下:
在 Class 目录下创建 New Class。
1 #pragma once 2 3 4 #include "Styling/SlateWidgetStyle.h" 5 #include "SlateWidgetStyleContainerBase.h" 6 7 #include "GlobalTestWidgetStyle.generated.h" 8 9 /** 10 * 11 */ 12 USTRUCT() 13 struct TEST05_API FGlobalTestStyle : public FSlateWidgetStyle 14 { 15 GENERATED_USTRUCT_BODY() 16 public: 17 18 FGlobalTestStyle(); 19 virtual ~FGlobalTestStyle(); 20 21 // FSlateWidgetStyle 22 virtual void GetResources(TArray<const FSlateBrush*>& OutBrushes) const override; 23 static const FName TypeName; 24 virtual const FName GetTypeName() const override { return TypeName; }; 25 static const FGlobalTestStyle& GetDefault(); 26 27 UPROPERTY(EditAnywhere, Category = Appearance) 28 FTextBlockStyle textBlockStyle; 29 }; 30 31 /** 32 */ 33 UCLASS(hidecategories=Object, MinimalAPI) 34 class UGlobalTestWidgetStyle : public USlateWidgetStyleContainerBase 35 { 36 GENERATED_BODY() 37 38 public: 39 /** The actual data describing the widget appearance. */ 40 UPROPERTY(Category=Appearance, EditAnywhere, meta=(ShowOnlyInnerProperties)) 41 FGlobalTestStyle WidgetStyle; 42 43 virtual const struct FSlateWidgetStyle* const GetStyle() const override 44 { 45 return static_cast< const struct FSlateWidgetStyle* >( &WidgetStyle ); 46 } 47 };
1 #include "Test05.h" 2 #include "GlobalTestWidgetStyle.h" 3 4 5 FGlobalTestStyle::FGlobalTestStyle() 6 { 7 8 } 9 10 FGlobalTestStyle::~FGlobalTestStyle() 11 { 12 } 13 14 const FName FGlobalTestStyle::TypeName(TEXT("FGlobalTestStyle")); 15 16 const FGlobalTestStyle& FGlobalTestStyle::GetDefault() 17 { 18 static FGlobalTestStyle Default; 19 return Default; 20 } 21 22 void FGlobalTestStyle::GetResources(TArray& OutBrushes) const 23 { 24 25 }
这里是重点, 我自己在作者的网页中没有看懂,最终咨询了同事后试验才找到正路。
在 Content 目录中创建 Style. 这个地址一定要是之前提到的 FSlateGameResources::New( 中使用的 地址,目前我用的是 /Game/ui 位置的地址,(参照上文解释)/Game/ui 的位置应该被替换成 /content/ui,如图:
得到一个资源,这个名字也很重要,之后要对应上。
现在就双击修改里面的内容。
这个东西会存在,就是因为自定义的 FSlateWidgetStyle 中定义了
1 UPROPERTY(EditAnywhere, Category = Appearance) 2 3 FTextBlockStyle textBlockStyle;
这正是它。
我修改了字体和字体大小。
到了最后一步,实例化显示了,测试代码片段如下,我写在
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())); }
所有步骤都做完了。可以显示了。效果如图: