LoginSignup
4
1

More than 1 year has passed since last update.

インスペクタに画像を表示する [Unityエディター拡張, Odin対応]

Posted at

こんな感じに、インスペクタのフィールド上に画像を表示する属性を作ります。
スクリーンショット 2022-12-07 232656.png

実装

画像を表示する属性ImageHeaderAttributeとそのドロワーの実装を、通常のUnityのものと、アセットOdinに対応したものの2種類を紹介します。
Odin版の方のみ、画像を自動的に中央揃えで表示します。

閑話

2022/12/07 23:37現在、Odinがセール中だそうです。
インスペクタがかなり使いやすくなる便利なアセットなので、購入して損はないと思います。

(特にアフィリエイトリンクなどは付けていません)

通常

ImageHeaderAttribute.cs
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class ImageHeaderAttribute : PropertyAttribute
{
    public string AssetPath { get; }
    public int Height { get; }

    public ImageHeaderAttribute(string assetPath, int height)
    {
        AssetPath = assetPath;
        Height = height;
    }

#if UNITY_EDITOR
    [CustomPropertyDrawer(typeof(ImageHeaderAttribute))]
    public class ImageHeaderAttributeDrawer : PropertyDrawer
    {
        private bool showImage;
        private float imageHeight;

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var targetAttribute = (ImageHeaderAttribute)attribute;

            // パスが指定されていない場合や高さが正値でない場合は表示しない
            if (string.IsNullOrEmpty(targetAttribute.AssetPath) || targetAttribute.Height <= 0)
            {
                showImage = false;
                EditorGUI.PropertyField(position, property, label, true);
                return;
            }

            var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(targetAttribute.AssetPath);
            // テクスチャを取得できない場合は表示しない
            if (texture == null)
            {
                showImage = false;
                EditorGUI.PropertyField(position, property, label, true);
                return;
            }

            showImage = true;
            imageHeight = targetAttribute.Height;
            var imagePos = position;
            imagePos.height = imageHeight;
            imagePos.width = texture.width * (targetAttribute.Height / (float)texture.height);
            GUI.Label(imagePos, texture);
            position.y += imagePos.height;

            EditorGUI.PropertyField(position, property, label, true);
        }

        /// <summary>
        /// 全体の高さを返す
        /// </summary>
        /// <param name="property">属性が付加されているプロパティ</param>
        /// <param name="label">ラベル</param>
        /// <returns>全体の高さ</returns>
        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            if (!showImage) return base.GetPropertyHeight(property, label);

            return (imageHeight > 0f ? imageHeight : 0f) + EditorGUIUtility.singleLineHeight;
        }
    }
#endif
}

Odin版

ImageHeaderAttribute.cs
using System;
using UnityEngine;
#if UNITY_EDITOR
using Sirenix.OdinInspector.Editor;
using UnityEditor;
#endif

public class ImageHeaderAttribute : Attribute
{
    public string AssetPath { get; }
    public int Height { get; }

    public ImageHeaderAttribute(string assetPath, int height)
    {
        AssetPath = assetPath;
        Height = height;
    }

#if UNITY_EDITOR
    [DrawerPriority(0.2, 0, 0)]
    public class ImageHeaderAttributeDrawer : OdinAttributeDrawer<ImageHeaderAttribute>
    {
        protected override void DrawPropertyLayout(GUIContent label)
        {
            // パスが指定されていない場合や高さが正値でない場合は表示しない
            if (string.IsNullOrEmpty(Attribute.AssetPath) || Attribute.Height <= 0)
            {
                CallNextDrawer(label);
                return;
            }

            var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(Attribute.AssetPath);
            // テクスチャを取得できない場合は表示しない
            if (texture != null)
            {
                var width = texture.width * (Attribute.Height / (float)texture.height);
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label(texture, GUILayout.Width(width), GUILayout.Height(Attribute.Height));
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
            }

            CallNextDrawer(label);
        }
    }
#endif
}

使い方

以下のように、フィールドにImageHeader属性を付加します。

SampleMonoBehaviour.cs
using UnityEngine;

public class SampleMonoBehaviour : MonoBehaviour
{
    [SerializeField] [ImageHeader("Assets/Images/my_icon.jpg", 100)]
    private string headerField;
}

第1引数がAssetsから指定した画像アセットのパスで、第2引数は表示したい画像の高さです。
これで、以下のようにフィールドの上に画像を表示できるようになります。
スクリーンショット 2022-12-07 232656.png

4
1
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
4
1