うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】Editor の OnInspectorGUI の呼び出しでハマったこと

EditorWindow の拡張を行っている際に ScriptableObject の Editor を取得し、 OnInspectorGUIを呼び出した際に
CustomPropertyDrawerと Foldout を利用した際にUIがおかしくなりました

f:id:hacchi_man:20200104220112p:plain

本来であればこう表示されます
f:id:hacchi_man:20200104220137p:plain

原因調査

公式の Editor.cs を読んでいると

https://github.com/Unity-Technologies/UnityCsReference/blob/5bc2902a12bd9f919e03a60f1f1ffffe5c31204c/Editor/Mono/Inspector/Editor.cs

EditorGUIUtility.hierarchyModeたるものを見つけました

    public void DrawHeader()
    {
      bool hierarchyMode = EditorGUIUtility.hierarchyMode;
      if (hierarchyMode)
        this.DrawHeaderFromInsideHierarchy();
      else
        this.OnHeaderGUI();
      if (UnityEditor.Editor.finishedDefaultHeaderGUI == null)
        return;
      if (hierarchyMode)
      {
        EditorGUILayout.EndVertical();
        EditorGUILayout.BeginVertical(GUILayoutUtility.topLevel.style);
      }
      EditorGUIUtility.labelWidth = 0.0f;
      EditorGUIUtility.fieldWidth = 0.0f;
      GUILayout.Space(-1f - (float) UnityEditor.Editor.BaseStyles.inspectorBig.margin.bottom - (float) UnityEditor.Editor.BaseStyles.inspectorBig.padding.bottom - (float) UnityEditor.Editor.BaseStyles.inspectorBig.overflow.bottom);
      EditorGUIUtility.hierarchyMode = true;
      EditorGUIUtility.wideMode = (double) EditorGUIUtility.contextWidth > 330.0;
      EditorGUILayout.BeginVertical(UnityEditor.Editor.BaseStyles.postLargeHeaderBackground, GUILayout.ExpandWidth(true));
      UnityEditor.Editor.finishedDefaultHeaderGUI(this);
      EditorGUILayout.EndVertical();
      if (hierarchyMode)
      {
        EditorGUILayout.EndVertical();
        EditorGUILayout.BeginVertical(this.UseDefaultMargins() ? EditorStyles.inspectorDefaultMargins : GUIStyle.none);
      }
    }

EditorGUIUtility-hierarchyMode - Unity スクリプトリファレンス

ヒエラルキーモードでは、EditorGUI.Foldout は Rect の内側に配置するよりむしろ指定された Rect の左側に foldout の三角形を配置します。このように、他のエディター GUI のラベルと一緒に並べることができます。 とあります。

今回利用しているのが Foldout のため恐らくこれを利用すれば解決するはずです

property.isExpanded = EditorGUI.Foldout(position, property.isExpanded, label);

Foldout

一応 Foldout 内の実装も見てみます

https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/EditorGUI.cs

途中をはぶきますが最終的にはこちらのメソッドが呼び出されます。
ここで EditorGUIUtility.hierarchyMode の際に xMinを左に寄せていることがわかります。

        // Make a label with a foldout arrow to the left of it.
        internal static bool FoldoutInternal(Rect position, bool foldout, GUIContent content, bool toggleOnLabelClick, GUIStyle style)
        {
            Rect origPosition = position;
            position = style.margin.Remove(position);
            if (EditorGUIUtility.hierarchyMode)
            {
                int offset = (EditorStyles.foldout.padding.left - EditorStyles.label.padding.left);
                position.xMin -= offset;
            }

EditorGUIUtility.hierarchyMode の対応

こちらの対応を入れることで Inspector と同じようにFoldoutが左側によりました。

まだまだ不具合

今回 Rect の領域確保に GUILayout.AreaScope(rect) を利用しているのですが

こちらを利用すると rect の領域内にしか表示できず xMin を引いても下記のようになってしまいます。

f:id:hacchi_man:20200104223220p:plain

そのため EditorGUI.IndentLevelScope を利用しているのですが、ReordableListを使った際に 左によってしまう問題があります

f:id:hacchi_man:20200104223408p:plain

Editor の OnGUI をそのまま利用する場合は rect をずらすことが可能なのでこちらの現象は発生しないはずです