unity 画线写字

news2024/9/19 11:43:33

效果

1.界面设置

2.涉及两个脚本UIDraw.cs和UIDrawLine.cs

UIDraw.cs

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

public class UIDraw : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler , IPointerDownHandler, IPointerUpHandler
{
    public Color DrawColor = Color.red;
    [Range(3,10)]
    public int DrawWidth = 3;
    public Color BgColor = new Color(0, 0, 0, 0);

    Vector2 lastPosition;
    public UIDrawLine UIDrawLine;

    List<Vector2> Vertics = new List<Vector2>();
    List<List<Vector2>> CachVertics = new List<List<Vector2>>();
    void Awake()
    {
    }
    public RectTransform Drawer;

    void Update()
    {
        if (canDraw)
        {
            Drawer.position = Input.mousePosition;
            DrawPoint(Drawer.anchoredPosition);

#if UNITY_ANDROID||UNITY_IPHONE 

#endif
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        canDraw = true;
    }
    public void OnPointerUp(PointerEventData eventData)
    {
        canDraw = false;
        //添加结尾
        lastPosition = Vector2.zero;
        AddPoint(lastPosition);
        //添加到缓存
        AddToCach();
    }
    bool canDraw;
    public void OnPointerEnter(PointerEventData eventData)
    {

    }
    public void OnPointerExit(PointerEventData eventData)  
    {
        lastPosition = Vector2.zero;
        AddPoint(lastPosition);
    }

    public void DrawPoint(Vector2 point)
    {
        if (lastPosition == Vector2.zero)
        {
            lastPosition = point;
        }

        UpdateColor(lastPosition, point, DrawWidth, DrawColor);
    }

    public void UpdateColor(Vector2 start_point, Vector2 end_point, int width, Color color)
    {
        float distance = Vector2.Distance(start_point, end_point);

        if (distance < 0.1f) return;


        AddPoint(end_point) ;

        lastPosition = end_point;

    }

    void AddPoint(Vector2 v)
    {
        Vertics.Add(v);
        UIDrawLine.Vertices.Add(v);
        UIDrawLine.SetAllDirty();
    }
    private void AddToCach()
    {
        List<Vector2> list = new List<Vector2>();
        list.AddRange(Vertics);
        CachVertics.Add(list);
        Vertics.Clear();
    }
    public void UnDo()
    {
        if (CachVertics.Count == 0) return;

        CachVertics.RemoveAt(CachVertics.Count-1);

        UIDrawLine.Vertices.Clear();

        for (int i = 0; i < CachVertics.Count; i++)
        {
            UIDrawLine.Vertices.AddRange(CachVertics[i]);
        }
        UIDrawLine.SetAllDirty();
    }
    public void Send()
    {
        //UIDrawLine.Vertices;
        Clear();
        //gameObject.SetActive(false);
    }
    internal void Clear()
    {
        UIDrawLine.Vertices.Clear();
        UIDrawLine.SetAllDirty();

        Vertics.Clear();
        CachVertics.Clear();
    }
    void OnDisable() 
    {
        Clear();
    }


}

UIDrawLine.cs

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

[AddComponentMenu("UI/Extensions/UI Line")]
public class UIDrawLine : MaskableGraphic
{
        [SerializeField]
        Texture m_Texture;

        public float thickness = 5;

        public List<Vector2> Vertices=new List<Vector2> ();

        private float size = 0;

