UMG源码笔记

整理下最近学习UE4 UMG的进度。

1.UMG类视图

UMG 控件跟Unity UGUI不太一样,不是所有的控件节点,都能拥有子节点,为了区分这三种控件,整理了下他们基类:

  • UWidget : 所有UMG 控件的公共基类,不提供增加子节点功能
  • UPanelWidget : 提供了增加子节点功能,可以有多个子节点
  • UContentWidget : 继承于UPanelWidget,是UPanelWidget的一种特例,只能有一个子节点

UMG常用控件的继承关系如下图所示:

1.1 不能有子节点的控件如下:

这个类别的控件的公共基类都是UWidget,每个UMG控件,都持有一个Slate控件的智能指针。

1.2 可以增加子节点的控件:

1.2.1 可以有一个子节点控件

有一个子节点的控件继承的父类依次是 UComponentWidget -> UPanelWidget,父类UComponentWidget构造函数中设置了不允许多个孩子标记位:

UContentWidget::UContentWidget(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    bCanHaveMultipleChildren = false;
}

公共基类UPanelWidget定义了AddChild函数,可以增加对应的子节点:

UPanelSlot* UPanelWidget::AddChild(UWidget* Content)
{
    if ( Content == nullptr )
    {
        return nullptr;
    }

    if ( !bCanHaveMultipleChildren && GetChildrenCount() > 0 )
    {
        return nullptr;
    }

    Content->RemoveFromParent();

    EObjectFlags NewObjectFlags = RF_Transactional;
    if (HasAnyFlags(RF_Transient))
    {
        NewObjectFlags |= RF_Transient;
    }

    UPanelSlot* PanelSlot = NewObject<UPanelSlot>(this, GetSlotClass(), NAME_None, NewObjectFlags);
    PanelSlot->Content = Content;
    PanelSlot->Parent = this;

    Content->Slot = PanelSlot;

    Slots.Add(PanelSlot);

    OnSlotAdded(PanelSlot);

    InvalidateLayoutAndVolatility();

    return PanelSlot;
}

其中,GetSlotClass返回对应控件的Slot的类型,在类视图里,带红色方格的标记的,是各自控件GetSlotClass返回的Slot的类型。Slot会分别指向父节点跟子节点。

1.2.2 可以有多个子节点控件

1.3 Slate控件类视图

Slate中除了SWidget之外有三个基础类,其他控件都是继承者三个基类。

  • SPanel : 有多个子节点
  • SLeafWidget : 没有子节点
  • SCompoundWidget : 可以有一个子节点

2 UMG渲染流程

TODO