5、CanvasUpdateRegistry

CanvasUpdateRegistry(画布更新注册处)是一个单例,它是UGUI与Canvas之间的中介,继承了ICanvasElement接口的组件都可以注册到它,它监听了Canvas即将渲染的事件,并调用已注册组件的Rebuild等方法。

CanvasUpdateRegistry维护了两个索引集(不会存放相同的元素):

//布局重建序列索引集

private readonly IndexedSet<ICanvasElement> m_LayoutRebuildQueue = new IndexedSet<ICanvasElement>();

//图形重建序列索引集

private readonly IndexedSet<ICanvasElement> m_GraphicRebuildQueue = new IndexedSet<ICanvasElement>();

 

m_LayoutRebuildQueue是通过RegisterCanvasElementForLayoutRebuild

和TryRegisterCanvasElementForLayoutRebuild方法添加元素。

m_GraphicRebuildQueue是通过RegisterCanvasElementForGraphicRebuild

和TryRegisterCanvasElementForGraphicRebuild方法添加元素。

二者通过UnRegisterCanvasElementForRebuild移除注册元素。

 

CanvasUpdateRegistry的构造函数:

protected CanvasUpdateRegistry()
{
    Canvas.willRenderCanvases += PerformUpdate;
}

willRenderCanvases是Canvas的静态事件,事件是一种特殊的委托,在渲染所有的Canvas之前,抛出willRenderCanvases事件,继而调用CanvasUpdateRegistry的PerformUpdate方法。

public enum CanvasUpdate
{
    Prelayout = 0,
    Layout = 1,
    PostLayout = 2,
    PreRender = 3,
    LatePreRender = 4,
    MaxUpdateValue = 5
}

除了最后一个枚举项,其他五个项分别代表了布局的三个阶段和渲染的两个阶段。

 

在PerformUpdate方法中

  • 从两个序列中删除不可用的元素 CleanInvalidItems();
  • 布局更新开始
  • 对m_LayoutRebuildQueue依据父对象的数量进行排序
  • 分别以PreLayout,Layout,PostLayout的参数顺序调用每一个元素的Rebuild方法
  • 调用所有元素的LayoutComplete方法
  • 清除布局重建序列中的所有元素
  • 布局更新结束
  • 完成布局后,调用组件的修剪方法
  • 图形更新开始
  • 以PreRender,LatePreRender的参数顺序调用每一个元素的Rebulid方法
  • 调用所有元素的GraphicUpdateComplete方法
  • 清除图形重建序列中的所有元素
  • 图形更新结束

 

至此,一个完整的更新流程就完成了。