        public override Texture mainTexture
        {
            get
            {
                return m_Texture == null ? s_WhiteTexture : m_Texture;
            }
        }
        public Texture texture
        {
            get
            {
                return m_Texture;
            }
            set
            {
                if (m_Texture == value) return;
                m_Texture = value;
                SetVerticesDirty();
                SetMaterialDirty();
            }
        }
        protected override void OnEnable()
        {
            Vertices.Clear();
        }
        void Update()
        {

        }
        protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs)
        {
            UIVertex[] vbo = new UIVertex[4];
            for (int i = 0; i < vertices.Length; i++)
            {
                var vert = UIVertex.simpleVert;
                vert.color = color;
                vert.position = vertices[i];
                vert.uv0 = uvs[i];
                vbo[i] = vert;
            }
            return vbo;
        }
        //生成方格的四个点
        protected override void OnPopulateMesh(VertexHelper vh)
        {
            vh.Clear();

            Vector2 uv0 = new Vector2(0, 1);
            Vector2 uv1 = new Vector2(1, 1);
            Vector2 uv2 = new Vector2(1, 0);
            Vector2 uv3 = new Vector2(0, 0);

            Vector2 lastPos0 = Vector2.zero;
            Vector2 lastPos1 = Vector2.zero;
            Vector2 lastPos2 = Vector2.zero;
            Vector2 lastPos3 = Vector2.zero;

        for (int i = 1; i < Vertices.Count; i++)
        {
            //当有0是说明是结束点,开始下个画线
            if (Vertices[i - 1]==Vector2.zero || Vertices[i]== Vector2.zero)
            {
                lastPos0 = Vector2.zero;
                continue;
            }
  
            Vector2 v = Rotate90(Vertices[i] - Vertices[i - 1]).normalized;

            Vector2 pos0 = Vertices[i - 1]- v * thickness * 0.5f;
            Vector2 pos1 = Vertices[i]- v * thickness * 0.5f;

            Vector2 pos2 = pos1 + v * thickness;
            Vector2 pos3 = pos0 + v * thickness;

            vh.AddUIVertexQuad(SetVbo(new[] { pos0, pos1, pos2, pos3 }, new[] { uv0, uv1, uv2, uv3 }));

            //角
            if (lastPos0!=Vector2.zero)
            {
                Vector2 p0 = pos0;
                Vector2 p1 = lastPos1;
                Vector2 p2 = pos3;
                Vector2 p3 = lastPos2;
                vh.AddUIVertexQuad(SetVbo(new[] { p0, p1, p2, p3 }, new[] { uv0, uv1, uv2, uv3 }));
            }

            lastPos0 = pos0;
            lastPos1 = pos1;
            lastPos2 = pos2;
            lastPos3 = pos3;
        }
    }
    private Vector2 Rotate90(Vector2 p)
    {
        return new Vector2(p.y, -p.x);
    }

}

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

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

相关文章

【大数据】什么是数据架构?

目录 一、什么是数据架构&#xff1f; 二、数据架构的发展历程 1. 早期阶段&#xff08;1960年代-1970年代&#xff09; 2. 关系数据库的兴起&#xff08;1970年代-1980年代&#xff09; 3. 数据仓库和数据挖掘&#xff08;1980年代-1990年代&#xff09; 4. 大数据和NoSQL&…

计算机基础|数据溢出

一、概念 在类似C这样的非高级语言存在数值溢出问题&#xff0c;简单概括&#xff1a;高位数据丢失被低位数据占据位置。 二、举例 2.1 以C语言 for循环为例 /*int8_t value range from -128 to 127*/int8_t input;for (input 124; input < 130; input) {printf("%…

《Unity3D网络游戏实战》深入了解TCP

从TCP到铜线 应用层 应用层功能是应用程序&#xff08;游戏程序&#xff09;提供的功能。在给客户端发送“hello”的例子中&#xff0c;程序把“hello”转化成二进制流传递给传输层&#xff08;传送给send方&#xff09;​。操作系统会对二进制数据做一系列加工&#xff0c;使…

嵌入式八股文-网络编程、多线程和进程

网络编程 1. TCP头部结构 TCP固定头部结构 每个TCP报文段都包含着此报文段的TCP头部信息,用于指定源端端口、目的端端口以及管理TCP连接等。完整的TCP头部结构可分为固定头部结构和头部选项两个部分。 32位端口号:包括了16位源端口号和16位目的端口号。32位序号:假设第一次…

Linux驱动开发基础(Hello驱动)

所学内容来自百问网 目录 1. 文件在内核中的表示 2. 打开字符设备节点时&#xff0c;内核中也有对应的struct file 3. 编写驱动程序步骤 4. 相关知识点 4.1 涉及函数解析 4.2 module_init/module_exit的实现 4.3 register_chrdev的内部实现 4.4 class_destroy/device_…

(Jmeter、Fiddler)脚本转换Loadrunner脚本

