【Unity3D】制作进度条——让Image同时具有Filled和Sliced的功能

解决方案转载于:UGUI——重写Image类实现进度条 作者:糯米团子滚呀滚

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Sprites;

public class childImage :  Image{
    
    

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
    
    
        base.OnPopulateMesh(toFill);
        if (overrideSprite == null)
        {
    
    
            base.OnPopulateMesh(toFill);
            return;
        }
        if (type == Type.Sliced)
        {
    
    
            GenerateSlicedSprite_(toFill);
        }
    }

    Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
    {
    
    
        for (int axis = 0; axis <= 1; axis++)
        {
    
    
            // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
            // In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
            float combinedBorders = border[axis] + border[axis + 2];
            if (rect.size[axis] < combinedBorders && combinedBorders != 0)
            {
    
    
                float borderScaleRatio = rect.size[axis] / combinedBorders;
                border[axis] *= borderScaleRatio;
                border[axis + 2] *= borderScaleRatio;
            }
        }
        return border;
    }

    static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
    {
    
    
        int startIndex = vertexHelper.currentVertCount;

        vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
        vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
        vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
        vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));

        vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
        vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
    }
    private void GenerateSlicedSprite_(VertexHelper toFill)
    {
    
    
        Vector4 outer, inner, padding, border;

        if (overrideSprite != null)
        {
    
    
            outer = DataUtility.GetOuterUV(overrideSprite);
            inner = DataUtility.GetInnerUV(overrideSprite);
            padding = DataUtility.GetPadding(overrideSprite);
            border = overrideSprite.border;
        }
        else
        {
    
    
            outer = Vector4.zero;
            inner = Vector4.zero;
            padding = Vector4.zero;
            border = Vector4.zero;
        }

        Rect rect = GetPixelAdjustedRect();
        border = GetAdjustedBorders(border / pixelsPerUnit, rect);
        padding = padding / pixelsPerUnit;
        float condition = (border.z + border.x) / rect.width;
        #region 实际显示size
        float[] x={
    
    0,0,0,0};

        x[0] = 0;
        if (fillAmount <condition)
        {
    
    
            x[1] = fillAmount / 2 * rect.width;
            x[2] = x[1]+ 0;
            x[3] = x[1]*2;
        }
        else
        {
    
    
          x[1] = border.x;
          x[2] = rect.width *fillAmount-border.z;
          x[3] =x[2]+border.z;
        }
        float []y ={
    
    0+rect.y,rect.height+rect.y};

        for (int i = 0; i < 4; ++i)
        {
    
    
            x[i] += rect.x;

        }
        #endregion

        #region uv值
        float[] x_uv = {
    
    0,0,0,0 };

        x_uv[0] =0;
        if (fillAmount <condition)
        {
    
    
            x_uv[1] = fillAmount*rect.width/2/sprite.rect.size.x;
            x_uv[2] = 1 - x_uv[1];
        }
        else
        {
    
    
            x_uv[1] = inner.x;
            x_uv[2] = inner.z;
        }
        x_uv[3] = outer.z;

        float y_uv = 1;
        #endregion

        toFill.Clear();
        for (int i = 0; i < 3; i++)
        {
    
    
            int i2 = i + 1;
            AddQuad(toFill,
                    new Vector2(x[i],y[0]),
                    new Vector2(x[i2],y[1]),
                    color,
                    new Vector2(x_uv[i],0),
                    new Vector2(x_uv[i2],y_uv));
        }

    }


}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.UI;
using UnityEditor;
using UnityEditor.AnimatedValues;
using System.Linq;

[CustomEditor(typeof(childImage))]
public class ChildchildImageInspector : ImageEditor
{
    
    
    SerializedProperty m_FillMethod;
    SerializedProperty m_FillOrigin;
    SerializedProperty m_FillAmount;
    SerializedProperty m_FillClockwise;
    SerializedProperty m_Type;
    SerializedProperty m_FillCenter;
    SerializedProperty m_Sprite;
    SerializedProperty m_PreserveAspect;
    GUIContent m_SpriteContent;
    GUIContent m_SpriteTypeContent;
    GUIContent m_ClockwiseContent;
    AnimBool m_ShowSlicedOrTiled;
    AnimBool m_ShowSliced;
    AnimBool m_ShowFilled;
    AnimBool m_ShowType;

    void SetShowNativeSize(bool instant)
    {
    
    
        childImage.Type type = (childImage.Type)m_Type.enumValueIndex;
        bool showNativeSize = (type == childImage.Type.Simple || type == childImage.Type.Filled);
        base.SetShowNativeSize(showNativeSize, instant);
    }
    protected override void OnEnable()
    {
    
    
        base.OnEnable();
        m_SpriteContent = new GUIContent("Source childImage");
        m_SpriteTypeContent = new GUIContent("childImage Type");
        m_ClockwiseContent = new GUIContent("Clockwise");

        m_Sprite = serializedObject.FindProperty("m_Sprite");
        m_Type = serializedObject.FindProperty("m_Type");
        m_FillCenter = serializedObject.FindProperty("m_FillCenter");
        m_FillMethod = serializedObject.FindProperty("m_FillMethod");
        m_FillOrigin = serializedObject.FindProperty("m_FillOrigin");
        m_FillClockwise = serializedObject.FindProperty("m_FillClockwise");
        m_FillAmount = serializedObject.FindProperty("m_FillAmount");
        m_PreserveAspect = serializedObject.FindProperty("m_PreserveAspect");

        m_ShowType = new AnimBool(m_Sprite.objectReferenceValue != null);
        m_ShowType.valueChanged.AddListener(Repaint);

        var typeEnum = (childImage.Type)m_Type.enumValueIndex;
        m_ShowSlicedOrTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
        m_ShowSliced = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
        m_ShowFilled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Filled);
        m_ShowSlicedOrTiled.valueChanged.AddListener(Repaint);
        m_ShowSliced.valueChanged.AddListener(Repaint);
        m_ShowFilled.valueChanged.AddListener(Repaint);

