UE4 从无到有纯 C++ & Slate 开发沙盒游戏(三) 使用WidgetStyle设置样式
上一部分在界面中创建了一个按钮,但按钮太大,这部分将会设置按钮的样式
在UE4中创建两个类
1. 一个 Slate Widget Style 类,放置到UI/Style文件夹
2. 一个 C++的空类,也放置到 UI/Style 文件夹,我们要通过这个类获取WidgetStyle 的样式
写 SlAiStyle 的目的是为了获取 WidgetStyle 样式,以及把 Style 注册进游戏
SlAiStyle.h
#include "CoreMinimal.h" #include "SlateBasics.h" //ISlateStyle 头文件 class SLAICOURSE_API SlAiStyle { public: static void Initialze(); //游戏注册的名字 static FName GetStyleSetName(); //游戏关闭的时候取消注册 static void ShutDown(); //给外部调用,获取单例 static const ISlateStyle& Get(); private: //FSlateStyleSet类模板,用来注册样式 static TSharedRef<class FSlateStyleSet> Create(); //作为单例模式,这个变量一定不能放到构造函数里取实现 static TSharedPtr<FSlateStyleSet> SlAiStyleInstance; };
SlAiStyle.cpp
#include "UI/Style/SlAiStyle.h" TSharedPtr<FSlateStyleSet> SlAiStyle::SlAiStyleInstance = NULL; void SlAiStyle::Initialze() { //注册 SlAiStyleInstance 具体为啥需要看下源码 if (!SlAiStyleInstance.IsValid()) { SlAiStyleInstance = Create(); FSlateStyleRegistry::RegisterSlateStyle(*SlAiStyleInstance); } } FName SlAiStyle::GetStyleSetName() { static FName StyleSetName(TEXT("SlAiStyle")); return StyleSetName; } void SlAiStyle::ShutDown() { //取消注册 FSlateStyleRegistry::UnRegisterSlateStyle(*SlAiStyleInstance); //确保是唯一的 ensure(SlAiStyleInstance.IsUnique()); //重置 SlAiStyleInstance.Reset(); } const ISlateStyle& SlAiStyle::Get() { return *SlAiStyleInstance; } TSharedRef<class FSlateStyleSet> SlAiStyle::Create() { //蓝图所存放的路径 TSharedRef<FSlateStyleSet> StyleRef = FSlateGameResources::New(SlAiStyle::GetStyleSetName(), "/Game/UI/Style", "/Game/UI/Style"); return StyleRef; }
由于外部调用 SlAiStyle::Get() 的时候 SlAiStyleInstance 可能为 NULL,所以需要在项目下的 SlAiCourse.h 添加初始化和卸载的代码
SlAiCourse.h
#include "CoreMinimal.h" class FSlAiCourceModule : public FDefaultGameModuleImpl { public: //模组加载时的方法 virtual void StartupModule() override; //模组卸载时的方法 virtual void ShutdownModule() override; };
SlAiCourse.cpp
#include "SlAiCourse.h" #include "Modules/ModuleManager.h" #include "UI/Style/SlAiStyle.h" //需要用到SlAiStyle的初始化和卸载函数 void FSlAiCourceModule::StartupModule() { //初始化样式 FSlateStyleRegistry::UnRegisterSlateStyle(SlAiStyle::GetStyleSetName()); //先取消注册 SlAiStyle::Initialze(); //初始化 } void FSlAiCourceModule::ShutdownModule() { //注销 SlAiStyle::ShutDown(); } IMPLEMENT_PRIMARY_GAME_MODULE(FSlAiCourceModule, SlAiCourse, "SlAiCourse");
样式写好了,但没有什么样式可以让他获取,所以去 SlAiMenuWidgetStyle.h 定义一个笔刷
SlAiMenuWidgetStyle.h
struct SLAICOURSE_API FSlAiMenuStyle : public FSlateWidgetStyle //构造体 { …… //定义一个笔刷 UPROPERTY(EditAnywhere, Category = MenuHUD) FSlateBrush MenuHUDBackgroundBrush; };
然后再HUD下放置一张背景图片
在 SSlAiMenuHUDWidget.cpp 文件中添加
#include …… #include "Widgets/Images/SImage.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SSlAiMenuHUDWidget::Construct(const FArguments& InArgs) { ChildSlot //ChildSlot 是层级一样的东西 [ SNew(SImage) ]; } END_SLATE_FUNCTION_BUILD_OPTIMIZATION
SSlAiMenuHUDWidget.h
#include "CoreMinimal.h" #include "Widgets/SCompoundWidget.h" class SLAICOURSE_API SSlAiMenuHUDWidget : public SCompoundWidget { public: …… private: //获取Menu样式,MenuStyle这个结构体指针对应的就是编辑器中蓝图继承这个样式的那个资源 const struct FSlAiMenuStyle* MenuStyle; };
定义一个笔刷
SlAiMenuWidgetStyle.h
#include …… #include "Styling\SlateBrush.h" USTRUCT() struct SLAICOURSE_API FSlAiMenuStyle : public FSlateWidgetStyle //构造体 { …… //定义一个笔刷 UPROPERTY(EditAnywhere, Category = MenuHUD) FSlateBrush MenuHUDBackgroundBrush; };
将笔刷添加到Image组件
SSlAiMenuHUDWidget.cpp
#include …… #include "UI/Style/SlAiStyle.h" #include "UI/Style/SlAiMenuWidgetStyle.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SSlAiMenuHUDWidget::Construct(const FArguments& InArgs) { //获取编辑器的MenuStule的名字 MenuStyle = &SlAiStyle::Get().GetWidgetStyle<FSlAiMenuStyle>("BPSlAiMenuStyle"); ChildSlot //ChildSlot 是层级一样的东西 [ //先实例化一个Image组件,给这个组件添加一个Image,给Image一个笔刷 SNew(SImage) .Image(&MenuStyle->MenuHUDBackgroundBrush) ]; } END_SLATE_FUNCTION_BUILD_OPTIMIZATION
现在还没有样式,在编辑器中新建一个样式,让它继承这个类
在 Content 下新建一个文件夹 UI
在 UI 文件夹下新建一个样式文件夹 Style,右侧面板右键点击 User Interface 选择 Slate Widget Style
出现如下面板,选择要继承的类,继承刚才写的SlAiMenuWidgetStyle
将样式名字改为 BPSlAiMenuStyle,双击样式,添加图片
这样就完成了进入游戏后的菜单背景画面
==============================================================================