源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.1 KiB

  1. 
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.EventSystems;
  7. using UnityEngine.UI;
  8. [RequireComponent(typeof(RawImage))]
  9. public class EraseHandler : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
  10. {
  11. //擦除完成调用事件
  12. public Action eraseFinishEvent;
  13. //笔刷半径
  14. int brushRadius = 50;
  15. //擦除比例,擦除比例高于该值,是为擦除完成,自动擦除剩余部分
  16. float finishPercent = 0.8f;
  17. //擦除点偏移量,距离上个擦除点>=该值时开始新的擦除点
  18. float drawOffset = 10f;
  19. //是否以擦除完成
  20. bool isFinish;
  21. //是否需要重置颜色透明度
  22. bool needInitColorAlp = false;
  23. //要擦除的图片
  24. RawImage eraseImage;
  25. Texture2D eraseTexture;
  26. //图片长宽
  27. int textureWidth;
  28. int textureHeight;
  29. //图片大小
  30. float textureLength;
  31. //擦除部分图片大小
  32. float eraseLength;
  33. public Camera mainCamera = null;
  34. void Awake()
  35. {
  36. eraseImage = GetComponent<RawImage>();
  37. }
  38. void Init()
  39. {
  40. isFinish = false;
  41. eraseLength = 0;
  42. eraseImage.enabled = true;
  43. //原擦除图片
  44. //Texture2D originalTexture = (Texture2D)eraseImage.mainTexture;
  45. if (needInitColorAlp)
  46. {
  47. InitColor();
  48. return;
  49. }
  50. Texture2D originalTexture = (Texture2D)eraseImage.texture;
  51. //被擦除的图片,展示擦除过程
  52. eraseTexture = new Texture2D(originalTexture.width, originalTexture.height, TextureFormat.ARGB32, false);
  53. textureWidth = eraseTexture.width;
  54. textureHeight = eraseTexture.height;
  55. eraseTexture.SetPixels(originalTexture.GetPixels());
  56. eraseTexture.Apply();
  57. Debug.Log(textureWidth + " - " + textureHeight);
  58. eraseImage.texture = eraseTexture;
  59. textureLength = eraseTexture.GetPixels().Length;
  60. needInitColorAlp = true;
  61. }
  62. #region Pointer Event
  63. public void OnPointerDown(PointerEventData eventData)
  64. {
  65. if (isFinish)
  66. return;
  67. tempLastPoint = eventData.position;
  68. ErasePoint(eventData.position);
  69. }
  70. Vector2 tempEventPoint;
  71. Vector2 tempLastPoint;
  72. public void OnDrag(PointerEventData eventData)
  73. {
  74. if (isFinish)
  75. return;
  76. tempEventPoint = eventData.position;
  77. //距离上个擦除点 >= 该值时开始新的擦除点
  78. if ((tempEventPoint - tempLastPoint).sqrMagnitude < drawOffset * drawOffset)
  79. return;
  80. //擦除点
  81. ErasePoint(tempEventPoint);
  82. //记录点
  83. tempLastPoint = tempEventPoint;
  84. }
  85. public void OnPointerUp(PointerEventData eventData)
  86. {
  87. if (isFinish)
  88. return;
  89. ErasePoint(eventData.position);
  90. }
  91. #endregion
  92. Vector3 tempWorldPoint;
  93. Vector3 tempLocalPoint;
  94. Vector2Int pixelPos;
  95. void ErasePoint(Vector2 screenPos)
  96. {
  97. if (!mainCamera) return;
  98. //点击位置坐标转换,正交相机无效,试着改成平行相机试一下
  99. tempWorldPoint = mainCamera.ScreenToWorldPoint(screenPos);
  100. tempLocalPoint = transform.InverseTransformPoint(tempWorldPoint);
  101. //相对图片像素点坐标
  102. pixelPos.x = (int)tempLocalPoint.x + textureWidth / 2;
  103. pixelPos.y = (int)tempLocalPoint.y + textureHeight / 2;
  104. //点击位置是否在图片范围内
  105. if (pixelPos.x < 0 || pixelPos.x >= textureWidth || pixelPos.y < 0 || pixelPos.y >= textureHeight)
  106. return;
  107. // Debug.Log("OnPointerUp" + " - " + 222);
  108. //遍历笔刷长宽范围内像素点
  109. for (int i = -brushRadius; i <= brushRadius; i++)
  110. {
  111. //超左/右边界
  112. if (pixelPos.x + i < 0 || pixelPos.x + i >= textureWidth)
  113. continue;
  114. for (int j = -brushRadius; j <= brushRadius; j++)
  115. {
  116. //超上/下边界
  117. if (pixelPos.y + j < 0 || pixelPos.y + j >= textureHeight)
  118. continue;
  119. //是否在圆形范围内
  120. if (Mathf.Pow(i, 2) + Mathf.Pow(j, 2) > Mathf.Pow(brushRadius, 2))
  121. continue;
  122. //像素点色值
  123. Color color = eraseTexture.GetPixel(pixelPos.x + i, pixelPos.y + j);
  124. //判断透明度,是否已擦除
  125. if (Mathf.Approximately(color.a, 0))
  126. continue;
  127. //Debug.Log("OnPointerUp" + " - " + 111);
  128. //修改像素点透明度
  129. color.a = 0;
  130. eraseTexture.SetPixel(pixelPos.x + i, pixelPos.y + j, color);
  131. //擦除数量统计
  132. eraseLength++;
  133. }
  134. }
  135. eraseTexture.Apply();
  136. //判断擦除进度
  137. RefreshErasePercent();
  138. }
  139. float tempPercent;
  140. void RefreshErasePercent()
  141. {
  142. if (isFinish)
  143. return;
  144. tempPercent = eraseLength / textureLength;
  145. tempPercent = (float)Math.Round(tempPercent, 2);
  146. if (tempPercent >= finishPercent)
  147. {
  148. isFinish = true;
  149. eraseImage.enabled = false;
  150. //触发结束事件
  151. if (eraseFinishEvent != null)
  152. eraseFinishEvent.Invoke();
  153. }
  154. }
  155. public void SetFinishPercent(float percent)
  156. {
  157. finishPercent = percent;
  158. }
  159. public void SetCamera(Camera cam)
  160. {
  161. mainCamera = cam;
  162. }
  163. public void SetFinishCallBack(Action call_back)
  164. {
  165. eraseFinishEvent = call_back;
  166. }
  167. public void Reset()
  168. {
  169. Init();
  170. }
  171. public void SetEraseArgs(int radius, float draw_offset)
  172. {
  173. brushRadius = radius;
  174. drawOffset = draw_offset;
  175. }
  176. void InitColor()
  177. {
  178. for (int i = 1; i <= textureWidth; i++)
  179. {
  180. for (int j = 1; j <= textureHeight; j++)
  181. {
  182. Color color = eraseTexture.GetPixel(i, j);
  183. color.a = 1;
  184. eraseTexture.SetPixel(i, j, color);
  185. }
  186. }
  187. eraseTexture.Apply();
  188. }
  189. }