Unity 画线OnPopulateMesh函数VertexHelper

news2024/12/25 10:53:26

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

底层使用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<Vector3> 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<Vector3> dataPoints = new List<Vector3>();
    [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<Vector3> 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
{
    /// <summary>
    //曲线平滑度。值越小曲线越平滑,但顶点数也会随之增加。
    /// </summary>
    [SerializeField] public float smoothness = 2;
    /// <summary>
    /// 曲线平滑系数。通过调整平滑系数可以改变曲线的曲率,得到外观稍微有变化的不同曲线。
    /// </summary>
    [SerializeField] public float lineSmoothStyle = 2;
 
 
    private List<Vector3> bezierPoints = new List<Vector3>();
    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;
/// <summary>
/// 画线 
/// https://github.com/monitor1394/unity-ugui-XCharts
/// </summary>
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<Vector3> 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<Vector3> 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);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/825921.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elisp之buffer-substring-no-properties用法(二十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

冲突域 和 广播域

冲突域&#xff1a; 在传统的以粗同轴电缆为传输介质的以太网中&#xff0c;同一介质上的多个节点共享链路的带宽&#xff0c;争用链路的使用权&#xff0c;这样就会发生冲突&#xff0c;CSMA/CD机制中当冲突发生时&#xff0c;网络就要进行回退&#xff0c;这段回退的时间内链…

SpringBoot复习:(15)Spring容器的核心方法refresh是在哪里被调用的?

在SpringApplication的run方法&#xff1a; refreshContext代码如下&#xff1a; 其中调用的refresh方法代码如下&#xff1a; 其中调用的refresh方法代码如下&#xff1a; 其中调用的fresh方法代码如下&#xff1a; 其中调用了super.refresh();而这个super.refresh()就是…

AP5179 高端电流采样降压恒流驱动IC SOP8 LED车灯电源驱动

产品描述 AP5179是一款连续电感电流导通模式的降压恒流源&#xff0c;用于驱动一颗或多颗串联LED输入电压范围从 5 V 到 60V&#xff0c;输出电流 最大可达 2.0A 。根据不同的输入电压和外部器件&#xff0c; 可以驱动高达数十瓦的 LED。内置功率开关&#xff0c;采用高端电流…

AI赋能下的“数字人”与“数智人”:异同解析

由于人工智能技术的快速发展&#xff0c;我们逐渐进入了一个数字化的时代。在这个时代中&#xff0c;两个概念引起了广泛的关注和讨论&#xff0c;那就是“数字人”和“数智人”。虽然这两个概念都与人工智能有关&#xff0c;但它们在含义和应用上存在一些不同之处。在本文中&a…

使用elementplus实现文本框的粘贴复制

需求&#xff1a; 文本框仅用于显示展示数据并且用户可以进行复制&#xff0c;并不会进行修改和编辑&#xff0c; 注意点&#xff1a; 1.首先且文本为多行。所以不能使用普通的el-input&#xff0c;这种一行超出就会隐藏了&#xff0c;如果多行超出行数也会隐藏&#xff08;…

《评论文章-无线纳米技术可以降低脊髓刺激成本和并发症,传统设备与无线刺激设备费用相比的回顾》

SCS治疗可能会出现并发症&#xff0c;并且管理这些并发症的费用很高。 慢性疼痛是促使人们寻求缓解的主要因素&#xff0c;也是阿片类药物研究的主要方向。 SCS治疗取得了突破性进展&#xff0c;在治疗背部手术失败综合征、神经性疼痛障碍、复杂区域疼痛综合征以及血管缺血引…

51单片机学习--蜂鸣器播放音乐

由原理图可知&#xff0c;蜂鸣器BEEP与P1_5 相关&#xff0c;但其实这个原理图有错&#xff0c;实测接的是P2_5 下面这个代码就是以500HZ的频率响500ms的例子 sbit Buzzer P2^5;unsigned char KeyNum; unsigned int i;void main() {while(1){KeyNum Key();if(KeyNum){for(i …

后端进阶之路——综述Spring Security认证,授权(一)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ 解决算法&#xff0c;一个专栏就够了★ ★ 架…

人脸检测之给照片加上眼镜

人脸检测 文章目录 人脸检测一、背景二、UV空间融合法三、总结与不足四、参考 一、背景 给人脸图像加眼镜在很多领域都有应用。比如修图换造型、眼镜店眼镜试戴、戴眼镜人脸识别等。 给人脸加眼镜的难点在于难以做到自然逼真&#xff0c;且人脸多种多样&#xff0c;角度多变&a…

HCIP——BGP综合实验

BGP综合实验 一、实验拓扑二、实验要求三、实验步骤1、配置接口IP地址与环回地址2、AS2配置OSPF3、配置BGP&#xff0c;建立对等体4、发布路由5、配置路由反射器6、做空接口、汇总以及宣告7、建立GRE隧道8、查看BGP路由表9、测试 一、实验拓扑 二、实验要求 1&#xff0c;AS1存…

关于ETL的两种架构(ETL架构和ELT架构) qt

&#xfeff;ETL&#xff0c;是英文 Extract-Transform-Load 的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transform&#xff09;、加载&#xff08;load&#xff09;至目的端的过程。ETL一词较常用在数据仓库&#xf…

Tomcat8安装并启动服务教程

目录 一、安装JDK 1.检查Linux版本信息 2.官网下载jdk 3.将下载的压缩包上传到Linux主机上 4.安装jdk到指定目录 5.配置环境变量 6.检测 二、安装tomcat 1.官网下载tomcat的安装包 2.将下载的包上传到自己的Linux主机上 3.安装tomcat到指定目录 4.为了方便&#xf…

uni-app 微信小程序自定义导航栏

一、效果图 二、导航栏的组成 上面的导航栏主要由状态栏&#xff08;就是手机电量显示栏&#xff09;和小程序的导航栏组成&#xff0c;android手机一般为48px&#xff0c;ios手机一般为44px 三、开发步骤 1、设置navigationStyle:custom {"path": "pages/v…

P2498 [SDOI2012] 拯救小云公主

题目 思路 伊艳二分 这个题比较难的地方就是如何判断在当前r的情况下能否到达终点 我们可以用并查集来判断两个点是否连接&#xff0c;再加两个点&#xff1a;0和n1 代码 #include<bits/stdc.h> using namespace std; #define _p(x) ((x)*(x)) const int maxn3005; co…

三言两语说透koa的洋葱模型

Koa是一个非常轻量化的Node.js web应用框架,其洋葱圈模型是它独特的设计理念和核心实现机制之一。本文将详细介绍Koa的洋葱圈模型背后的设计思想,以及它是如何实现的。 洋葱圈模型设计思想 Koa的洋葱圈模型主要是受函数式编程中的compose思想启发而来的。Compose函数可以将需…

MybatisPlus存在 sql 注入漏洞(CVE-2023-25330)解决办法

首先我们了解下这个漏洞是什么&#xff1f; MyBatis-Plus TenantPlugin 是 MyBatis-Plus 的一个为多租户场景而设计的插件&#xff0c;可以在 SQL 中自动添加租户 ID 来实现数据隔离功能。 MyBatis-Plus TenantPlugin 3.5.3.1及之前版本由于 TenantHandler#getTenantId 方法在…

openEuler22.03安装 filebeat启动失败

报错详情 runtime/cgo: pthread_create failed: Operation not permitted runtime/cgo: pthread_create failed: Operation not permitted SIGABRT: abort PC=0x7faeea51af1f m=8 sigcode=18446744073709551610goroutine 0 [idle]: runtime: unknown pc 0x7faeea51af1f stack:…

pycharm出现python test运行报错(pytest模式)

pycharm出现python test运行报错 一、python test 执行代码报错二、删除运行配置三、修改pycharm默认配置为 unittests四、成功&#xff01; 一、python test 执行代码报错 二、删除运行配置 三、修改pycharm默认配置为 unittests 四、成功&#xff01;

【EI/SCOPUS会议征稿】第三届电气工程与计算机技术国际学术会议(ICEECT 2023)

第三届电气工程与计算机技术国际学术会议 2023 3rd International Conference on Electrical Engineering and Computer Technology 往届均已完成EI、SCOPUS检索 继ICEECT2021、ICEECT2022顺利举办&#xff0c;往届所录用论文均已完成出版及EI核心检索。第三届电气工程与计算…