摘要:
本文主要介绍在C++中如何使用OnPaint函数去每帧的绘画文字,图片,线段,或者是其他的控件。
该功能一般使用的场景是用于小地图, 或者是其他的需要动态变化的UI界面,特别是当需要动态的去增加,删除各种控件的时候,一般都是用Onpaint函数去画出来。 该功能的实现主要是用Scompoundwidget类中的OnPaint函数去实现的,只要给一系列参数。
具体实现
一.创建一个SlateWidgetStyle,和一个普通的C++类,我们通过这个单例C++类来获取SlateWidgetStyle,这样可以避免SlateWidgetStyle重复注册,或者重复卸载。下面是普通C++类的实现,主要要代码是Create()函数通过路径去获取到引擎中的Style,接下来只要在主模块加载和卸载的时候分别去调用Initialze(),Shutdown()就可以了。然后去引擎中/Game/Widget/路径创建我们建立的SlateWidgetStyle并且命名为MySlate.
TSharedPtr<FSlateStyleSet>Slogin::StyleInstance = NULL;
void Slogin::Initialze()
{
if (!StyleInstance.IsValid())
{
StyleInstance = Create();
//把从编辑器中拿到的Style注册到FSlateStyleRegistry
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
}
}
FName Slogin::GetStyleSetName()
{
//随便给FSlateStyleName命一个名字
static FName SlateSetName(TEXT("juso do"));
return SlateSetName;
}
void Slogin::Shutdown()
{
//取消注册
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
ensure(StyleInstance.IsUnique());
StyleInstance.Reset();
}
const ISlateStyle& Slogin::Get()
{
return *StyleInstance;
}
TSharedRef<class FSlateStyleSet> Slogin::Create()
{
//根据系统路径获取SlateSyeleSet并且重新命名为GetStyleSetName返回的名字
TSharedRef<FSlateStyleSet> styleRef = FSlateGameResources::New(Slogin::GetStyleSetName(), "/Game/Widget/MySlate", "/Game/Widget/MySlate");
return styleRef;
}
二.在创建的SlateWidgetStyle中我们只要在.h文件写入我们需要的图片或者字体就可以了, 注意要写在.h文件中的第一个结构体下。
三.在新建一个SlateWidget,我们具体的绘制方法就在这里实现,利用重写的OnPaint()函数来绘制出我们需要的效果。具体实现代码如下。
注意具体使用从这里开始看就可以了。
int32 SMyDrawWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
//绘制文字
FSlateDrawElement::MakeText(
OutDrawElements,
LayerId + 10,
AllottedGeometry.ToPaintGeometry(FVector2D(50, 50), FVector2D(50,50)),
NSLOCTEXT("SlAiGame", "这个一个测试", "这个一个测试"),
Style->TextFont,//这里是一个上面定义的FSlateFontInfo
ESlateDrawEffect::None,
FLinearColor(1, 1, 1, 1)
);
//绘制文字
FSlateDrawElement::MakeText(
OutDrawElements,
LayerId + 10,
AllottedGeometry.ToPaintGeometry(FVector2D(960, 540), FVector2D(500, 500),1),
NSLOCTEXT("SlAiGame", "N", "N"),
Style->TextFont, //这里是一个上面定义的FSlateFontInfo
ESlateDrawEffect::None,
FLinearColor(1, 1, 1, 1)
);
//绘制图片
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId + 10,
AllottedGeometry.ToPaintGeometry(FVector2D(100, 100), FVector2D(50, 50)),
&Style->DrawBrushOne,//这里是一个上面定义的FSlateBrush
ESlateDrawEffect::None,
FLinearColor(1, 0, 0, 1)
);
return LayerId;
}
这里我们具体来讨论OnPaint函数所需要的参数和他们都是拿来干什么的,我们先看绘制文字的
FSlateDrawElement::MakeText(
OutDrawElements,
LayerId + 10,
AllottedGeometry.ToPaintGeometry(FVector2D(960, 540), FVector2D(500, 500),1),
NSLOCTEXT("SlAiGame", "N", "N"),
Style->TextFont,
ESlateDrawEffect::None,
FLinearColor(1, 1, 1, 1));
OutDrawElements,是需要绘画元素的列表,我们当前Make出来的Text,或者Image,或者什么其他的控件都会加入这个列表让这个函数去帮忙绘制。
LayerId, 是绘画当前元素的层级,当两个元素绘画在同一位置上的时候, 低层级的元素会被高层级的元素遮挡住。
AllottedGeometry,是当前元素的几何变化,关于坐标的转换一般都是利用它来实现的,我们调用它里面的ToPaintGeometry()来选择绘制元素的位置和大小,第一个Fvector2D传入的是LocalOffset,可以将其理解成是元素在屏幕中的位置,第二个FVctor2D传入的是当前绘制元素的大小,最后一个参数传入的是一个float类型的值,它表示当把窗口的缩放到当前值的时候,元素所在屏幕中的位置,后面无论窗口怎么缩放,绘画元素都会按最开始的比例显示在窗口上。
NSLOCTEXT(“SlAiGame”, “N”, “N”),一个本地化文字, 这就是你自己需要绘制的文字, 写什么都可以。
Style->TextFont, 这里给的是一个FslateFont就是字体的样式,其中Style是我在.h文件中声明的
const struct FMySlateStyle* Style; 它的赋值是在构造函数里面
Style = &Slogin::Get().GetWidgetStyle(“MySlate”);通过最开始写的单例去获取样式,这就就可以在编辑器中修改了。
ESlateDrawEffect::None, 这个是绘制元素的可以添加的效果,一般选择None就完全够用了。
FLinearColor(1, 1, 1, 1), 最后一个是绘制这个元素的前景色,可以改变字体的颜色。
以上就是绘制字体的时候所要填入的参数,当绘制图片的时候只需要一点小小的变化如下:
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId + 10,
AllottedGeometry.ToPaintGeometry(FVector2D(x, 100), FVector2D(50, 50)),
&Style->DrawBrushOne,
ESlateDrawEffect::None,
FLinearColor(1, 0, 0, 1));
前三个参数和最后两个参数同绘制字体的时候是一模一样的,不一样的是第四个参数, 它传入的是一个FslateBrush,就是所要绘制的图片。
四.效果展示
配置一个图片和一个字体样式