背景:公司政治任务、各种体系文档要留档,但有些不在体系内的工具生成的脚本需要转化到体系内以备留档。 一、Loadrunner代理设置 开始录制配置: Record->Remote Application via LoadRunner Proxy LoadRrunner Proxy listens on port-> 8889 (系统建立出入站规则…

解析防蠕动交叉导轨的防蠕动机制

随着工业自动化的不断发展&#xff0c;对机械导轨系统的精度和稳定性要求越来越高。防蠕动交叉导轨作为一种新型导轨系统&#xff0c;能够有效提高设备的运行精度和稳定性&#xff0c;降低维护成本。 蠕动现象通常发生在导轨负载超出其额定范围、表面粗糙度不足或润滑不良等情况…

Python 实现 Excel 文件操作的技术性详解

目录 一、引言 二、Excel 文件格式及库的选择 2.1 Excel 文件格式 2.2 库的选择 三、安装必要的库 四、使用 openpyxl 读取 Excel 文件 4.1 基本步骤 4.2 实战案例 五、使用 pandas 读取 Excel 文件 5.1 基本步骤 5.2 实战案例 六、写入 Excel 文件 6.1 使用 …

【每日刷题】Day100

【每日刷题】Day100 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 【模板】堆_牛客题霸_牛客网 (nowcoder.com) 2. 【模板】链表_牛客题霸_牛客网 (nowcoder.com) 3…

Linux系统移植——开发板烧写

目录&#xff1a; 目录&#xff1a; 一、什么是EMMC分区&#xff1f; 1.1 eMMC分区 1.2 分区的管理 二、相关命令介绍&#xff1a; 2.1 mmc 2.1.1 主要功能 2.1.2 示例用法 2.2 fdisk 2.2.1 基本功能 2.2.2 交互模式常用命令 2.2.3 注意事项 三、U-BOOT烧写 3.1 mmc命令 3.2 f…

24小时监控识别潜在的非安全生产隐患的明厨亮灶开源了。

明厨亮灶视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。AI技术可以24小时…

【JS】旋涡数组

前言 实现如下图的旋涡数组&#xff0c;简单理解为遇到拐点自动拐弯&#xff0c;否则一直沿当前方向推进。 封装一个函数接收两个参数分别为行数以及列数&#xff0c;实现该旋涡数组。 思路 二维数组&#xff0c;初始填充0分别记录水平和垂直方向的坐标&#xff0c;并根据步…

学习记录702@计算机组成原理之计算机硬件组成细化

运算器 ACC是累加器ALU是逻辑和算数运算单元MQ是乘商寄存器 X是操作数寄存器各部分存储的值 控制器 PC是程序计数器&#xff0c;用来存放下一条应该执行程序的地址&#xff0c;与MAR地址寄存器相连&#xff0c;找到下一个要执行的程序的地址。IR指令寄存器&#xff0c;用来…

怎么利用XML发送视频彩信

传统的短信推广主要以文字为主&#xff0c;用户接收到的信息往往显得单调乏味。而视频彩信则不同&#xff0c;它结合了视频和音频的优势&#xff0c;通过生动的画面和悦耳的音乐&#xff0c;给用户带来强烈的视听冲击&#xff0c;从而极大地提高了用户的吸引力。 XML成功返回示…

某通电子文档安全管理系统 CDGAuthoriseTempletService1接口SQL注入漏洞复现 [附POC]

文章目录 某通电子文档安全管理系统 CDGAuthoriseTempletService1接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现0x06 修复建议某通电子文档安全管理系统 CDGAuthoriseTempletService1接口SQL注入漏…

聚鼎科技:现在开一家装饰画店铺究竟受欢迎吗

在这个时代&#xff0c;装饰画不仅仅是墙上的一抹色彩&#xff0c;它已经成为人们情感寄托、审美追求的象征。那么&#xff0c;现在开一家装饰画店铺究竟受欢迎吗? “家&#xff0c;是一幅画。”这句话道出了现代人对于家的期待与向往。在这个快节奏的时代&#xff0c;人们渴望…

8.13 哈希表中等 128 Longest Consecutive Sequence 138 Copy List with Random Pointer

128 Longest Consecutive Sequence class Solution { public:int longestConsecutive(vector<int>& nums) {//无序array整数数组&#xff0c;返回最长的连续的序列长度&#xff0c;首先这些数不按顺序//时间复杂度O(n)//使用哈希表&#xff0c;先存后遍历---->no …

web页面的性能测试

背景 测试大模型主要web页面的性能 使用工具 通过google自带的lighthouse测试页面的性能 各个参考指标 First Contentful Paint(FCP):测量在用户导航到页面后浏览器呈现第一段 DOM 内容所花费的时间。页面上的图像、非白色<canvas>元素和 SVG 被视为 DOM 内容&#…

C++STL之string类:基本使用及模拟实现

目录 一&#xff0c;前言 为什么要学习string类 C语言中的字符串 C中的字符串 STL(Standard Template Library) 里面的 string 类 二&#xff0c;string类的基本使用 文档的阅读 常见接口的基本使用 1&#xff0c;构造函数(constructor) 2&#xff0c;拷贝构造(copy …

程序员喜欢的7个免费公共API

本文将介绍七个程序员们喜爱的免费公共API&#xff0c;它们覆盖了从天气信息、翻译到数据分析、游戏等多个领域。这些API不仅易于使用&#xff0c;而且功能全面&#xff0c;能够帮助开发者快速实现项目需求&#xff0c;无论是个人学习、小项目开发还是商业应用&#xff0c;都能…