227 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			227 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
using UnityEngine;
 | 
						|
using UnityEditor;
 | 
						|
 | 
						|
[CanEditMultipleObjects]
 | 
						|
[CustomEditor(typeof(Transform), true)]
 | 
						|
public class UGuiRectTransformInspector : Editor
 | 
						|
{
 | 
						|
    static public UGuiRectTransformInspector instance;
 | 
						|
 | 
						|
    SerializedProperty mPos;
 | 
						|
    SerializedProperty mRot;
 | 
						|
    SerializedProperty mScale;
 | 
						|
 | 
						|
    void OnEnable()
 | 
						|
    {
 | 
						|
        instance = this;
 | 
						|
        mPos = serializedObject.FindProperty("m_LocalPosition");
 | 
						|
        mRot = serializedObject.FindProperty("m_LocalRotation");
 | 
						|
        mScale = serializedObject.FindProperty("m_LocalScale");
 | 
						|
    }
 | 
						|
 | 
						|
    void OnDestroy() { instance = null; }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 开始绘制Transform
 | 
						|
    /// </summary>
 | 
						|
    public override void OnInspectorGUI()
 | 
						|
    {
 | 
						|
        EditorGUIUtility.labelWidth = 15;
 | 
						|
 | 
						|
        serializedObject.Update();
 | 
						|
        DrawPosition();
 | 
						|
        DrawRotation();
 | 
						|
        DrawScale();
 | 
						|
 | 
						|
        serializedObject.ApplyModifiedProperties();
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 绘制坐标
 | 
						|
    /// </summary>
 | 
						|
    void DrawPosition()
 | 
						|
    {
 | 
						|
        GUILayout.BeginHorizontal();
 | 
						|
        {
 | 
						|
            bool reset = GUILayout.Button("P", GUILayout.Width(20f));
 | 
						|
 | 
						|
            EditorGUILayout.PropertyField(mPos.FindPropertyRelative("x"));
 | 
						|
            EditorGUILayout.PropertyField(mPos.FindPropertyRelative("y"));
 | 
						|
            EditorGUILayout.PropertyField(mPos.FindPropertyRelative("z"));
 | 
						|
 | 
						|
            if (reset) mPos.vector3Value = Vector3.zero;
 | 
						|
        }
 | 
						|
        GUILayout.EndHorizontal();
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 绘制形变
 | 
						|
    /// </summary>
 | 
						|
    void DrawScale()
 | 
						|
    {
 | 
						|
        GUILayout.BeginHorizontal();
 | 
						|
        {
 | 
						|
            bool reset = GUILayout.Button("S", GUILayout.Width(20f));
 | 
						|
 | 
						|
            EditorGUILayout.PropertyField(mScale.FindPropertyRelative("x"));
 | 
						|
            EditorGUILayout.PropertyField(mScale.FindPropertyRelative("y"));
 | 
						|
            EditorGUILayout.PropertyField(mScale.FindPropertyRelative("z"));
 | 
						|
 | 
						|
            if (reset) mScale.vector3Value = Vector3.one;
 | 
						|
        }
 | 
						|
        GUILayout.EndHorizontal();
 | 
						|
    }
 | 
						|
 | 
						|
    #region 旋转个坑爹玩意......因为四元属性绘制没有原生支持
 | 
						|
    enum Axes : int
 | 
						|
    {
 | 
						|
        None = 0,
 | 
						|
        X = 1,
 | 
						|
        Y = 2,
 | 
						|
        Z = 4,
 | 
						|
        All = 7,
 | 
						|
    }
 | 
						|
 | 
						|
    Axes CheckDifference(Transform t, Vector3 original)
 | 
						|
    {
 | 
						|
        Vector3 next = t.localEulerAngles;
 | 
						|
 | 
						|
        Axes axes = Axes.None;
 | 
						|
 | 
						|
        if (Differs(next.x, original.x)) axes |= Axes.X;
 | 
						|
        if (Differs(next.y, original.y)) axes |= Axes.Y;
 | 
						|
        if (Differs(next.z, original.z)) axes |= Axes.Z;
 | 
						|
 | 
						|
        return axes;
 | 
						|
    }
 | 
						|
 | 
						|
    Axes CheckDifference(SerializedProperty property)
 | 
						|
    {
 | 
						|
        Axes axes = Axes.None;
 | 
						|
 | 
						|
        if (property.hasMultipleDifferentValues)
 | 
						|
        {
 | 
						|
            Vector3 original = property.quaternionValue.eulerAngles;
 | 
						|
 | 
						|
            foreach (Object obj in serializedObject.targetObjects)
 | 
						|
            {
 | 
						|
                axes |= CheckDifference(obj as Transform, original);
 | 
						|
                if (axes == Axes.All) break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return axes;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 绘制一个可编辑的浮动区域
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="hidden">是否值用 -- 代替</param>
 | 
						|
    static bool FloatField(string name, ref float value, bool hidden, GUILayoutOption opt)
 | 
						|
    {
 | 
						|
        float newValue = value;
 | 
						|
        GUI.changed = false;
 | 
						|
 | 
						|
        if (!hidden)
 | 
						|
        {
 | 
						|
            newValue = EditorGUILayout.FloatField(name, newValue, opt);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            float.TryParse(EditorGUILayout.TextField(name, "--", opt), out newValue);
 | 
						|
        }
 | 
						|
 | 
						|
        if (GUI.changed && Differs(newValue, value))
 | 
						|
        {
 | 
						|
            value = newValue;
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 由于 Mathf.Approximately 太敏感.
 | 
						|
    /// </summary>
 | 
						|
 | 
						|
    static bool Differs(float a, float b) { return Mathf.Abs(a - b) > 0.0001f; }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 绘制旋转
 | 
						|
    /// </summary>
 | 
						|
    void DrawRotation()
 | 
						|
    {
 | 
						|
        GUILayout.BeginHorizontal();
 | 
						|
        {
 | 
						|
            bool reset = GUILayout.Button("R", GUILayout.Width(20f));
 | 
						|
 | 
						|
            Vector3 visible = (serializedObject.targetObject as Transform).localEulerAngles;
 | 
						|
 | 
						|
            visible.x = WrapAngle(visible.x);
 | 
						|
            visible.y = WrapAngle(visible.y);
 | 
						|
            visible.z = WrapAngle(visible.z);
 | 
						|
 | 
						|
            Axes changed = CheckDifference(mRot);
 | 
						|
            Axes altered = Axes.None;
 | 
						|
 | 
						|
            GUILayoutOption opt = GUILayout.MinWidth(30f);
 | 
						|
 | 
						|
            if (FloatField("X", ref visible.x, (changed & Axes.X) != 0, opt)) altered |= Axes.X;
 | 
						|
            if (FloatField("Y", ref visible.y, (changed & Axes.Y) != 0, opt)) altered |= Axes.Y;
 | 
						|
            if (FloatField("Z", ref visible.z, (changed & Axes.Z) != 0, opt)) altered |= Axes.Z;
 | 
						|
 | 
						|
            if (reset)
 | 
						|
            {
 | 
						|
                mRot.quaternionValue = Quaternion.identity;
 | 
						|
            }
 | 
						|
            else if (altered != Axes.None)
 | 
						|
            {
 | 
						|
                RegisterUndo("Change Rotation", serializedObject.targetObjects);
 | 
						|
 | 
						|
                foreach (Object obj in serializedObject.targetObjects)
 | 
						|
                {
 | 
						|
                    Transform t = obj as Transform;
 | 
						|
                    Vector3 v = t.localEulerAngles;
 | 
						|
 | 
						|
                    if ((altered & Axes.X) != 0) v.x = visible.x;
 | 
						|
                    if ((altered & Axes.Y) != 0) v.y = visible.y;
 | 
						|
                    if ((altered & Axes.Z) != 0) v.z = visible.z;
 | 
						|
 | 
						|
                    t.localEulerAngles = v;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        GUILayout.EndHorizontal();
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 保证角在 180到-180度之间
 | 
						|
    /// </summary>
 | 
						|
 | 
						|
    [System.Diagnostics.DebuggerHidden]
 | 
						|
    [System.Diagnostics.DebuggerStepThrough]
 | 
						|
    static public float WrapAngle(float angle)
 | 
						|
    {
 | 
						|
        while (angle > 180f) angle -= 360f;
 | 
						|
        while (angle < -180f) angle += 360f;
 | 
						|
        return angle;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// 创建制定对象的撤消点
 | 
						|
    /// </summary>
 | 
						|
    static public void RegisterUndo(string name, params Object[] objects)
 | 
						|
    {
 | 
						|
        if (objects != null && objects.Length > 0)
 | 
						|
        {
 | 
						|
            UnityEditor.Undo.RecordObjects(objects, name);
 | 
						|
 | 
						|
            foreach (Object obj in objects)
 | 
						|
            {
 | 
						|
                if (obj == null) continue;
 | 
						|
                EditorUtility.SetDirty(obj);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    #endregion
 | 
						|
}
 |