EditorWindowのScrollView内のGUIを拡縮する
※この記事は2017年05月22日にqiitaに投稿した記事内容です。
環境
Unity5.6.0f3
概要
ノードグラフなエディタを作る際、ミドルボタンで拡縮したくなります
スクロールビュー内でGUIUtility.ScaleAroundPivotを使用してGUIを拡縮したら Clipがおかしくなり、UIが表示されなかったり、途切れて見えたりします 仕方ないのでリフレクションで無理やり修正しました GUIClip.visibleRectとGUIClip.SetTransformを使用しています
プログラム
例:Assets/Editor/TestScaleGUI.cs
using UnityEngine; using UnityEditor; using System; using System.Reflection; public class TestScaleGUI : EditorWindow { private MethodInfo _getTopRect = null; private PropertyInfo _getVisibleRect = null; private MethodInfo _setTransform = null; private Vector2 _scrPos = Vector2.zero; //Windowメニュー [MenuItem( "Test/TestScaleGUI" )] public static void Create() { var win = GetWindow<TestScaleGUI>( "TestScaleGUI" ); } private void OnEnable() { Assembly UnityEngine = System.Reflection.Assembly.Load( "UnityEngine.dll" ); Type GUIClipType = UnityEngine.GetType( "UnityEngine.GUIClip" ); _getTopRect = GUIClipType.GetMethod( "GetTopRect", BindingFlags.Static | BindingFlags.NonPublic ); _getVisibleRect = GUIClipType.GetProperty( "visibleRect", BindingFlags.Static | BindingFlags.Public ); _setTransform = GUIClipType.GetMethod( "SetTransform", BindingFlags.Static | BindingFlags.NonPublic ); } private void OnDisable() { } private Rect GUIClipGetTopRect() { if( _getTopRect == null ) return new Rect( 0, 0, position.width, position.height ); var rect = (Rect)_getTopRect.Invoke( null, null ); return rect; } private Rect GUIClipGetVisibleRect() { if( _getVisibleRect == null ) return new Rect( 0, 0, position.width, position.height ); var rect = (Rect)_getVisibleRect.GetValue( null, null ); return rect; } private void GUIClipSetTransform( Matrix4x4 clipTransform, Matrix4x4 objectTransform, Rect clipRect ) { if( _setTransform == null ) return; _setTransform.Invoke( null, new object[]{ clipTransform, objectTransform, clipRect } ); } private void OnGUI() { var topRect = GUIClipGetTopRect(); var pivotPoint = Vector2.zero; var rect = new Rect( 0, 0, topRect.width, topRect.height ); var zoom = 2.0f; // 1.0f~ 値が大きいほど、小さく表示される var invZoom = 1.0f / zoom; { using( var scrollScope = new EditorGUILayout.ScrollViewScope( _scrPos ) ) { _scrPos = scrollScope.scrollPosition; var area = GUILayoutUtility.GetRect( new GUIContent( string.Empty ), GUIStyle.none, GUILayout.Width( 3000 ), GUILayout.Height( 3000 ) ); { GUIUtility.ScaleAroundPivot( Vector2.one * invZoom, pivotPoint ); var visibleRect = GUIClipGetVisibleRect(); visibleRect.position *= zoom; visibleRect.size *= zoom; GUIClipSetTransform( Matrix4x4.identity, Matrix4x4.identity, visibleRect ); //内部のGUI 適当! int x, y; x = 3000 -25; for( y = 0; y <= 6000; y+= 100 ) GUI.Button( new Rect( x, y, 50, 50 ), y.ToString() ); x = 6000 -25; for( y = 0; y <= 6000; y+= 100 ) GUI.Button( new Rect( x, y, 50, 50 ), y.ToString() ); y = 3000 - 25; for( x = -25; x <= 6000; x+= 100 ) GUI.Button( new Rect( x, y, 50, 50 ), x.ToString() ); y = 6000 - 25; for( x = 0; x <= 6000; x+= 100 ) GUI.Button( new Rect( x, y, 50, 50 ), x.ToString() ); GUI.matrix = Matrix4x4.identity; } } } } }