UGUI Image組件檢視面板編輯器擴展(ImageEditor類)

問題描述


    說到Unity的檢視面板編輯器擴展,相信大家都不會陌生。但是當你嘗試用同樣的方式去擴展UGUI的組件時,會發現根本沒有效果。

解決方案


    這個問題的解決方案有兩個關鍵點:

用繼承的方式避開同系統編輯器擴展的衝突
所擴展的編輯器類要繼承ImageEditor類而不是Editor類


測試版本

Unity2018.4.0

前提條件
    由於所要使用的ImageEditor類所在命名空間爲UnityEditor.UI,而這個命名空間並不能直接敲出來。Unity一邊的錯誤提示是程序集引用錯誤。這是一個坑點。

解決方法:需要手動將Unity安裝路徑Unity\Editor\Data\UnityExtensions\Unity\GUISystem\Editor 下的UnityEditor.UI.dll文件拷貝到當前項目的Assets文件夾的Plugins加下。

源代碼

using UnityEngine.UI;
using UnityEngine.Sprites;
using UnityEngine;
public class CircletImage : Image
{
    [SerializeField]
    // 多少份三角形 拼成的圓形
     int segements = 100;
    //顯示部分佔圓形的百分比
    [SerializeField]
     float showPercent = 0.5f;
    //需要繪製的頂點面片數據都存在了vh
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        float width = rectTransform.rect.width;
        float height = rectTransform.rect.height; 

        int realsegments = (int)(segements * showPercent);
        //先 引入 using UnityEngine.Sprites; 命名空間 再獲取圖片的外層的UV  
        //最好使用父類的overrideSprite  不使用sprite 具體因爲啥我也不知道
        Vector4 uv = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
        float uvWidth = (uv.z - uv.x);
        float uvHeight = (uv.w - uv.y);
        //獲取UI中心
        Vector2 uvCenter = new Vector2(uvWidth * 0.5f, uvHeight * 0.5f);
        //求出於組件的寬高比
        Vector2 convertRatio = new Vector2(uvWidth / width, uvHeight / height);
        //單個三角形的弧度
        float radian = (2 * Mathf.PI) / segements;
        //獲取半徑
        float radius = width * 0.5f;

        //有了弧度 有了半徑 就能求出 頂點的座標 通過 Sin Cos 函數
        //生成 順時針 生成三角形  0 是中心點

        Vector2 posTemp = Vector2.zero;
        UIVertex origin = new UIVertex();
        origin.color = color;
        origin.position = posTemp;
        // 換算UV座標對應到Image中的位置  因爲牽扯到Pivot 的0.5
        origin.uv0 = new Vector2(posTemp.x * convertRatio.x + uvCenter.x, posTemp.y * convertRatio.y + uvCenter.y);
        //添加頂點
        vh.AddVert(origin);
        //獲取頂點的個數
        int vertexCont = realsegments + 1;
        float curRadian = 0;
        for (int i = 0; i < vertexCont; i++)
        {
            //獲取當前的頂點座標
            float x = Mathf.Cos(curRadian) * radius;
            float y = Mathf.Sin(curRadian) * radius;
            //累加 三角形弧度
            curRadian += radian;
            UIVertex vertexTemp = new UIVertex();
            vertexTemp.color = color;
            posTemp = new Vector2(x, y);
            vertexTemp.position = posTemp;
            // 換算UV座標對應到Image中的位置  因爲牽扯到Pivot 的0.5
            vertexTemp.uv0 = new Vector2(posTemp.x * convertRatio.x + uvCenter.x, posTemp.y * convertRatio.y + uvCenter.y);
            vh.AddVert(vertexTemp);
        }
        int id = 1;
        for (int i = 0; i < realsegments; i++)
        {
            //生成 順時針 生成三角形  0 是中心點  傳入三個頂點  三個頂點是i , 0,i+1
            vh.AddTriangle(id, 0, id + 1);
            id++;
        }
    }
}

 

using UnityEngine;
using UnityEditor;
using UnityEditor.UI;
[CustomEditor(typeof(CircletImage), true)]
[CanEditMultipleObjects]
public class CircletImageEditor : ImageEditor
{
    SerializedProperty _fillPercent;
    SerializedProperty _segements;
    protected override void OnEnable()
    {
        base.OnEnable();
        _fillPercent = serializedObject.FindProperty("showPercent");
        _segements = serializedObject.FindProperty("segements");
    }
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        if (GUILayout.Button("測試按鈕"))
        {
        }
        serializedObject.Update();
        EditorGUILayout.Slider(_fillPercent, 0, 1, new GUIContent("showPercent"));
        EditorGUILayout.PropertyField(_segements);
        serializedObject.ApplyModifiedProperties();
        if (GUI.changed)
        {
            EditorUtility.SetDirty(target);
        }
    }
}

參考文獻

https://blog.csdn.net/duzixi/article/details/78013295

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章