自定义实现UISlider

2023-10-16 16:29:49 浏览数 (3)

代码语言:javascript复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Sprites;
using UnityEngine.EventSystems;

namespace UnityEngine.UIExtend
{
    [AddComponentMenu("UI/UISlider", 15)]
    public class UISlider : Graphic, IDragHandler, IEndDragHandler
    {
        public Slider.Direction m_Direction;
        public System.Action<float> m_OnValueChanged;
        [SerializeField]
        Sprite m_BackGround;
        [SerializeField]
        Sprite m_Fill;
        public RectTransform m_Handle;

        [Range(0, 1)]
        public float value;
        public Color fg_Color;
        private float curValue;
        public override void SetNativeSize()
        {
            base.SetNativeSize();
        }
        public override Texture mainTexture
        {
            get
            {
                if (m_BackGround == null)
                {
                    if (material != null && material.mainTexture != null)
                    {
                        return material.mainTexture;
                    }
                    return s_WhiteTexture;
                }

                return m_BackGround.texture;
            }
        }
        protected UISlider()
        {
            useLegacyMeshGeneration = false;
            raycastTarget = false;
            curValue = value;
        }

        protected override void OnPopulateMesh(VertexHelper vh)
        {
            base.OnPopulateMesh(vh);
            vh.Clear();
            Texture tex = mainTexture;
            var r = GetPixelAdjustedRect();
            Vector4 v = new Vector4(r.x, r.y, r.width   r.x, r.height   r.y);
            float horizontalNormal = r.width * value;
            float verticalNormal = r.height * value;
            if (curValue != value)
            {
                m_OnValueChanged?.Invoke(value);
                curValue = value;
            }
            if (m_Direction == Slider.Direction.LeftToRight || m_Direction == Slider.Direction.RightToLeft)
            {
                if (m_Direction == Slider.Direction.LeftToRight)
                {
                    if (m_BackGround != null)
                    {
                        var bgUV = DataUtility.GetInnerUV(m_BackGround);
                        var color32 = color;
                        float fill = (bgUV.z - bgUV.x) * value;
                        vh.AddVert(new Vector3(v.x   horizontalNormal, v.y), color32, new Vector2(bgUV.x   fill, bgUV.y)); //0
                        vh.AddVert(new Vector3(v.x   horizontalNormal, v.w), color32, new Vector2(bgUV.x   fill, bgUV.w)); //1
                        vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(bgUV.z, bgUV.w)); //2
                        vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(bgUV.z, bgUV.y)); //3
                        vh.AddTriangle(0, 1, 2);
                        vh.AddTriangle(2, 3, 0);
                    }
                    if (m_Fill != null)
                    {
                        var fileSpUV = DataUtility.GetInnerUV(m_Fill);
                        var colort = fg_Color;
                        float fill = (fileSpUV.z - fileSpUV.x) * value;
                        vh.AddVert(new Vector3(v.x, v.y), colort, new Vector2(fileSpUV.x, fileSpUV.y));  //4
                        vh.AddVert(new Vector3(v.x, v.w), colort, new Vector2(fileSpUV.x, fileSpUV.w)); //5
                        vh.AddVert(new Vector3(v.x   horizontalNormal, v.w), colort, new Vector2(fileSpUV.x   fill, fileSpUV.w)); //6
                        vh.AddVert(new Vector3(v.x   horizontalNormal, v.y), colort, new Vector2(fileSpUV.x   fill, fileSpUV.y)); //7
                        vh.AddTriangle(4, 5, 6);
                        vh.AddTriangle(6, 7, 4);
                    }
                    if (m_Handle != null)
                    {
                        float diffValue=r.width*(0.5f-m_Handle.anchorMin.x) - m_Handle.rect.width*(0.5f-m_Handle.anchorMin.x);
                        m_Handle.anchoredPosition = new Vector2(v.x   horizontalNormal diffValue, m_Handle.anchoredPosition.y);
                    }
                }
                if (m_Direction == Slider.Direction.RightToLeft)
                {
                    if (m_BackGround != null)
                    {

                        var spriteUV = DataUtility.GetInnerUV(m_BackGround);
                        var color32 = color;
                        float fill = (spriteUV.z - spriteUV.x) * value;
                        vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(spriteUV.x, spriteUV.y));
                        vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(spriteUV.x, spriteUV.w));
                        vh.AddVert(new Vector3(v.z - horizontalNormal, v.w), color32, new Vector2(spriteUV.z - fill, spriteUV.w));
                        vh.AddVert(new Vector3(v.z - horizontalNormal, v.y), color32, new Vector2(spriteUV.z - fill, spriteUV.y));
                        vh.AddTriangle(4, 5, 6);
                        vh.AddTriangle(6, 7, 4);
                    }
                    if (m_Fill != null)
                    {
                        var fileSpUV = DataUtility.GetInnerUV(m_Fill);
                        var colort = fg_Color;
                        float fill = (fileSpUV.z - fileSpUV.x) * value;
                        float vertFill = r.width * value;
                        vh.AddVert(new Vector3(v.z - horizontalNormal, v.y), colort, new Vector2(fileSpUV.z - fill, fileSpUV.y));
                        vh.AddVert(new Vector3(v.z - horizontalNormal, v.w), colort, new Vector2(fileSpUV.z - fill, fileSpUV.w));
                        vh.AddVert(new Vector3(v.z, v.w), colort, new Vector2(fileSpUV.z, fileSpUV.w));
                        vh.AddVert(new Vector3(v.z, v.y), colort, new Vector2(fileSpUV.z, fileSpUV.y));
                        vh.AddTriangle(0, 1, 2);
                        vh.AddTriangle(2, 3, 0);
                    }
                    if (m_Handle != null)
                    {
                        float diffValue=r.width*(0.5f-m_Handle.anchorMin.x) - m_Handle.rect.width*(0.5f-m_Handle.anchorMin.x);
                        m_Handle.anchoredPosition = new Vector2(v.z - horizontalNormal   diffValue, m_Handle.anchoredPosition.y);
                    }
                }
            }
            else
            {
                if (m_Direction == Slider.Direction.BottomToTop)
                {
                    if (m_BackGround != null)
                    {

                        var spriteUV = DataUtility.GetInnerUV(m_BackGround);
                        var color32 = color;
                        float fill = (spriteUV.w - spriteUV.y) * value;

                        vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(spriteUV.x, spriteUV.w)); //0
                        vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(spriteUV.z, spriteUV.w)); //1
                        vh.AddVert(new Vector3(v.z, v.y   verticalNormal), color32, new Vector2(spriteUV.z, spriteUV.y   fill)); //2
                        vh.AddVert(new Vector3(v.x, v.y   verticalNormal), color32, new Vector2(spriteUV.x, spriteUV.y   fill)); //3

                        vh.AddTriangle(0, 1, 2);
                        vh.AddTriangle(2, 3, 0);
                    }
                    if (m_Fill != null)
                    {
                        var fileSpUV = DataUtility.GetInnerUV(m_Fill);
                        var colort = fg_Color;
                        float fill = (fileSpUV.w - fileSpUV.y) * value;

                        vh.AddVert(new Vector3(v.x, v.y   verticalNormal), colort, new Vector2(fileSpUV.x, fileSpUV.y   fill));
                        vh.AddVert(new Vector3(v.z, v.y   verticalNormal), colort, new Vector2(fileSpUV.z, fileSpUV.y   fill));
                        vh.AddVert(new Vector3(v.z, v.y), colort, new Vector2(fileSpUV.z, fileSpUV.y));
                        vh.AddVert(new Vector3(v.x, v.y), colort, new Vector2(fileSpUV.x, fileSpUV.y));

                        vh.AddTriangle(4, 5, 6);
                        vh.AddTriangle(6, 7, 4);
                    }
                    if (m_Handle != null)
                    {
                        float diffValue=r.height*(0.5f-m_Handle.anchorMin.y) - m_Handle.rect.height*(0.5f-m_Handle.anchorMin.y);
                        m_Handle.anchoredPosition = new Vector2(m_Handle.anchoredPosition.x, v.y   verticalNormal diffValue);
                    }
                       
                }
                if (m_Direction == Slider.Direction.TopToBottom)
                {
                    if (m_Fill != null)
                    {
                        var spriteUV = DataUtility.GetInnerUV(m_Fill);
                        var color32 = color;
                        float fill = (spriteUV.w - spriteUV.y) * value;
                        vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(spriteUV.x, spriteUV.w)); //0
                        vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(spriteUV.z, spriteUV.w)); //1
                        vh.AddVert(new Vector3(v.z, v.w - verticalNormal), color32, new Vector2(spriteUV.z, spriteUV.w - fill)); //2
                        vh.AddVert(new Vector3(v.x, v.w - verticalNormal), color32, new Vector2(spriteUV.x, spriteUV.w - fill)); //3

                        vh.AddTriangle(0, 1, 2);
                        vh.AddTriangle(2, 3, 0);
                    }
                    if (m_BackGround != null)
                    {
                        var fileSpUV = DataUtility.GetInnerUV(m_BackGround);
                        var colort = fg_Color;
                        float fill = (fileSpUV.w - fileSpUV.y) * value;
                        vh.AddVert(new Vector3(v.x, v.w - verticalNormal), colort, new Vector2(fileSpUV.x, fileSpUV.w - fill));
                        vh.AddVert(new Vector3(v.z, v.w - verticalNormal), colort, new Vector2(fileSpUV.z, fileSpUV.w - fill));
                        vh.AddVert(new Vector3(v.z, v.y), colort, new Vector2(fileSpUV.z, fileSpUV.y));
                        vh.AddVert(new Vector3(v.x, v.y), colort, new Vector2(fileSpUV.x, fileSpUV.y));

                        vh.AddTriangle(4, 5, 6);
                        vh.AddTriangle(6, 7, 4);
                    }
                    if (m_Handle != null)
                    {
                        float diffValue=r.height*(0.5f-m_Handle.anchorMin.y) - m_Handle.rect.height*(0.5f-m_Handle.anchorMin.y);
                        m_Handle.anchoredPosition = new Vector2(m_Handle.anchoredPosition.x, v.w - verticalNormal diffValue);
                    }
                }
            }



        }

        public void OnDrag(PointerEventData eventData)
        {
            if (m_Handle == null) return;
            Vector2 localCursor;
            if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(this.rectTransform, eventData.position, eventData.pressEventCamera, out localCursor))
                return;
            var r = GetPixelAdjustedRect();
            if (m_Direction == Slider.Direction.LeftToRight)
                value = Mathf.Clamp01((localCursor.x - r.x) / r.width);
            else if (m_Direction == Slider.Direction.RightToLeft)
                value = 1 - Mathf.Clamp01((localCursor.x - r.x) / r.width);
            else if (m_Direction == Slider.Direction.TopToBottom)
                value = 1 - Mathf.Clamp01((localCursor.y - r.y) / r.height);
            else if (m_Direction == Slider.Direction.BottomToTop)
                value = Mathf.Clamp01((localCursor.y - r.y) / r.height);
            SetVerticesDirty();
        }

        public void OnEndDrag(PointerEventData eventData)
        {
            if (m_Handle == null) return;
            Vector2 localCursor;
            if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(this.rectTransform, eventData.position, eventData.pressEventCamera, out localCursor))
                return;
            var r = GetPixelAdjustedRect();
            if (m_Direction == Slider.Direction.LeftToRight)
                value = Mathf.Clamp01((localCursor.x - r.x) / r.width);
            else if (m_Direction == Slider.Direction.RightToLeft)
                value = 1 - Mathf.Clamp01((localCursor.x - r.x) / r.width);
            else if (m_Direction == Slider.Direction.TopToBottom)
                value = 1 - Mathf.Clamp01((localCursor.y - r.y) / r.height);
            else if (m_Direction == Slider.Direction.BottomToTop)
                value = Mathf.Clamp01((localCursor.y - r.y) / r.height);
            SetVerticesDirty();
        }
    }
}

0 人点赞