UE4C++Slate与C++DPI(屏幕自适应方式)设定
DPI原理
我们常常以在ProjectSetting->UserInterface->DPI Scaling的方式设置DPI,让物体基于一个边进行缩放
如图,图中以最短边为基础轴进行缩放,并设置俩个基点(540,0.5)与(1080,1),其窗口短边变化时候,从540 - 1080变化时,窗口内容按照0.5 - 1之间的缩放比例进行变化,而最短边大于1080或者小于540的时候,屏幕窗口内容都不会发生缩放变化,其中还有其他几种缩放形式,有兴趣的稍微懂点英文大概就知道什么意思了,再这也不过多赘述。
再次之前,我们将DPI设置成一条直线,便于看出我们代码中所自定义的DPI形式,如下图所示:
c++中创建我们自己的HUD
WorldSetting中设置我们的HUD
也许有些小伙伴在界面中找不到WorldSetting,打开方式见下图:
创建Slate Widget类型,用作HUD的中的内容显示
再次之前建议可以看看Slate的一些基础描述
- .h文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "GameSand_Style.h"
/**
*
*/
class GAME_SANDBOX_API SGameSand_HUD_Widget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SGameSand_HUD_Widget)
{}
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
private:
//用于绑定UIScaler的缩放系数
float GetUIScaler()const;
//获取屏幕尺寸
FVector2D GetViewportSize()const;
private:
//获取蓝图中的Menu样式,用作图片的资源样式设置
const struct FGameSand_MenuStyle* MenuStyle;
//DPI缩放系数
TAttribute<float>UIScaler;
};
- .cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "UI/SGameSand_HUD_Widget.h"
#include "SlateOptMacros.h"
#include "Widgets/Images/SImage.h"
#include "UI/GameSand_MenuWidgetStyle.h"
#include "UI/GameSand_Style.h"
#include "UI/GameSand_MenuWidgetStyle.h"
#include "Widgets/Layout/SDPIScaler.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SGameSand_HUD_Widget::Construct(const FArguments& InArgs)
{
//获取编辑器中的MenuStyle,这个获取方式只是封装了通过路径获取蓝图中的WidgetStyle
MenuStyle = &GameSand_Style::Get().GetWidgetStyle<FGameSand_MenuStyle>("BP_GameSand_Style");
//绑定缩放规则函数
UIScaler.Bind(this, &SGameSand_HUD_Widget::GetUIScaler);
ChildSlot
[
//创建DPI绑定其缩放规则,在下面的子类都根据这个规则进行缩放
SNew(SDPIScaler)
.DPIScale(UIScaler)
[
//创建Overlay,添加插槽
SNew(SOverlay)
+ SOverlay::Slot()
//设置其子类的布局方式,这里设置成FILL
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
//设置子类Padding
.Padding(FMargin(30.f))
[
//设置图片,并设置其笔刷
SNew(SImage)
//这里的MenuHUDBackgroundBrush是创建的笔刷,可以自己删除,这里是用作演示
.Image(&MenuStyle->MenuHUDBackgroundBrush)
]
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SImage)
//这里的MenuBackgroundBrush是创建的笔刷,可以自己删除,这里是用作演示
.Image(&MenuStyle->MenuBackgroundBrush)
]
]
];
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
float SGameSand_HUD_Widget::GetUIScaler() const
{
//DPI : Resolutuon 1080 ScaleY/1080.f
return GetViewportSize().Y / 1080.f;
}
FVector2D SGameSand_HUD_Widget::GetViewportSize() const
{
FVector2D Result(1920, 1080);
if (GEngine && GEngine->GameViewport)
//获取显示窗口大小,返回给Result
GEngine->GameViewport->GetViewportSize(Result);
return Result;
}
HUD中创建我们的Widget
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "Templates/SharedPointer.h"
#include "GameSand_HUD.generated.h"
/**
*
*/
UCLASS()
class GAME_SANDBOX_API AGameSand_HUD : public AHUD
{
GENERATED_BODY()
public:
AGameSand_HUD();
TSharedPtr<class SGameSand_HUD_Widget>GameSand_HUD_Widget;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "GamePlay/GameSand_HUD.h"
#include "UI/SGameSand_HUD_Widget.h"
AGameSand_HUD::AGameSand_HUD()
{
if (GEngine&&GEngine->GameViewport)
{
GameSand_HUD_Widget=SAssignNew(GameSand_HUD_Widget, SGameSand_HUD_Widget);
GEngine->GameViewport->AddViewportWidgetContent(GameSand_HUD_Widget.ToSharedRef());
}
}
在蓝图中找到自己创建的WidgetStyle,设置其图片等系列东西
通过短轴的拉伸,我们可以看到图片的DPI确实发生了变化