Slate控件树的连接
父子控件的连接是通过槽实现的,正常的UI实现的话,通过如下的方式:
class Widget
{
public:
std::vector<std::shared_ptr<Widget>> m_widgets;//一堆儿子,然后递归遍历控件
};
但是Slate通过这种方式:
class SCompoundWidget
{
//子槽
FCompoundWidgetOneChildSlot ChildSlot;
};
//由槽来持有儿子控件
至于为什么要这样做?因为Slate对槽赋予了布局的概念,槽还携带对齐、填充(padding)等属性。
然后槽类有很多,单独定义在每个控件类里面,有画板槽类,单一子槽等。
每个带有连接特质的控件都会在类里面定义一个槽类,比如SCompoundWidget可以挂一个儿子控件,SOverlay可以挂一堆儿子。
我们看看SOverlay的槽类:
class SOverlay : public SPanel
{
/*一个槽支持内容的对齐还有填充,还有z-order*/
class FOverlaySlot : public TBasicLayoutWidgetSlot<FOverlaySlot>
{
public:
FOverlaySlot(int32 InZOrder)
: TBasicLayoutWidgetSlot<FOverlaySlot>(HAlign_Fill, VAlign_Fill)
, ZOrder(InZOrder)
{}
public:
int32 ZOrder;
};
TPanelChildren<FOverlaySlot> Children;//SOverlay持有一个槽数组
}
TBasicLayoutWidgetSlot这个模板类,持有一个SWidget的智能指针,可以挂一个SWidget。类图可以在布局计算中查看。
TPanelChildren是一个类似数组的模板类,针对槽增加了一些比较好用的接口。
让我们看看UMG里面用的最多的控件SConstraintCanvas:
class SConstraintCanvas : public SPanel
{
class FSlot : public TSlotBase<FSlot>
{
public:
TAttribute<FMargin> OffsetAttr;
TAttribute<FAnchors> AnchorsAttr;
TAttribute<FVector2D> AlignmentAttr;
TAttribute<bool> AutoSizeAttr;
//TAttribute<float> ZOrderAttr;
float ZOrder;
};
TPanelChildren<FSlot> Children;
};
在布局计算这篇文章里面,布局的具体计算是在OnArrange这个虚函数里面,会在这个OnArrange里面根据槽的属性,计算布局,比如根据ZOrder计算出Layer,然后排列好,存放到FArrangedChildren(已经安排好的孩子)里面,FArrangedChildren类可以看看布局计算这篇文章,是个FArrangedWidget的数组,FArrangedWidget由SWidget和FGeometry组成。