什么是SInvalidationPanel
『失效面板』中的控件可以对子控件几何图形进行缓存,以加快Slate的渲染速度。任何由失效面板缓存的控件都不会进行Prepassed(预渲染), Ticked(更新) 或 Painted(描画)。
对应UserWidget控件为 InValidationBox
主要功能
其主旨简要来说就是:『缓存』。包含了(What)『缓存什么信息』,(When)『什么时机进行缓存』以及(How)『如何缓存』
What | CachedWindowElements:子控件OnPaint返回的FSlateWindowElementList CachedMaxChildLayer:子控件OnPaint返回的渲染层ID CachedResources:CachedWindowElements的图片资源信息 CachedAbsolutePosition: 父控件为其分配的几何信息之渲染位置 |
When | 首次调用OnPaint 由父控件分配的几何信息改变时 裁切信息改变时 子控件手动失效时 |
How | 从SlateApplication的缓存池词典TMap< const ILayoutCache*, TSharedPtr<FCacheElementPools>> CachedElementLists中,以自身指针为Key,申请一段新的缓存FCacheElementPools. 在每次因需遍历子控件的OnPaint方法后,缓存其返回的WindowElements信息,然后遍历WindowElements,获取并缓存其BrushResource信息。 |
工作原理
SlateApplication 每帧会对所有的SWindow界面,遍历其子控件,搜集FSlateWindowElementList& OutDrawElements
SinvalidationPanel会在 IsCachingNeeded == true 的时候进行一遍正常的OnPaint,并把自己传递进去,如下图代码所示:
SInvalidationPanel* MutableThis = const_cast<SInvalidationPanel*>( this ); TSharedRef<SInvalidationPanel> SharedMutableThis = SharedThis(MutableThis); // 在Args中将当前控件作为参数传入 CachedMaxChildLayer = SCompoundWidget::OnPaint( Args.EnableCaching(SharedMutableThis, RootCacheNode, true, false), AllottedGeometry, MyCullingRect, *CachedWindowElements.Get(), LayerId, InWidgetStyle, bParentEnabled); |
子控件中的处理:
// 存储Args中传入的参数(即InvalidationPanel) TWeakPtr<ILayoutCache> LayoutCache = Args.GetLayoutCache();
// 自身进行失效时,进行通知 FORCEINLINE void Advanced_ForceInvalidateLayout() { TSharedPtr<ILayoutCache> SharedLayoutCache = LayoutCache.Pin(); if (SharedLayoutCache.IsValid() ) { SharedLayoutCache->InvalidateWidget(this); } } |
IsCachingNeeded在Panel初始化时为True,确保首次调用OnPaint时进行缓存;
当父控件分配的几何信息或裁切信息改变时,IsCachingNeeded为True
当其直接负责的子控件进行手动失效时,会根据Args.EnableCaching的信息,通知当前此面板进行处理,如上述代码所示
特别说明
标记为IsVolatile的子控件会被特殊处理,会被放入CachedWindowElements的VolatileElements列表中,InvalidationPanel会在后续专门调用PaintVolatile方法来绘制它们。
// SWidget.cpp if ( IsVolatile() && Args.IsCaching() && !Args.IsVolatilityPass() ) { const int32 VolatileLayerId = UseDefaultLayerPolicy() ? LayerId + 1 : LayerId; OutDrawElements.QueueVolatilePainting( FSlateWindowElementList::FVolatilePaint(SharedThis(this), Args, AllottedGeometry, CullingBounds, OutDrawElements.GetClippingState(), VolatileLayerId, InWidgetStyle, bParentEnabled)); NotifyEndPaint(); return VolatileLayerId; } // SInvalidationPanel.cpp // After normal Paint pass if ( CachedWindowElements.IsValid() ) { int32 VolatileLayerId = CachedWindowElements->PaintVolatile(xxx)} |
工作流程图