|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
[RequireComponent(typeof(RawImage))]
|
|
public class EraseHandler : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
|
|
{
|
|
//擦除完成调用事件
|
|
public Action eraseFinishEvent;
|
|
|
|
//笔刷半径
|
|
int brushRadius = 50;
|
|
|
|
//擦除比例,擦除比例高于该值,是为擦除完成,自动擦除剩余部分
|
|
float finishPercent = 0.8f;
|
|
|
|
//擦除点偏移量,距离上个擦除点>=该值时开始新的擦除点
|
|
float drawOffset = 10f;
|
|
|
|
//是否以擦除完成
|
|
bool isFinish;
|
|
|
|
//是否需要重置颜色透明度
|
|
bool needInitColorAlp = false;
|
|
|
|
//要擦除的图片
|
|
RawImage eraseImage;
|
|
Texture2D eraseTexture;
|
|
//图片长宽
|
|
int textureWidth;
|
|
int textureHeight;
|
|
|
|
//图片大小
|
|
float textureLength;
|
|
//擦除部分图片大小
|
|
float eraseLength;
|
|
|
|
public Camera mainCamera = null;
|
|
|
|
void Awake()
|
|
{
|
|
eraseImage = GetComponent<RawImage>();
|
|
}
|
|
|
|
void Init()
|
|
{
|
|
isFinish = false;
|
|
eraseLength = 0;
|
|
|
|
eraseImage.enabled = true;
|
|
|
|
//原擦除图片
|
|
//Texture2D originalTexture = (Texture2D)eraseImage.mainTexture;
|
|
|
|
if (needInitColorAlp)
|
|
{
|
|
InitColor();
|
|
return;
|
|
}
|
|
Texture2D originalTexture = (Texture2D)eraseImage.texture;
|
|
|
|
//被擦除的图片,展示擦除过程
|
|
eraseTexture = new Texture2D(originalTexture.width, originalTexture.height, TextureFormat.ARGB32, false);
|
|
textureWidth = eraseTexture.width;
|
|
textureHeight = eraseTexture.height;
|
|
eraseTexture.SetPixels(originalTexture.GetPixels());
|
|
eraseTexture.Apply();
|
|
Debug.Log(textureWidth + " - " + textureHeight);
|
|
eraseImage.texture = eraseTexture;
|
|
textureLength = eraseTexture.GetPixels().Length;
|
|
needInitColorAlp = true;
|
|
}
|
|
|
|
#region Pointer Event
|
|
|
|
public void OnPointerDown(PointerEventData eventData)
|
|
{
|
|
if (isFinish)
|
|
return;
|
|
|
|
tempLastPoint = eventData.position;
|
|
ErasePoint(eventData.position);
|
|
}
|
|
|
|
Vector2 tempEventPoint;
|
|
Vector2 tempLastPoint;
|
|
public void OnDrag(PointerEventData eventData)
|
|
{
|
|
if (isFinish)
|
|
return;
|
|
|
|
tempEventPoint = eventData.position;
|
|
|
|
//距离上个擦除点 >= 该值时开始新的擦除点
|
|
if ((tempEventPoint - tempLastPoint).sqrMagnitude < drawOffset * drawOffset)
|
|
return;
|
|
|
|
//擦除点
|
|
ErasePoint(tempEventPoint);
|
|
//记录点
|
|
tempLastPoint = tempEventPoint;
|
|
}
|
|
|
|
public void OnPointerUp(PointerEventData eventData)
|
|
{
|
|
|
|
if (isFinish)
|
|
return;
|
|
|
|
ErasePoint(eventData.position);
|
|
}
|
|
|
|
#endregion
|
|
|
|
Vector3 tempWorldPoint;
|
|
Vector3 tempLocalPoint;
|
|
Vector2Int pixelPos;
|
|
void ErasePoint(Vector2 screenPos)
|
|
{
|
|
if (!mainCamera) return;
|
|
//点击位置坐标转换,正交相机无效,试着改成平行相机试一下
|
|
tempWorldPoint = mainCamera.ScreenToWorldPoint(screenPos);
|
|
tempLocalPoint = transform.InverseTransformPoint(tempWorldPoint);
|
|
|
|
//相对图片像素点坐标
|
|
pixelPos.x = (int)tempLocalPoint.x + textureWidth / 2;
|
|
pixelPos.y = (int)tempLocalPoint.y + textureHeight / 2;
|
|
|
|
//点击位置是否在图片范围内
|
|
if (pixelPos.x < 0 || pixelPos.x >= textureWidth || pixelPos.y < 0 || pixelPos.y >= textureHeight)
|
|
return;
|
|
// Debug.Log("OnPointerUp" + " - " + 222);
|
|
//遍历笔刷长宽范围内像素点
|
|
for (int i = -brushRadius; i <= brushRadius; i++)
|
|
{
|
|
//超左/右边界
|
|
if (pixelPos.x + i < 0 || pixelPos.x + i >= textureWidth)
|
|
continue;
|
|
|
|
for (int j = -brushRadius; j <= brushRadius; j++)
|
|
{
|
|
//超上/下边界
|
|
if (pixelPos.y + j < 0 || pixelPos.y + j >= textureHeight)
|
|
continue;
|
|
|
|
//是否在圆形范围内
|
|
if (Mathf.Pow(i, 2) + Mathf.Pow(j, 2) > Mathf.Pow(brushRadius, 2))
|
|
continue;
|
|
|
|
//像素点色值
|
|
Color color = eraseTexture.GetPixel(pixelPos.x + i, pixelPos.y + j);
|
|
|
|
//判断透明度,是否已擦除
|
|
if (Mathf.Approximately(color.a, 0))
|
|
continue;
|
|
|
|
//Debug.Log("OnPointerUp" + " - " + 111);
|
|
//修改像素点透明度
|
|
color.a = 0;
|
|
eraseTexture.SetPixel(pixelPos.x + i, pixelPos.y + j, color);
|
|
|
|
//擦除数量统计
|
|
eraseLength++;
|
|
}
|
|
}
|
|
eraseTexture.Apply();
|
|
|
|
//判断擦除进度
|
|
RefreshErasePercent();
|
|
}
|
|
|
|
float tempPercent;
|
|
void RefreshErasePercent()
|
|
{
|
|
if (isFinish)
|
|
return;
|
|
|
|
tempPercent = eraseLength / textureLength;
|
|
tempPercent = (float)Math.Round(tempPercent, 2);
|
|
if (tempPercent >= finishPercent)
|
|
{
|
|
isFinish = true;
|
|
eraseImage.enabled = false;
|
|
|
|
//触发结束事件
|
|
if (eraseFinishEvent != null)
|
|
eraseFinishEvent.Invoke();
|
|
}
|
|
}
|
|
|
|
public void SetFinishPercent(float percent)
|
|
{
|
|
finishPercent = percent;
|
|
}
|
|
|
|
public void SetCamera(Camera cam)
|
|
{
|
|
mainCamera = cam;
|
|
}
|
|
public void SetFinishCallBack(Action call_back)
|
|
{
|
|
eraseFinishEvent = call_back;
|
|
}
|
|
public void Reset()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
public void SetEraseArgs(int radius, float draw_offset)
|
|
{
|
|
brushRadius = radius;
|
|
drawOffset = draw_offset;
|
|
}
|
|
|
|
void InitColor()
|
|
{
|
|
for (int i = 1; i <= textureWidth; i++)
|
|
{
|
|
for (int j = 1; j <= textureHeight; j++)
|
|
{
|
|
Color color = eraseTexture.GetPixel(i, j);
|
|
color.a = 1;
|
|
eraseTexture.SetPixel(i, j, color);
|
|
}
|
|
}
|
|
eraseTexture.Apply();
|
|
}
|
|
}
|