我有一个 ScriptableObject,它只有一个对象列表:
class MyClassHolder : ScriptableObject
{
public MyClass[] myClass;
}
[System.Serializable]
public class MyClass
{
public string key;
public int priority;
public Data data;
}
还有一些数据类:
[System.Serializable]
public class Data
{
public Icon icon;
public Color color;
}
[System.Serializable]
public class Icon
{
public TextureSet[] small;
public TextureSet[] big;
}
[System.Serializable]
public class TextureSet
{
public Texture2D texture;
public Vector2 offset;
[Range(0f, 1.2f)]
public float scale = 1;
}
现在看起来像这样:
我有绘制图标的代码,就像:
我想尝试做的是在“小”和“大”旁边添加一个预览,如果可以的话,像这样:
或者在这样的数据下:
我知道有 CustomEditor 或一些抽屉,但不知道哪个适合这种情况。
我应该和哪个班级一起工作?
对于这个用例,我不会使用 CustomEditor,它用于为整个
ScriptableObject
或 MonoBehaviour
实现自定义检查器。仅自定义某个字段的绘制方式将带来大量开销。此外,您必须为使用此字段类型的每个其他类执行此操作。
PropertyDrawer
,它用于实现自定义方式来仅绘制特定类型的字段 - 在您的情况下为TextureSet
.
可能看起来有点像例如
...
#if UNITY_EDITOR
using UnityEditor;
#endif
[Serializable]
public class TextureSet
{
public Texture2D texture;
public Vector2 offset;
[UnityEngine.Range(0f, 1.2f)]
public float scale = 1;
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(TextureSet))]
private class TextureSetDrawer : PropertyDrawer
{
// height and width of the preview field in lines
const float PREVIEW_SIZE_LINES = 4;
// height and width of the preview field in pixels
readonly float PREVIEW_SIZE = EditorGUIUtility.singleLineHeight * PREVIEW_SIZE_LINES;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!property.isExpanded)
{
// if folded simply single line
return EditorGUIUtility.singleLineHeight;
}
// compose the total height of the poperty
// 1 line - offset
// 1 line - scale
// PREVIEW_SIZE_LINES - preview
// 1 line - a bit of buffer to separate from next list element
return EditorGUIUtility.singleLineHeight * (2 + PREVIEW_SIZE_LINES + 1);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
using (new EditorGUI.PropertyScope(position, label, property))
{
if (!property.isExpanded)
{
// draw the foldout label of the entire TextureSet property
property.isExpanded = EditorGUI.Foldout(position, property.isExpanded, label);
}
else
{
// move down half buffer to separate a bit from previous fields
position.y += EditorGUIUtility.singleLineHeight * 0.5f;
// draw the foldout label of the entire TextureSet property
property.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), property.isExpanded, label);
// indent the child properties a bit for better visual grouping
using (new EditorGUI.IndentLevelScope())
{
position = EditorGUI.IndentedRect(position);
// Find/Bind the three properties
var textureProperty = property.FindPropertyRelative(nameof(texture));
var offsetProperty = property.FindPropertyRelative(nameof(offset));
var scaleProperty = property.FindPropertyRelative(nameof(scale));
// Calculate the positions and sizes of the fields to draw
var textureRect = new Rect(position.x, position.y + PREVIEW_SIZE * 0.5f - EditorGUIUtility.singleLineHeight * 0.5f, position.width - PREVIEW_SIZE, EditorGUIUtility.singleLineHeight);
var previewRect = new Rect(position.x + position.width - PREVIEW_SIZE, position.y, PREVIEW_SIZE, PREVIEW_SIZE);
var offsetRect = new Rect(position.x, position.y + previewRect.height, position.width, EditorGUIUtility.singleLineHeight);
var scaleRect = new Rect(position.x, offsetRect.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight);
// The default texture field
EditorGUI.PropertyField(textureRect, textureProperty);
// using a grey texture as fallback if there is none referenced yet
var tex = textureProperty.objectReferenceValue ? (Texture)textureProperty.objectReferenceValue : Texture2D.grayTexture;
var texCoords = new Rect(offsetProperty.vector2Value.x, offsetProperty.vector2Value.y, 1 / scaleProperty.floatValue, 1 / scaleProperty.floatValue);
GUI.DrawTextureWithTexCoords(previewRect, tex, texCoords);
// The default vector2 field
EditorGUI.PropertyField(offsetRect, offsetProperty);
// The default float field with RangeAttribute applied
EditorGUI.PropertyField(scaleRect, scaleProperty);
}
}
}
}
}
#endif
}
我希望这是一个很好的起点,您可能需要尝试一下并根据您的需要弄清楚您想要将
scale
和 offset
应用到预览中的确切程度。
小演示
public class Example : MonoBehaviour
{
public TextureSet test;
public TextureSet[] tests;
}