设置widget大小
从Geometry里可以获取两种size,Absolute和Local,这两者的关系是,在当前的渲染窗口中,AbsoluteSize/GetViewportScale() = LocalSize。这里的GetViewportScale()就是获取DPI系数。
Viewport上的Size是AbsoluteSize,因此GetViewportScale()是从LocalSize变换成AbsoluteSize的Scale。
参考 线性映射(linear mapping) ,s就是DPI缩放系数(通常值为0.67),(A, B)为LocalSize(Viewport坐标系描述),(X, Y)为ScreenSize(真实物理设备尺寸描述,不是所谓的ScreenSpace下的描述)。GetViewportSize()返回的是真实物理设备Screen坐标系下的尺寸描述。
UMG语境下,Absolute坐标与Local坐标都是在Viewport坐标系里的表述。
关于Unreal Engine中Widget的Slot
各种Layouts与Widgets之间可能会有嵌套、组合之类的关系的。
比如,一个Layout引用一个widget,通常C++里可能会引用widget基类指针,UE4对这种使用指针的用法进行了建模,用Slot来代替指针的作用,Slot里比普通的指针提供了额外的一些信息,可以认为是一个强化版的指针,它包含双指针,一个指向这个Slot对应的Widget(C),一个指向该Widget(C)的ParentWidget(通常值就是this)。因此,每一个Widget里都有一个Slot成员(定义在Widget.h里的UPanelSlot* Slot;)。
UPanelSlot* PanelSlot = NewObject<UPanelSlot>(this, GetSlotClass(), NAME_None, NewObjectFlags); PanelSlot->Content = Content; PanelSlot->Parent = this; Content->Slot = PanelSlot;
线性映射(linear mapping)
在unreal engine里就是Clamp函数。
问题:P的取值范围是[A, B],要将其线性对应到[X, Y]范围的Q点。已知P,求Q。
这种线性映射问题,其实就是一个缩放+平移的问题。先缩放一下使得两段范围宽度一致,再把两段范围的参照点平移对齐,就完成了映射过程。比如:将[A, B]缩放成[A', B'],其尺寸与[X, Y]相同,再把[A', B']平移叠到[X, Y]上,这样就完成了线性映射。将缩放和平移作用到P上,即可求出Q:
\[Q = s * P + t\]
s为缩放系数,t为平移量。将P=A,Q=X与P=B,Q=Y两组解分别带入上式,可得二元一次方程组:
\[\left\{
\begin{array}{l}
X = A * s + t \\
Y = B * s + t
\end{array}\right.\]
求解可得:
\[\left\{\begin{array}{l}
s=\frac{Y-X}{B-A} \\
t=\frac{BX-AY}{B-A}
\end{array}
\right.
\]
另一个角度的理解就是:先求AP在AB中所占比例t,线性映射中该比例不变,因此XQ在XY中所占比例也应为t,于是就有:
\[\begin{align*}
t = \frac{P-A}{B-A} \\
Q=t*(Y-X) + X
\end{align*}
\]