控件定位
由于所有的控件 (Element) 都是基于 Minecraft 的文本展示实体 (opens new window)实现的,所以它们的默认行为多少会有一点点奇怪,需要去不断调试才能得到最佳效果。
以下使用 e 来代表控件实例。
# 定位方式
在 VectorDisplays 中存在两种标尺
- 文本渲染标尺:按字体的像素大小计算,单位长度是像素
- 世界标尺:按世界上的方块计算,单位长度是1个方块
你不需要担心标尺不同的问题,VectorDisplays 已经为你解决标尺问题了。
在 Element 中输入的相对 x、y 坐标均使用文本渲染标尺,在实际确定悬浮字位置时,会通过 HologramFont 类转换为世界标尺。
相对 x、y 坐标的方向,已被修正为与常见的 UI 设计器相同
- 对于
x轴,往左是负,往右是正 - 对于
y轴,往上是负,往下是正
此外,我们还增加了一个特殊的 zIndex 值,最终坐标会在 z 方向上增加 0.001 * zIndex 的世界标尺长度。但由于 Minecraft 存在渲染深度冲突问题,这个值的作用并不明显。
使用文本展示实体的 TextElement 控件定位演示图如下

图中的红点就是控件的坐标点。其中的 e.getTextWidth() 和 e.getTextHeight() 已考虑悬浮字的缩放,获取的值是经过缩放后的值,可以放心地直接用于坐标运算。
首先,VectorDisplays 会根据你的对齐方式(EnumAlign)和文本长宽,确定初始坐标点,然后再应用开发者输入的相对坐标,获得悬浮字坐标。
出于性能考虑,主要是因为对齐机制,将等价坐标点移到左上角极其麻烦,所以我们没有将坐标点移动到传统 UI 规定的左上角坐标,而是使用 Minecraft 默认的中下方坐标。
正因 VectorDisplays 需要根据对齐位置和文本长宽来确定初始坐标点,如果你添加了一个新的控件类型,需要更新悬浮字文本,则必须要跟自带的控件 Button 一样,每当你在设置悬浮字的 文本、坐标 或 缩放 之后,要执行以下代码,以更新控件的大小信息与悬浮字在世界上的位置。
e.calculateSize();
// 为了避免悬浮字还没生成就发送“实体传送”包
if (!e.getHologram().isDead()) {
e.updateLocation();
// 如果要更新缩放和文字,还要再执行下面这一句
e.getHologram().update();
}
2
3
4
5
6
7
出于性能考虑,文本、坐标、缩放 等属性在设置之后,不会立即生效,需要执行以上代码才会生效。因为开发者有可能会同时设置多个属性,如果每设置一个属性发一两次包,未免有点浪费带宽了。
# 变换方式
VectorDisplays 会先获取父面板 (Terminal) 的悬浮字在世界上的坐标,算出所有控件在父面板面向南方 (Z轴正方向) 时在世界上的坐标。
因为这非常容易计算,在这种条件下,界面设计时的X轴依然是世界坐标系的X轴,界面设计时的Y轴与世界坐标系的Y轴方向相反。
然后再根据父面板的旋转变换(使用四元数),绕父面板在世界上的坐标,算出所有控件在进行旋转变换后的坐标。
最后应用父面板的旋转变换到所有控件,即完成悬浮字面板的变换。一些特殊的控件,例如线条 Line 需要根据两个端点的坐标,计算新的旋转变换。
这样一来,在父面板的旋转将会带动所有控件的旋转,让控件始终出现在正确的相对位置上。
你大可以任意设置父面板和各个控件的旋转,但有一些限制。违反了这些限制不会出现报错,但悬浮字将会不正常显示。
- 父面板的
LeftRotation会被应用到各个控件,所以你不能更改控件的LeftRotation,否则旋转变换将会随时被覆盖 - 父面板的
RightRotation没有被使用,所以你也不能更改它,否则背景将会错位
你可以使用 QuaternionUtils.fromEulerYXZtoQuaternion(yaw, pitch, roll) 来快捷转换欧拉角为四元数,以便于更直观地设置控件的旋转变换。
Minecraft 的文本展示实体(悬浮字)会按顺序经历以下的变换:
- 右旋转 (
RightRotation)- 缩放 (
Scale)- 左旋转 (
LeftRotation)- 平移 (
Transition)以免对 VectorDisplays 的坐标系统造成破坏,不推荐通过
e.getHologram()更改悬浮字的左旋转、缩放、平移变换,缩放变换请通过e.setScale(scale)来更改。