Unity 画线OnPopulateMesh函数VertexHelper

关于OnPopulateMesh函数 和 VertexHelper类参考:Unity中UGUI的 OnPopulateMesh函数与VertexHelper类_Peter_Gao_的博客-CSDN博客

一个画图表(折线图,树状图,饼状图,雷达图)的插件。

底层使用UGUI中的重写了OnPopulateMesh这个方法, 用来实现鼠标画线的功能。

OnPopulateMesh(VertexHelper vh) 
{

}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public enum LineType
{
    Straight,
    Smooth
}
 
public class DrawLineComponent : Graphic
{
    [Header("线的属性")]
    [SerializeField] private LineType lineType = LineType.Straight;
    [SerializeField] private Line line = new StraightLine();
    [SerializeField] protected float m_ChartWidth;
    [NonSerialized] private bool m_RefreshChart = false;
    public float chartWidth { get { return m_ChartWidth; } }
    public LineType LineType
    {
        get => lineType;
        set
        {
            lineType = value;
            if (value == LineType.Straight)
                line = new StraightLine();
            else
                line = new SmoothLine();
            m_RefreshChart = true;
 
        }
    }
 
    protected override void Awake()
    {
        base.Awake();
        m_ChartWidth = rectTransform.sizeDelta.x;
        if (LineType == LineType.Smooth)
            line = new SmoothLine();
    }
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        line.DrawLine(vh);
    }
    private void Update()
    {
        CheckRefreshChart();
    }
    protected void CheckRefreshChart()
    {
        if (m_RefreshChart)
        {
            int tempWid = (int)chartWidth;
            rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, tempWid - 1);
            rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, tempWid);
            m_RefreshChart = false;
        }
    }
    public void AddPoint(Vector3 v3)
    {
        line.AddPoint(v3);
        m_RefreshChart = true;
    }
    public void AddPoint(List points)
    {
        line.AddPoint(points);
        m_RefreshChart = true;
 
    }
 
    public void SetSize(float size)
    {
        line.size = size;
        m_RefreshChart = true;
 
    }
    public void SetColor(Color color)
    {
        line.lineColor = color;
        m_RefreshChart = true;
 
    }
    public void SetSmoothness(float smoothness)
    {
        if (LineType == LineType.Smooth)
            ((SmoothLine)line).smoothness = smoothness;
 
        m_RefreshChart = true;
 
    }
    public void SetLineSmoothStyle(float smoothStyle)
    {
        if (LineType == LineType.Smooth)
            ((SmoothLine)line).lineSmoothStyle = smoothStyle;
        m_RefreshChart = true;
 
    }
}
 
