当前位置: 首页 > article >正文

Unity开发绘画板——04.笔刷大小调节

笔刷大小调节

上面的代码中其实我们已经提供了笔刷大小的字段,即brushSize,现在只需要将该字段和界面中的Slider绑定即可,Slider值的范围我们设置为1~20

代码中只需要做如下改动:

public Slider brushSizeSlider; //控制笔刷大小的滑动条
public float brushSize => brushSizeSlider.value;    //笔刷大小取滑动条的值

完整代码如下:

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

public class Painter : MonoBehaviour
{
    public RenderTexture renderTexture;
    public Slider brushSizeSlider;
    public Texture2D brushTexture; //笔刷纹理
    public float brushSize => brushSizeSlider.value;    //笔刷大小
    
    public float resolutionMultiplier = 5;  //线性插值密度调节
    
    
    private Vector2 previousMousePos; //记录上一帧鼠标的位置  
    
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            previousMousePos = Input.mousePosition;
        }
        
        if (Input.GetMouseButton(0))
        {
            var mousePosition = Input.mousePosition;
            DrawLine(previousMousePos, mousePosition);
            previousMousePos = mousePosition;
        }
    }

    private void DrawLine(Vector2 start, Vector2 end)
    {
        float distance = Vector2.Distance(start, end);
        int steps = Mathf.CeilToInt(distance * resolutionMultiplier);
        for (int i = 0; i <= steps; i++)
        {
            float t = i / (float)steps;
            int x = Mathf.FloorToInt(Mathf.Lerp(start.x, end.x, t));
            int y = Mathf.FloorToInt(Mathf.Lerp(start.y, end.y, t));
            DrawBrush(x, y);
        }
    }

    private void DrawBrush(int x, int y)
    {
        Rect brushRect = new Rect(x, y, brushSize, brushSize);
        Graphics.SetRenderTarget(renderTexture);
        GL.PushMatrix();
        GL.LoadPixelMatrix(0, renderTexture.width, 0, renderTexture.height);
        Graphics.DrawTexture(brushRect, brushTexture);
        GL.PopMatrix();
        Graphics.SetRenderTarget(null);
    }

    
}

效果优化 

运行效果如下图,可见虽然笔刷粗细已可以调节,但是在调节过程中,滑动的同时滑动条周围有绘制的线条,这本不该出现的,出现的原因是因为我们监听了鼠标按下的事件来绘制,这导致在操作滑动条的时候,绘制依然在进行。

操作UI时屏蔽绘制

我们需要检测当前的鼠标是否在UI元素上,如果在,则不进行绘制,这可以使用EventSystem的射线检测来实现,如下我们定义一个函数,当光标在UI元素上的时候返回true,否则返回false:

private bool IsPointerOverUIElement()
{
    PointerEventData eventData = new PointerEventData(EventSystem.current);
    eventData.position = Input.mousePosition;
    List<RaycastResult> results = new List<RaycastResult>();
    EventSystem.current.RaycastAll(eventData, results);
    return results.Count > 0;
}

我们在鼠标左键点击的时候判断是否在UI元素上,如果在则禁止绘制;

但有个问题,我们用来绘制的RawImage也是UI元素,它铺满整个屏幕,这会导致我们始终没办法绘制,我们可以将其Raycast Target关掉,这样再操作UI元素的时候就不会进行多余的绘制了

完整代码如下:

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

public class Painter : MonoBehaviour
{
    public RenderTexture renderTexture;
    public Slider brushSizeSlider; //控制笔刷大小的滑动条
    public Texture2D brushTexture; //笔刷纹理
    public float brushSize => brushSizeSlider.value;    //笔刷大小取滑动条的值
    
    public float resolutionMultiplier = 5;  //线性插值密度调节
    
    
    private Vector2 previousMousePos; //记录上一帧鼠标的位置  
    private bool startFromUIElement = false; //点击是否是从UI元素上开始的
    void Update()
    {
        //判断光标是否在UI元素上
        if (Input.GetMouseButtonDown(0))
        {
            if (IsPointerOverUIElement())
            {
                startFromUIElement = true;
            }
            previousMousePos = Input.mousePosition;
        }
        
        if (Input.GetMouseButton(0) && !startFromUIElement)
        {
            var mousePosition = Input.mousePosition;
            DrawLine(previousMousePos, mousePosition);
            previousMousePos = mousePosition;
        }

        if (Input.GetMouseButtonUp(0))
        {
            startFromUIElement = false;
        }
    }

    private void DrawLine(Vector2 start, Vector2 end)
    {
        float distance = Vector2.Distance(start, end);
        int steps = Mathf.CeilToInt(distance * resolutionMultiplier);
        for (int i = 0; i <= steps; i++)
        {
            float t = i / (float)steps;
            int x = Mathf.FloorToInt(Mathf.Lerp(start.x, end.x, t));
            int y = Mathf.FloorToInt(Mathf.Lerp(start.y, end.y, t));
            DrawBrush(x, y);
        }
    }

    private void DrawBrush(int x, int y)
    {
        Rect brushRect = new Rect(x, y, brushSize, brushSize);
        Graphics.SetRenderTarget(renderTexture);
        GL.PushMatrix();
        GL.LoadPixelMatrix(0, renderTexture.width, 0, renderTexture.height);
        Graphics.DrawTexture(brushRect, brushTexture);
        GL.PopMatrix();
        Graphics.SetRenderTarget(null);
    }

    private bool IsPointerOverUIElement()
    {
        PointerEventData eventData = new PointerEventData(EventSystem.current);
        eventData.position = Input.mousePosition;
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, results);
        return results.Count > 0;
    }
    
}

在下一节我将为大家介绍如何调节线条的颜色~


http://www.kler.cn/news/326365.html

相关文章:

  • 智能AI对话绘画二合一网站源码系统 带完整的安装代码包以及搭建部署教程
  • XPath入门
  • 65.【C语言】联合体
  • Python | Leetcode Python题解之第442题数组中重复的数据
  • plt注解相关介绍及应用
  • 封装提示词翻译组件
  • K8S:开源容器编排平台,助力高效稳定的容器化应用管理
  • 开放词汇目标检测
  • Unity实战案例全解析:RTS游戏的框选和阵型功能(4)阵型功能
  • 【单元测试】任务1:白盒测试1
  • 完成UI界面的绘制
  • DRF实操学习——购物车及订单生成
  • 【Redis 源码】1下载与源码编译
  • 使用CAPTCHA对反爬虫有优势吗
  • java 解析excel (网络资源)
  • Matlab|计及需求响应消纳风电的电热综合能源系统经济调度
  • 防火墙的区域划分+来自公网、内网的ip欺骗攻击+防御
  • 24.9.25学习笔记
  • 语音识别控制(软件、硬件)
  • 【Pytorch图像+序列双输入网络源代码】
  • mac 触控板 三指拖动
  • 【软件工程】模块化思想概述
  • 线性模型到神经网络
  • PyCharm开发工具的安装和基础使用
  • JVM(HotSpot):字符串常量池(StringTable)
  • DK5V100R20ST1直插TO220F功率12V 3A同步整流芯片
  • 解决目标主机showmount -e信息泄露(CVE-1999-0554)
  • 开创远程就可以监测宠物健康新篇章
  • C++ | Leetcode C++题解之第432题全O(1)的数据结构
  • Centos 8安装VNC及多用户配置详细教程