2017年12月22日

Unity テクスチャの一部を切り取ってインスペクタに表示する


エディタ拡張を利用してインスペクタ上にテクスチャの一部だけを表示する方法をメモメモ…


※このページの内容の動作確認にはUnity5.6を使用しています。
「インスペクタ上にテクスチャを表示する方法」はいろいろ情報が転がっているのですが「テクスチャの一部分だけを表示する方法」についてちょっとすぐには見つからなかったのでメモしておきます。たとえばアトラス(1枚のテクスチャに複数の画像をまとめたもの)を扱うときにもしかしたら利用する機会があるかもしれません。

ポイントから先に言ってしまうと、GUIクラスにDrawTextureWithTexCoordsというそのものズバリなメソッドがあるのでそれを利用すれば簡単です。


using UnityEngine;

public class TextureTrim : MonoBehaviour {

 public Texture2D texture;
 public Vector2 position = new Vector2(0, 0);
 public Vector2 size = new Vector2(1, 1);

}
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(TextureTrim))]
public class TextureTrimEditor : Editor {

 SerializedProperty textureProp;
 SerializedProperty positionProp;
 SerializedProperty sizeProp;

 private void OnEnable()
 {
  textureProp = serializedObject.FindProperty("texture");
  positionProp = serializedObject.FindProperty("position");
  sizeProp = serializedObject.FindProperty("size");
 }

 public override void OnInspectorGUI()
 {
  serializedObject.Update();

  // 50x50 の四角形を描画
  GUILayout.Box(GUIContent.none, GUILayout.Width(50), GUILayout.Height(50));

  // テクスチャを取得
  Texture2D tex = textureProp.objectReferenceValue as Texture2D;

  if (tex != null)
  {
   // テクスチャのどの範囲を切り取るかをRectで指定
   Rect rect = new Rect(positionProp.vector2Value, sizeProp.vector2Value);

   // さっきの四角形の位置に切り取ったテクスチャを表示
   GUI.DrawTextureWithTexCoords(GUILayoutUtility.GetLastRect(), tex, rect);
  }

  // フィールドの入力欄を表示
  EditorGUILayout.PropertyField(textureProp);
  EditorGUILayout.PropertyField(positionProp);
  EditorGUILayout.PropertyField(sizeProp);

  serializedObject.ApplyModifiedProperties();
 }
}

なんかいっぱい書いてますが、大事なのは22行目~35行目だけです。正方形を描画してその位置にテクスチャを表示する、ということをやっています。

四角形の中にテクスチャの左上部分だけを表示

まず34行目にさらっと登場するGUILayoutUtility.GetLastRect()というのは、GUILayout を使って直前に描画した要素の範囲(Rect)を取得できる便利メソッドです。この場合、直前に描画したのは23行目のGUILayout.Boxなのでその位置が返ってくるわけですね。そしてそのBoxの範囲をDrawTextureWithTexCoords(インスペクタ上の表示範囲, 対象のテクスチャ, テクスチャを切り取る範囲)の最初の引数として渡しています。

それから、SerializedPropertyの実際の値を取得するとき、通常は31行目のvector2Valueのように"~Value"を使います。ただし26行目のTexture2Dのように"~Value"が用意されていない型やクラスの場合は、objectReferenceValueをキャストすることで使えるようになります。

さらにひと手間くわえて、たとえば「表示位置を変更し見栄えを良くする」とか「値が常に0-1におさまるようチェックする」とか「PositionとSizeではなく2つのUV座標で指定する」とかいろいろカスタマイズしてもいいと思います。

0 件のコメント:

コメントを投稿