[System.Serializable]
public class Line
{
    [SerializeField]
    protected List dataPoints = new List();
    [SerializeField] public float size = 1;
    [SerializeField] public Color lineColor = Color.black;
    public virtual void DrawLine(VertexHelper vh)
    {
    }
    public void AddPoint(Vector3 p)
    {
        dataPoints.Add(p);
    }
    public void AddPoint(List points)
    {
        dataPoints.AddRange(points);
    }
}
public class StraightLine : Line
{
    public override void DrawLine(VertexHelper vh)
    {
        for (int i = 0; i < dataPoints.Count; i++)
        {
            if (i < dataPoints.Count - 1)
            {
                UIDrawLine.DrawLine(vh, dataPoints[i], dataPoints[i + 1], size, lineColor);
            }
        }
    }
}
public class SmoothLine:Line
{
    /// 
    //曲线平滑度。值越小曲线越平滑,但顶点数也会随之增加。
    /// 
    [SerializeField] public float smoothness = 2;
    /// 
    /// 曲线平滑系数。通过调整平滑系数可以改变曲线的曲率,得到外观稍微有变化的不同曲线。
    /// 
    [SerializeField] public float lineSmoothStyle = 2;
 
 
    private List bezierPoints = new List();
    public override void DrawLine(VertexHelper vh)
    {
        Vector3 lp = Vector3.zero;
        Vector3 np = Vector3.zero;
        Vector3 llp = Vector3.zero;
        Vector3 nnp = Vector3.zero;
 
        for (int i = 0; i < dataPoints.Count; i++)
        {
            if (i < dataPoints.Count - 1)
            {
                llp = i > 1 ? dataPoints[i - 2] : lp;
                nnp = i < dataPoints.Count - 1 ? dataPoints[i + 1] : np;
                UIDrawLine.GetBezierList(ref bezierPoints, dataPoints[i], dataPoints[i + 1], llp, nnp, smoothness, lineSmoothStyle);
                for (int j = 0; j < bezierPoints.Count; j++)
                {
                    if (j < bezierPoints.Count - 1)
                    {
                        UIDrawLine.DrawLine(vh, bezierPoints[j], bezierPoints[j + 1], size, lineColor);
                    }
                }
            }
        }
    }
 
 
}
 
 

 画线的脚本

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// 
/// 画线 
/// https://github.com/monitor1394/unity-ugui-XCharts
/// 
public class UIDrawLine
{
    private static UIVertex[] vertex = new UIVertex[4];
    public static void DrawLine(VertexHelper vh, Vector3 p1, Vector3 p2, float size, Color32 color)
    {
        if (p1 == p2) return;
        Vector3 v = Vector3.Cross(p2 - p1, Vector3.forward).normalized * size;
        vertex[0].position = p1 - v;
        vertex[1].position = p2 - v;
        vertex[2].position = p2 + v;
        vertex[3].position = p1 + v;
 
        for (int j = 0; j < 4; j++)
        {
            vertex[j].color = color;
            vertex[j].uv0 = Vector2.zero;
        }
        vh.AddUIVertexQuad(vertex);
    }
 
 
 
    public static void GetBezierList(ref List posList, Vector3 sp, Vector3 ep,
           Vector3 lsp, Vector3 nep, float smoothness = 2f, float k = 2.0f)
    {
        float dist = Mathf.Abs(sp.x - ep.x);
        Vector3 cp1, cp2;
        var dir = (ep - sp).normalized;
        var diff = dist / k;
        if (lsp == sp)
        {
            cp1 = sp + dist / k * dir * 1;
            cp1.y = sp.y;
            cp1 = sp;
        }
        else
        {
            cp1 = sp + (ep - lsp).normalized * diff;
        }
        if (nep == ep) cp2 = ep;
        else cp2 = ep - (nep - sp).normalized * diff;
        dist = Vector3.Distance(sp, ep);
        int segment = (int)(dist / (smoothness <= 0 ? 2f : smoothness));
        if (segment < 1) segment = (int)(dist / 0.5f);
        if (segment < 4) segment = 4;
        GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
    }
    public static void GetBezierList2(ref List posList, Vector3 sp, Vector3 ep, int segment, Vector3 cp,
          Vector3 cp2)
    {
        posList.Clear();
        if (posList.Capacity < segment + 1)
        {
            posList.Capacity = segment + 1;
        }
        for (int i = 0; i < segment; i++)
        {
            posList.Add((GetBezier2(i / (float)segment, sp, cp, cp2, ep)));
        }
        posList.Add(ep);
    }
    public static Vector3 GetBezier2(float t, Vector3 sp, Vector3 p1, Vector3 p2, Vector3 ep)
    {
        t = Mathf.Clamp01(t);
        var oneMinusT = 1f - t;
        return oneMinusT * oneMinusT * oneMinusT * sp +
            3f * oneMinusT * oneMinusT * t * p1 +
            3f * oneMinusT * t * t * p2 +
            t * t * t * ep;
    }
}

public class TestMouse : MonoBehaviour
{
    [SerializeField] private DrawLineComponent dl;
    void Start()
    {
        dl.SetSize(2);
    }
 
    void Update()
    {
        if(Input.GetMouseButton(0))
        {
            Debug.Log(Input.mousePosition);
            dl.AddPoint(Input.mousePosition);
        }
    }
}

你可能感兴趣的:(Unity3D,unity)