🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
概述
Slate系统是UE的一套UI解决方案,UMG系统也是依赖Slate系统实现的。
问题:
- Slate系统是如何组织的?
- 控件树的父子关系是如何绑定的?
- Slate系统是如何渲染的?
- slate渲染结构和流程是如何组织的?
- 如何进行合批?
结构
SWidget控件类型
SWidget是Slate系统中所有控件的父类。
控件有三种类型。
叶控件 - 不带子槽的控件。如显示一块文本的 STextBlock。其原生便了解如何绘制文本。
面板 - 子槽数量为动态的控件。如垂直排列任意数量子项,形成一些布局规则的 SVerticalBox。
合成控件 - 子槽显式命名、数量固定的控件。如拥有一个名为 Content 的槽(包含按钮中所有控件)的 SButton。
– 官方文档
也有一些其他控件直接继承自SWidget,情况比较特殊,暂时忽略。
SWidget 控件树实现
上述控件三种类型中,其中SPanel、SCompoundWidget可以作为父节点,控件之间的父子关系是依赖Slot实现的。父控件引用Slot,Slot引用子控件并且保留子控件相对于父控件的布局信息。UMG的控件树的实现方式类似,以UCanvasPanel为例:
UCanvasPanel 控件树相关源码分析
相关类图
- UCanvasPanel有一个SConsntraintCanvas的引用,UCanvasPanel功能依赖SConsntraintCanvas实现。(组合关系)
Class UMG_API UCanvasPanel : public UPanelWidget
{
// ...
protected:
TSharedPtr<class SConstraintCanvas> MyCanvas;
// ...
}
- UCanvasPanel有一个Slot容器,AddChild会生成Slot并与Child互相绑定引用,然后把Slot放入Slot容器。
UCanvasPanelSlot* UCanvasPanel::AddChildToCanvas(UWidget* Content)
{
return Cast( Super::AddChild(Content) );
}
class UMG\_API UPanelWidget : public UWidget
{
// ...
protected:
TArray Slots;
// ...
}
UPanelSlot* UPanelWidget::AddChild(UWidget* Content)
{
// ...
UPanelSlot* PanelSlot = NewObject(this, GetSlotClass(), NAME\_None, NewObjectFlags);
PanelSlot->Content = Content;
PanelSlot->Parent = this;
Content->Slot = PanelSlot;
Slots.Add(PanelSlot);
OnSlotAdded(PanelSlot);
InvalidateLayoutAndVolatility();
return PanelSlot;
}
- 当UCanvasPanel增加一个UCanvasPanelSlot,其SConstraintCanvas引用也响应的添加一个FSlot(SConstraintCanvas::FSlot),且UCanvasPanelSlot保存FSlot的引用。
void UCanvasPanel::OnSlotAdded(UPanelSlot* InSlot)
{
// Add the child to the live canvas if it already exists
if ( MyCanvas.IsValid() )
{
CastChecked(InSlot)->BuildSlot(MyCanvas.ToSharedRef());
}
}
class UMG\_API UCanvasPanelSlot : public UPanelSlot
{
// ...
private:
SConstraintCanvas::FSlot* Slot;
// ...
}
void UCanvasPanelSlot::BuildSlot(TSharedRef Canvas)
{
Slot = &Canvas->AddSlot()
[
Content == nullptr ? SNullWidget::NullWidget : Content->TakeWidget()
];
SynchronizeProperties();
}
class SLATE\_API SConstraintCanvas : public SPanel
{
public:
class FSlot : public TSlotBase { /* Offset,Anchors,Alignment 等布局数据... */ }
// ...
protected:
TPanelChildren< FSlot > Children;