Mesh-Clip分割_skybeauty_新浪博客

Mesh-Clip分割

效果图如上,分割各种多边形图,具体操作是通过修改uv过滤显示,具体代码如下:


using System;
using UnityEngine;
using UnityEngine.UI;
public class MeshClipBase : MaskableGraphic, ILayoutElement, ICanvasRaycastFilter
{
    [SerializeField]
    Sprite m_Sprite;
    public Sprite sprite
    {
        get { return m_Sprite; }
        set
        {
            m_Sprite = value;
            SetAllDirty();
        }
    }
    [NonSerialized]
    Sprite m_OverrirdeSprite;
    public Sprite overrideSprite
    {
        get { return m_OverrirdeSprite==null?sprite:m_OverrirdeSprite; }
        set
        {
            m_OverrirdeSprite = value;
            SetAllDirty();
        }
    }
    public float alphaThreshold = 1;
    public override Texture mainTexture
    {
        get
        {
            if (overrideSprite != null)
            {
                return overrideSprite.texture;
            }
            else if (material != null && material.mainTexture != null)
            {
                return material.mainTexture;
            }
            else
            {
                return s_WhiteTexture;
            }
        }
    }
    public float pixelsPerUnit
    {
        get
        {
            float spritePixelsPerUnit = 100;
            float referencePixelsPerUnit = 100;
            if (sprite != null)
            {
                spritePixelsPerUnit = sprite.pixelsPerUnit;
            }
            if (canvas != null)
            {
                referencePixelsPerUnit = canvas.referencePixelsPerUnit;
            }
            return spritePixelsPerUnit / referencePixelsPerUnit;
        }
    }
    protected UIVertex[] SetVBO(Vector2[] vertices, Vector2[] uvs)
    {
        UIVertex[] vbo = new UIVertex[4];
        for (int i = 0; i < vertices.Length; i++)
        {
            UIVertex vertex = UIVertex.simpleVert;
            vertex.color = color;
            vertex.position = vertices[i];
            vertex.uv0 = uvs[i];
            vbo[i] = vertex;
        }
        return vbo;
    }
    public float minWidth => 0;
    public float preferredWidth => overrideSprite!=null ? overrideSprite.rect.size.x/pixelsPerUnit:0 ;
    public float flexibleWidth => -1;
    public float minHeight => 0;
    public float preferredHeight => overrideSprite!=null? overrideSprite.rect.size.y/pixelsPerUnit :0;
    public float flexibleHeight => -1;
    public int layoutPriority => 0;
    public void CalculateLayoutInputHorizontal()
    {
        throw new System.NotImplementedException();
    }
    public void CalculateLayoutInputVertical()
    {
        throw new System.NotImplementedException();
    }
    public bool IsRaycastLocationValid(Vector2 point, Camera eventCamera)
    {
        if (alphaThreshold >= 1 || overrideSprite==null) return true;
        Sprite sp = overrideSprite;
        Vector2 local;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,point , eventCamera, out local);
        Rect rect = GetPixelAdjustedRect();
        local.x += rectTransform.pivot.x * rect.width;
        local.y += rectTransform.pivot.y * rect.height;
        local = MapCoordinate(local, rect);
        Rect sp_rect = sprite.textureRect;
        Vector2 normallized = new Vector2(local.x / sp_rect.width, local.y / sp_rect.height);
        float x = Mathf.Lerp(sp_rect.x, sp_rect.xMax, normallized.x) / sp.texture.width;
        float y = Mathf.Lerp(sp_rect.y, sp_rect.yMax, normallized.y) / sp.texture.height;
        return sp.texture.GetPixelBilinear(x, y).a >= alphaThreshold;

    }
    Vector2 MapCoordinate(Vector2 local, Rect rect)
    {
        Rect sp_rect = sprite.rect;
        return new Vector2(local.x * sp_rect.width / rect.width, local.y * sp_rect.height / rect.height);
    }

    Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
    {
        for (int i = 0; i <= 1; i++)
        {
            float combineBorders = border[i] + border[i + 2];
            if ( combineBorders != 0 && rect.size[i] < combineBorders)
            {
                float borderScaleRatio = rect.size[i] / combineBorders;
                border[i] *= borderScaleRatio;
                border[i + 2] *= borderScaleRatio;
            }
        }
        return border;
    }
}


