我正在Unity中编写一个自定义编辑器窗口,我希望能够在其中滚动/滚动并拖动视图。为此,我已经将GUI.matrix
设置为Matrix4x4.TRS(offset, Quaternion.identity, Vector3.one * scale)
,在CCD_2中我可以控制offset
和scale
。这可以很好地工作,除了在滚动时,它会固定在窗口的左上角我希望它固定在鼠标的位置。
如果这只需要在缩放时更改偏移量,那就太好了——我只是不确定这里的偏移量应该是多少。Matrix4x4
在数学方面超出了我的舒适区。
以下是我目前处理缩放的方式:
if (Event.current.type == EventType.ScrollWheel)
{
_scale *= Math.Sign(Event.current.delta.y) == 1 ? 1.1f : 1f / 1.1f;
_offset += Math.Sign(Event.current.delta.y) * /*What do I put here?*/;
}
让我们试着了解GUI矩阵的作用。它表示一种转换,它获取世界空间(GUI对象所在的位置(中的坐标,并将它们转换为GUI空间(或多或少与窗口对齐(。由于我们没有旋转,我们可以很容易地解释用TRS()
构造矩阵对世界空间点pWorld
:的作用
pGUI = scale * pWorld + offset
现在您要将scale
更改为scaleNew
。这样做时,您希望在鼠标下保持相同的世界位置。
如果您的鼠标位置是在GUI空间中给定的(例如,从Event.current.mousePosition
(,那么我们首先需要找到相应的世界空间点:
v3World = (1.0 / scaleOld) * (v3GUI - offsetOld)
我们想在鼠标下修复这一点,即:
v3GUI = scaleNew * v3World + offsetNew
v3GUI = scaleNew / scaleOld * (v3GUI - offsetOld) + offsetNew
我们可以解决这个问题来获得新的偏移量:
v3GUI = scaleNew / scaleOld * v3GUI - scaleNew / scaleOld * offsetOld + offsetNew
(1 - scaleNew / scaleOld) * v3GUI + scaleNew / scaleOld * offsetOld = offsetNew
就是这样。
顺便说一句,你也可以单独使用矩阵运算来实现这一点。这就是GUIUtility.ScaleAroundPivot()
的作用。这就是它的样子:
newMatrix = T(v3GUI) * S(newScale / oldScale) * T(-v3GUI) * oldMatrix
12表示平移,CCD_ 13表示缩放。平移对T(v3GUI)
和T(-v3GUI)
将坐标系的临时原点移动到鼠标位置,并从那里执行缩放。然后,您可以直接从这个矩阵中读取偏移量和比例。