MY BLOG DIRECTORY:
YivanLee:专题概述及目录INTRODUCTION:
Slate是跟平台无关的一个UI设计框架,不仅仅可以用来做引擎UI,还可以做引擎编辑器,甚至可以用它来开发其他应用,比如虚幻epic的商城。
一直以来对Unreal的Slate都非常困惑,各种插槽,尺寸,各种布局Panel,最后的UI按键到底尺寸多大感觉难以控制,非常玄学,所以特别研究了一下虚幻的Slate布局。
MAIN CONTENT:
首先需要先知道Slate的设计原理和组织方式。
![v2-a6636caa9b3b8b7741eb9bcddf128a98_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-a6636caa9b3b8b7741eb9bcddf128a98_b.jpg)
上图黄色框内的部分是可渲染部分,红色框部分是用于UI布局的部分。SLeafWidget没有插槽,SCompounWidget可以拥有一个插槽,SPanel可以拥有很多插槽。这里需要说明的是可以把插槽理解为一个节点。
![v2-754e85910f68175c4f14bebd86685510_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-754e85910f68175c4f14bebd86685510_b.jpg)
下面来几个实际的例子
![v2-0b540d4c9774964fe277cd3e20e6cfa0_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-0b540d4c9774964fe277cd3e20e6cfa0_b.jpg)
![v2-e8da50278c1717cbc7bda8694b7651fc_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-e8da50278c1717cbc7bda8694b7651fc_b.jpg)
可以看到我创建了三个按钮,最上面两个按钮在最下面那个按钮的slot里。一个slot里可以嵌套一个Panel然后这个panel又可以嵌套几个Slot。类似如下结构。SLeafWidget没有插槽,SCompounWidget可以拥有一个插槽,SPanel可以拥有很多插槽。
![v2-83a3470532b7aa60568cfe50d3119e8e_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-83a3470532b7aa60568cfe50d3119e8e_b.jpg)
正常情况一般不会在按钮上面再嵌套按钮
![v2-b4f199945e11cd33ee09b25f7b4cb4fe_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-b4f199945e11cd33ee09b25f7b4cb4fe_b.jpg)
![v2-db0915160d5622a9b3c521ce4d65f692_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-db0915160d5622a9b3c521ce4d65f692_b.jpg)
![](/qrcode.jpg)
这个插槽的大小到底占UI空间的多少,取决于很多因素,首先来看SizeParm,这是决定UI控件大小的第一步。
![v2-4eb7b613c41814414f43f1ca067093f7_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-4eb7b613c41814414f43f1ca067093f7_b.jpg)
SizeRule有两个策略,一个Stretch一个是Auto
如果我使用Auto,那么Slot大小会使用DesiredSize,如果是stretch那么Slot就会尽可能充满UI空间。
下面是(Auto, fill)的情况
![v2-b73181fd786daa5000570f51bb2c347a_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-b73181fd786daa5000570f51bb2c347a_b.jpg)
![v2-696e63d43d9957209f76031e19334fce_b.gif](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-696e63d43d9957209f76031e19334fce_b.gif)
下面是(stretch, fill)的情况
![v2-6aa62312e00e1dc235262cfd79b50126_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-6aa62312e00e1dc235262cfd79b50126_b.jpg)
![v2-57d0ca8b3de93d1c0312185b197d47d5_b.gif](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-57d0ca8b3de93d1c0312185b197d47d5_b.gif)
不指认的话默认就是stretch。可以看到他们的默认值如下
![v2-6293a11e25a3aeaea38665b685d8aae5_b.jpg](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-6293a11e25a3aeaea38665b685d8aae5_b.jpg)
可以看到Slot还有个HAlign和VAlign两个参数。这两个参数的作用注释给得很清楚了,就是用来描述Slot的位置的
![v2-ddc7cf899b127b7dd63f870047f84f67_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-ddc7cf899b127b7dd63f870047f84f67_b.jpg)
当我们使用(Auto,Fill)和(Auto,HAlign_Left)的组合的时候可以看到
![v2-4d2ef49fe6cea47839dd33fccde92247_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-4d2ef49fe6cea47839dd33fccde92247_b.jpg)
目前只考虑水平方向。首先会看这个Slot的数量和Alignment是那哪种。假设现在有三个Slot并且向这三个slot中添加了一个按钮UI控件,其中两个按钮是(Auto,HAlign_Left),一个按钮是(Fill,Fill_HAlign)的
![v2-58313c34bdca964fb5a86720712f5e0e_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-58313c34bdca964fb5a86720712f5e0e_b.jpg)
这个结果的计算过程如下
![v2-b59e3716e6ecde237037d07f306dc853_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-b59e3716e6ecde237037d07f306dc853_b.jpg)
首先有三个插槽,其中两个因为是Auto,所以插槽的大小等于插槽内控件的DesireSize。第一个插槽是stretch,所以它会尽可能延展自己的大小。所以其大小等于窗口的总大小减去其余两个slot占的固定大小。三个插槽的大小准备好以后再往里面填UI控件。因为第一个插槽的填充模式是Fill,所以它会被填满再slot插槽里。剩余的两个插槽里填的控件的填充模式是Left,因为插槽的大小本来就和控件的DesireSize相同,所以后面两个控件刚好能填满后面两个插槽。如果我们把第一个插槽的控件的填充模式缓冲Left
![v2-a640b7634ba81c2a15db1483c6a87df1_b.jpg](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-a640b7634ba81c2a15db1483c6a87df1_b.jpg)
可以看到因为插槽的大小大于控件自己本身的大小,所以它从开始填充根本填不满整个Slot,所以留下了很多没有被填充的Slot空间。
所以过程大致是先对UI空间进行切割,分割出每个Slot空间的大小,然后再根据不同的UI控件不同的填充模式再把Slot空间进行填充。
如果我三个控件全部选择Auto
![v2-5e3d6647a155dee753a785e1af784e81_b.jpg](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-5e3d6647a155dee753a785e1af784e81_b.jpg)
首先我们有三个Slot,因为都是选用Auto,所以其大小可以被明确计算出来。如果三个Slot里的控件的DesireSize之和小于窗口的大小,那么窗口就会有控件剩余。这时再把控件填充进来,因为是选用的Auto,所以不管控件是什么填充模式,Slot空间的大小始终刚好等于内部控件的大小。
![v2-a0485db747f667c6f22e1e4b68954e4c_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-a0485db747f667c6f22e1e4b68954e4c_b.jpg)
以上的推导都是建立在控件的大小的总和小于窗口大小下成立,那么当控件的大小总和大于窗口的时候会是什么情况呢
![v2-af3ecccd325b76fc55e16ec8fdf4f4d0_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-af3ecccd325b76fc55e16ec8fdf4f4d0_b.jpg)
因为是Auto,所以Slot的绝对大小不会改变,多余的部分直接会被擦掉。在窗口中的表现就会如下效果所示:
![v2-90e8465039f9c93e452d795758c8ecd6_b.gif](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-90e8465039f9c93e452d795758c8ecd6_b.gif)
![v2-5abe81d45e9ac8861a04f917849e7231_b.jpg](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-5abe81d45e9ac8861a04f917849e7231_b.jpg)
最后就是DesiredSize了,前面一直在说这个东西。
![v2-49477cc3ac775259713166e9612e8d09_b.png](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-49477cc3ac775259713166e9612e8d09_b.png)
我们可以找到SBox的计算函数
![v2-7f6792b2d3756f7b7cbbf8649f013f64_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-7f6792b2d3756f7b7cbbf8649f013f64_b.jpg)
这个值可以自己定义怎么计算。
反正不管怎么定义计算它就是代表内部控件的大小。即下一个链接节点的大小
![v2-3b9c739f415776d93466a66fbb45989b_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-3b9c739f415776d93466a66fbb45989b_b.jpg)
就SBox这个控件而言可以通过以下变量控制这个DesiredSize
![v2-175e618ec75ffb75030395eaa89f051a_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-175e618ec75ffb75030395eaa89f051a_b.jpg)
剩下的垂直方向上的逻辑和上面讨论的水平方向上的情况是一样的。还有个stretch情况。这种情况就比较简单了,会根据所有的slot的fill百分比进行缩放,我这里直接上代码就不做细致讨论了。
![v2-27848c7bb64cfe701f1661287f7331d0_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-27848c7bb64cfe701f1661287f7331d0_b.jpg)
SUMMARY AND OUTLOOK:
至此我们就彻底搞清楚了UI的控件大小布局,如果对UI的细节还不清楚可以先看 @Voron 大佬的文章,文章链接在我的Reference里。我这里只是对控件布局做进一步研究。
个人感觉Slate写UI还是比较简单的,各种东西都封装好了,开发起来也十分方便,甚至可以用它开发其它应用程序。
Enjoy it
NEXT:
todo...
Reference: