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;
    }
    
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值