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

猜你喜欢

转载自blog.csdn.net/qq_36848370/article/details/103726991