3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

UIElementsでEditorWindowをダークテーマに固定する

Last updated at Posted at 2020-10-08

事件

せっかくつくったエディタ拡張が、エディタのテーマを変更したら文字が背景に同化した……
image.png
image.png

個人プロジェクトならまだいいですが、人に配るものとなるとこうはいきません。
いやしかし、全部の要素のUSSを書き換えて文字色・背景色を変えるのは難しいですし、新しい要素を追加するときも面倒です。
環境によらずつねに同じ色で表示されてほしい……

そんなわけで今回は、UIElementsでテーマをダークテーマに(またはライトテーマに)固定するというお話です。

UIElementsとエディタテーマ

UIElementsはUXML/USSという言語でUIを作ります。ちょうどHTML/CSSとよく似た仕組みで、USSがスタイルを制御するファイルにあたります。
UIElementsでは、読み込んでいるテーマに応じて自動的にそのテーマ用のUSSが適用されるようになっています。

これはUIElements Debuggerをみるとよくわかります。適当なEditorWindowのタイトル部分を右クリックしてUIElements Debuggerを見てみましょう:
image.png
ありました。 DefaultCommonLight_inter.ussっていうこいつです。ダークテーマの時はDefaultCommonDark_inter.ussというUSSが読み込まれます。
「じゃあこのファイルを探してきて読み込めばいいのでは?」と行きたいところですが、実はこのファイル、Unityのエディタビルトインアセットとして保存されています。EditorGUIUtility.Load(string path)で読み込めるのですが、Unityのバージョンによってアセットのパスが同一である保証はありません。ついでに使用している言語やフォントによってUSSが異なります。
つまりどういうことかというと、ちゃんとUnity側のAPIを通してスタイルシートを取得するのがよさそうということです。

Unity側の処理を見てみる

Unity側にEditorWindowに対して自動的にテーマに応じたUSSを適用する処理が存在しているわけですが、そこの処理を拝借してくればよさそうです。

EditorWindowがテーマを取得しているのは以下の箇所です。

UnityCsReference/EditorWindow.cs at master · Unity-Technologies/UnityCsReference

ここからさらに処理を辿ると、 UIElementsEditorUtility に辿り着きました。

UnityCsReference/UIElementsEditorUtility.cs at master · Unity-Technologies/UnityCsReference

ありました。UIElementsEditorUtility.s_DefaultCommonDarkStyleSheetUIElementsEditorUtility.s_DefaultCommonLightStyleSheetです。

しかし(予想はしていましたが)、こいつらはinternalです。つまりリフレクションの出番です。ゴリ押していきましょう。

SkinFixedEditorWindow.cs
using System.Reflection;
using UnityEditor;
using UnityEngine.UIElements;

public class SkinFixedEditorWindow : EditorWindow
{
    [MenuItem("Window/SkinFixedEditorWindow")]
    public static void ShowWindow()
    {
        GetWindow(typeof(SkinFixedEditorWindow));
    }

    private static StyleSheet defaultCommonDarkStyleSheet;
    private static StyleSheet defaultCommonLightStyleSheet;

    private static void GetSkins()
    {
        //UnityEditor.UIElementsのアセンブリを取得
        var assembly = typeof(Toolbar).Assembly;

        //UIElementsEditorUtilityのTypeを取得
        var type = assembly.GetType("UnityEditor.UIElements.UIElementsEditorUtility");
        if (type == null) return;

        //StyleSheetを格納するフィールドを取得
        var darkField = type.GetField("s_DefaultCommonDarkStyleSheet", BindingFlags.Static | BindingFlags.NonPublic);
        var lightField = type.GetField("s_DefaultCommonLightStyleSheet", BindingFlags.Static | BindingFlags.NonPublic);

        if (darkField == null || lightField == null) return;

        //staticなフィールドとして値を取得
        defaultCommonDarkStyleSheet = (StyleSheet) darkField.GetValue(null);
        defaultCommonLightStyleSheet = (StyleSheet) lightField.GetValue(null);
    }

    private void OnEnable()
    {
        GetSkins();
    }
}

あとは取得したUSSをEditorWindowのrootVisualElementに適用してあげます。

SkinFixedEditorWindow.cs
    private void OnEnable()
    {
        GetSkins();
        
        //Darkテーマに設定
        rootVisualElement.styleSheets.Clear();
        rootVisualElement.styleSheets.Add(defaultCommonDarkStyleSheet);
        
        //EditorWindowのデフォルトの背景色はUIElementsの色ではなく地の色なので、背景色だけはUIElements側に手動で設定する必要がある
        rootVisualElement.style.backgroundColor = new StyleColor(new Color(0.22f, 0.22f, 0.22f));
        rootVisualElement.style.flexGrow = 1f;

        //VisualElementを配置してみる
        var button = new Button();
        button.text = "ボタン";
        rootVisualElement.Add(button);
        
        var textField = new TextField("テキスト");
        rootVisualElement.Add(textField);

        var floatField = new FloatField("数値");
        rootVisualElement.Add(floatField);
    }

image.png

そんなわけで、LigthtテーマのUnityの上にDarkテーマ固定のEditorWindowを出現させることに成功しました。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?