public class EditorClipDemoWnd : EditorWindow { [MenuItem("Demos/EditorClipDemoWnd")] static void ShowWindow() { var window = GetWindow<EditorClipDemoWnd>(); window.titleContent = new GUIContent("EditorClipDemoWnd"); window.Show(); } private string[] m_ToolbarNames = { "scrollOff.y", "renderOff.y", "clip.y" }; private int m_ToolbarIndex = 0; ///裁剪區域 private Rect m_ViewportRect; private float m_ContentHeight; ///GUI.BeginClip的scrollOffset引數 private Vector2 m_ScrollOffset; /// GUI.BeginClip的renderOffset引數 private Vector2 m_RenderOffset; /// GUI.BeginClip的resetOffset引數 public bool m_ResetOffset; private void OnEnable() { m_ViewportRect = new Rect(0, 0, 200, 60); } private void OnGUI() { EditorGUI.DrawRect(m_ViewportRect, Color.gray); //繪製出裁剪區域 GUI.BeginClip(m_ViewportRect, m_ScrollOffset, m_RenderOffset, m_ResetOffset); { //內容超出視口將被裁減掉 EditorGUILayout.LabelField("aaaaaaa"); EditorGUILayout.LabelField("bbbbbbb"); EditorGUILayout.LabelField("ccccccc"); EditorGUILayout.LabelField("ddddddd"); EditorGUILayout.LabelField("fffffff"); } GUI.EndClip(); if (Event.current.type == EventType.Repaint) { var rect = GUILayoutUtility.GetLastRect(); m_ContentHeight = rect.yMax; } //捲軸放在裁剪區域右側 float scrollBarMaxPos = Mathf.Max(0, m_ContentHeight - m_ViewportRect.height); //內容超出的部分即為可滾動距離 float scrollBarPos = Mathf.Clamp(-m_ScrollOffset.y, 0, scrollBarMaxPos); Rect scrollBarRect = new Rect(m_ViewportRect.xMax, m_ViewportRect.y, 13, m_ViewportRect.height); scrollBarPos = GUI.VerticalScrollbar(scrollBarRect, scrollBarPos, m_ViewportRect.height, 0, Mathf.Max(m_ViewportRect.height, m_ContentHeight)); m_ScrollOffset.y = -scrollBarPos; EditorGUILayout.Space(); m_ToolbarIndex = GUILayout.Toolbar(m_ToolbarIndex, m_ToolbarNames); m_ResetOffset = EditorGUILayout.ToggleLeft("resetOffset", m_ResetOffset); if (GUILayout.Button("ResetAll")) { m_ViewportRect.position = Vector2.zero; m_ScrollOffset = Vector2.zero; m_RenderOffset = Vector2.zero; m_ResetOffset = false; } if (Event.current.isScrollWheel) { var delta = Event.current.delta; //向下滾動滾輪, delay.y>0 if (0 == m_ToolbarIndex) { m_ScrollOffset.y -= delta.y; //scrollOffset.y<0時ui往上移動 Debug.Log($"delta:{delta.y}, scrollOffset:{m_ScrollOffset.y}"); } else if (1 == m_ToolbarIndex) { m_RenderOffset.y -= delta.y; //renderOffset.y<0時ui往下移動 Debug.Log($"delta:{delta.y}, renderOffset:{m_RenderOffset.y}"); } else if (2 == m_ToolbarIndex) { m_ViewportRect.y -= delta.y; //viewportRect.y<0時ui往上移動 Debug.Log($"delta:{delta.y}, viewport:{m_ViewportRect.y}"); } Repaint(); } } }
僅scrollOffset.y變小:裁剪區域不變, y<0 ui內容向上移動
僅renderOffset.y變小:裁剪區域大小不變, y<0 viewport向下移動
僅viewportRect.y變大:裁剪區域大小不變,y>0 viewport向下移動
所以:
GUI.BeginClip(new Rect(0, 0, 66, 17), Vector2.zero, new Vector2(0, -10), false);
GUI.BeginClip(new Rect(0, 10, 66, 17), Vector2.zero, new Vector2(0, 0), false);
可以得到一樣的viewport向下移動10畫素的效果
先viewportRect.y變大,再renderOffset變小,再scrollOffset變小
resetOffset為true時,renderOffset將相對於視窗標題的左上角(而不是裁剪區域的左上角),同時scrollOffset將不起作用
參考:
Unity EditorWindow GUI裁剪 - lunoctis - 部落格園 (cnblogs.com)
UnityEditor ScrollView 簡易分頁 - 知乎 (zhihu.com)