using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MeshClip : MeshClipBase
{
    static readonly int FILL_PERCENT = 100;
    public bool isFill = true;
    public float thicness = 5;
    [Range(3,360)]
    public int sides = 6;
    [Range(0, 360)]
    public float rotation = 0;
    [Range(0, 1)]
    public List verticesValues;
    float size = 0;
    public void SetVerticeValues(List values)
    {
        if (values != null)
        {
            verticesValues.Clear();
            verticesValues.AddRange(values);
        }
        else
        {
            ResetValues();
        }
       
      
        SetVerticesDirty();
#if UNITY_EDITOR
        UnityEditor.EditorUtility.SetDirty(transform);
#endif
    }
    public void DrawPolygon(int m_sides,float m_rotation =0,List m_verticesValues = null)
    {
        sides = m_sides;
        if (m_verticesValues != null)
        {
            verticesValues.Clear();
            verticesValues.AddRange(m_verticesValues);
        }
        else
        {
            ResetValues();
        }
        rotation = m_rotation;
    }
    protected override void OnRectTransformDimensionsChange()
    {
        base.OnRectTransformDimensionsChange();
        size = Mathf.Min( rectTransform.rect.width,rectTransform.rect.height);
        thicness = (float)Mathf.Clamp(thicness, 0, size / 2);
    }
    void StepThroughPointsAndFill(float outer, float inner, ref Vector2 prevX, ref Vector2 prevY, out Vector2 pos0, out Vector2 pos1, out Vector2 pos2, out Vector2 pos3, float cos, float sin)
    {
        pos0 = prevX;
        pos1 = new Vector2(outer * cos, inner * sin);
        pos2 = Vector2.zero;
        pos3 = Vector2.zero;
        prevX = pos1;
        prevY = pos2;
    }
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        float flag = -rectTransform.pivot.x * size;
        float outer = flag;
        float inner = flag + thicness;
        vh.Clear();
        Vector2 prevX = Vector2.zero;
        Vector2 prevY = Vector2.zero;
        Vector2 uv0 = Vector2.zero;
        Vector2 uv1 = Vector2.up;
        Vector2 uv2 = Vector2.one;
        Vector2 uv3 = Vector2.right;
        Vector2 pos0;
        Vector2 pos1;
        Vector2 pos2;
        Vector2 pos3;
        float w = rectTransform.rect.width;
        float h = rectTransform.rect.height;
        if (verticesValues.Count != sides)
        {
            ResetValues();
        }
        float angleStep = (FILL_PERCENT / 100f *( Mathf.PI * 2f)) / sides;
        float currentAngle = 0;
        Vector2[] pos = new Vector2[4];
        Vector2[] uv = new Vector2[4];
        for (int i = 0; i <= sides; i++)
        {
            float angle = currentAngle + rotation;
            float cos = Mathf.Cos(angle);
            float sin = Mathf.Sin(angle);
            outer = flag * verticesValues[i % sides];
            inner = flag * verticesValues[i % sides] +thicness;
            StepThroughPointsAndFill(outer ,inner,ref prevX,ref prevY,out pos0,out pos1,out pos2,out pos3,cos,sin);
            uv0 = Vector2.one * 0.5f + new Vector2(pos0.x / w, pos0.y / h);
            uv1 = Vector2.one * 0.5f + new Vector2(pos1.x / w, pos1.y / h);
            uv2 = Vector2.one * 0.5f + new Vector2(pos2.x / w, pos2.y / h);
            uv3 = Vector2.one * 0.5f + new Vector2(pos3.x / w, pos3.y / h);
            pos[0] = pos0;
            pos[1] = pos1;
            pos[2] = pos2;
            pos[3] = pos3;
            uv[0] = uv0;
            uv[1] = uv1;
            uv[2] = uv2;
            uv[3] = uv3;
            vh.AddUIVertexQuad( SetVBO( pos,uv));
            currentAngle += angleStep;
        }
    }
    void ResetValues()
    {
        verticesValues.Clear();
        for (int i = 0; i < sides; i++)
        {
            verticesValues.Add(1);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值