Fork me on GitHub

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,双击样式,添加图片

这样就完成了进入游戏后的菜单背景画面

 

 

 

 

 ==============================================================================

posted @ 2021-07-09 18:10  索智源  阅读(822)  评论(0编辑  收藏  举报