        SetShowNativeSize(true);
    }
    public override void OnInspectorGUI()
    {
    
    
        serializedObject.Update();

        SpriteGUI();
        AppearanceControlsGUI();
        RaycastControlsGUI();

        m_ShowType.target = m_Sprite.objectReferenceValue != null;
        if (EditorGUILayout.BeginFadeGroup(m_ShowType.faded))
        {
    
    
            EditorGUILayout.PropertyField(m_Type, m_SpriteTypeContent);

            ++EditorGUI.indentLevel;
            {
    
    
                childImage.Type typeEnum = (childImage.Type)m_Type.enumValueIndex;
                bool showSlicedOrTiled = (!m_Type.hasMultipleDifferentValues && (typeEnum ==childImage.Type.Sliced|| typeEnum == childImage.Type.Tiled));
                if (showSlicedOrTiled && targets.Length > 1)
                    showSlicedOrTiled = targets.Select(obj => obj as childImage).All(img => img.hasBorder);

                m_ShowSlicedOrTiled.target = showSlicedOrTiled;
                m_ShowSliced.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
                m_ShowFilled.target = (!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Filled);

                childImage cImage = target as childImage;

                if (EditorGUILayout.BeginFadeGroup(m_ShowSlicedOrTiled.faded))
                {
    
    
                    if (cImage.hasBorder)
                    {
    
    
                        EditorGUILayout.PropertyField(m_FillCenter);
                        EditorGUILayout.PropertyField(m_FillAmount);
                    }

                }
                EditorGUILayout.EndFadeGroup();

                if (EditorGUILayout.BeginFadeGroup(m_ShowSliced.faded))
                {
    
    
                    if (cImage.sprite != null && !cImage.hasBorder)
                        EditorGUILayout.HelpBox("This childImage doesn't have a border.", MessageType.Warning);
                }
                EditorGUILayout.EndFadeGroup();

                if (EditorGUILayout.BeginFadeGroup(m_ShowFilled.faded))
                {
    
    
                    EditorGUI.BeginChangeCheck();
                    EditorGUILayout.PropertyField(m_FillMethod);
                    if (EditorGUI.EndChangeCheck())
                    {
    
    
                        m_FillOrigin.intValue = 0;
                    }
                    switch ((childImage.FillMethod)m_FillMethod.enumValueIndex)
                    {
    
    
                        case childImage.FillMethod.Horizontal:
                            m_FillOrigin.intValue = (int)(childImage.OriginHorizontal)EditorGUILayout.EnumPopup("Fill Origin", (childImage.OriginHorizontal)m_FillOrigin.intValue);
                            break;
                        case childImage.FillMethod.Vertical:
                            m_FillOrigin.intValue = (int)(childImage.OriginVertical)EditorGUILayout.EnumPopup("Fill Origin", (childImage.OriginVertical)m_FillOrigin.intValue);
                            break;
                        case childImage.FillMethod.Radial90:
                            m_FillOrigin.intValue = (int)(childImage.Origin90)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin90)m_FillOrigin.intValue);
                            break;
                        case childImage.FillMethod.Radial180:
                            m_FillOrigin.intValue = (int)(childImage.Origin180)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin180)m_FillOrigin.intValue);
                            break;
                        case childImage.FillMethod.Radial360:
                            m_FillOrigin.intValue = (int)(childImage.Origin360)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin360)m_FillOrigin.intValue);
                            break;
                    }
                    EditorGUILayout.PropertyField(m_FillAmount);
                    if ((childImage.FillMethod)m_FillMethod.enumValueIndex > childImage.FillMethod.Vertical)
                    {
    
    
                        EditorGUILayout.PropertyField(m_FillClockwise, m_ClockwiseContent);
                    }
                }
                EditorGUILayout.EndFadeGroup();
            }
            --EditorGUI.indentLevel;
        }

        EditorGUILayout.EndFadeGroup();

        SetShowNativeSize(false);
        if (EditorGUILayout.BeginFadeGroup(m_ShowNativeSize.faded))
        {
    
    
            EditorGUI.indentLevel++;
            EditorGUILayout.PropertyField(m_PreserveAspect);
            EditorGUI.indentLevel--;
        }
        EditorGUILayout.EndFadeGroup();
        NativeSizeButtonGUI();

        serializedObject.ApplyModifiedProperties();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_37658157/article/details/108796097