You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
4.8 KiB

using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
//----
//This attribute adds a helpbox to the Unity property inspector
//----
[AttributeUsage(AttributeTargets.Field, Inherited = true)]
public class HelpAttribute : PropertyAttribute {
public readonly string text;
#if UNITY_EDITOR
public readonly MessageType type;
#endif
public HelpAttribute(string text
#if UNITY_EDITOR
, MessageType type = MessageType.Info
#endif
)
{
this.text = text;
#if UNITY_EDITOR
this.type = type;
#endif
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(HelpAttribute))]
public class HelpDrawer : PropertyDrawer {
const int paddingHeight = 8; // Used for top and bottom padding between the text and the HelpBox border.
const int marginHeight = 2; // Used to add some margin between the the HelpBox and the property.
float baseHeight = 0; // Global field to store the original (base) property height.
float addedHeight = 0; // Custom added height for drawing text area which has the MultilineAttribute.
HelpAttribute helpAttribute { get { return (HelpAttribute)attribute; } } // A wrapper which returns the PropertyDrawer.attribute field as a HelpAttribute.
RangeAttribute rangeAttribute {
get {
var attributes = fieldInfo.GetCustomAttributes(typeof(RangeAttribute), true);
return attributes != null && attributes.Length > 0 ? (RangeAttribute)attributes[0] : null;
}
}
MultilineAttribute multilineAttribute {
get {
var attributes = fieldInfo.GetCustomAttributes(typeof(MultilineAttribute), true);
return attributes != null && attributes.Length > 0 ? (MultilineAttribute)attributes[0] : null;
}
}
public override float GetPropertyHeight(SerializedProperty prop, GUIContent label) {
baseHeight = base.GetPropertyHeight(prop, label);
float minHeight = paddingHeight * 5;
var content = new GUIContent(helpAttribute.text);
var style = GUI.skin.GetStyle("helpbox");
var height = style.CalcHeight(content, EditorGUIUtility.currentViewWidth);
height += marginHeight * 2; // add tiny padding here to make sure the text is not overflowing the HelpBox from the top and bottom.
// Since we draw a custom text area with the label above if our property contains the
// MultilineAttribute, we need to add some extra height to compensate. This is stored in a
// seperate global field so we can use it again later.
if (multilineAttribute != null && prop.propertyType == SerializedPropertyType.String) {
addedHeight = 48f;
}
// If the calculated HelpBox is less than our minimum height we use this to calculate the returned height instead.
return height > minHeight ? height + baseHeight + addedHeight : minHeight + baseHeight + addedHeight;
}
public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label) {
var multiline = multilineAttribute;
EditorGUI.BeginProperty(position, label, prop);
// Copy the position out so we can calculate the position of our HelpBox without affecting the original position.
var helpPos = position;
helpPos.height -= baseHeight + marginHeight;
if (multiline != null) {
helpPos.height -= addedHeight;
}
// Renders the HelpBox in the Unity inspector UI.
EditorGUI.HelpBox(helpPos, helpAttribute.text, helpAttribute.type);
position.y += helpPos.height + marginHeight;
position.height = baseHeight;
// If we have a RangeAttribute on our field, we need to handle the PropertyDrawer differently to keep the same style as Unity's default.
var range = rangeAttribute;
if (range != null) {
if (prop.propertyType == SerializedPropertyType.Float) {
EditorGUI.Slider(position, prop, range.min, range.max, label);
}
else if (prop.propertyType == SerializedPropertyType.Integer) {
EditorGUI.IntSlider(position, prop, (int)range.min, (int)range.max, label);
} else {
EditorGUI.PropertyField(position, prop, label);
}
}
else if (multiline != null) {
// Here's where we handle the PropertyDrawer differently if we have a MultiLineAttribute, to try and keep some kind of multiline text area. This is not identical to Unity's default but is better than nothing...
if (prop.propertyType == SerializedPropertyType.String) {
var style = GUI.skin.label;
var size = style.CalcHeight(label, EditorGUIUtility.currentViewWidth);
EditorGUI.LabelField(position, label);
position.y += size;
position.height += addedHeight - size;
prop.stringValue = EditorGUI.TextArea(position, prop.stringValue);
}
else {
EditorGUI.PropertyField(position, prop, label);
}
}
else
{
// If we get to here it means we're drawing the default property field below the HelpBox. More custom
// and built in PropertyDrawers could be implemented to enable HelpBox but it could easily make for
// hefty else/if block which would need refactoring!
EditorGUI.PropertyField(position, prop, label);
}
EditorGUI.EndProperty();
}
}
#endif