Mirror.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Sprites;
  6. using UnityEngine.UI;
  7. using UGUI.Collections;
  8. namespace UGUI.Effects
  9. {
  10. [AddComponentMenu("UI/Effects/Mirror", 20)]
  11. [RequireComponent(typeof(Graphic))]
  12. public class Mirror : BaseMeshEffect
  13. {
  14. public enum MirrorType
  15. {
  16. /// <summary>
  17. /// 水平
  18. /// </summary>
  19. Horizontal,
  20. /// <summary>
  21. /// 垂直
  22. /// </summary>
  23. Vertical,
  24. /// <summary>
  25. /// 四分之一
  26. /// 相当于水平,然后再垂直
  27. /// </summary>
  28. Quarter,
  29. }
  30. /// <summary>
  31. /// 镜像类型
  32. /// </summary>
  33. [SerializeField]
  34. private MirrorType m_MirrorType = MirrorType.Horizontal;
  35. public MirrorType mirrorType
  36. {
  37. get { return m_MirrorType; }
  38. set
  39. {
  40. if (m_MirrorType != value)
  41. {
  42. m_MirrorType = value;
  43. if(graphic != null){
  44. graphic.SetVerticesDirty();
  45. }
  46. }
  47. }
  48. }
  49. [NonSerialized]
  50. private RectTransform m_RectTransform;
  51. public RectTransform rectTransform
  52. {
  53. get { return m_RectTransform ?? (m_RectTransform = GetComponent<RectTransform>()); }
  54. }
  55. /// <summary>
  56. /// 设置原始尺寸
  57. /// </summary>
  58. public void SetNativeSize()
  59. {
  60. if (graphic != null && graphic is Image)
  61. {
  62. Sprite overrideSprite = (graphic as Image).overrideSprite;
  63. if(overrideSprite != null){
  64. float w = overrideSprite.rect.width / (graphic as Image).pixelsPerUnit;
  65. float h = overrideSprite.rect.height / (graphic as Image).pixelsPerUnit;
  66. rectTransform.anchorMax = rectTransform.anchorMin;
  67. switch (m_MirrorType)
  68. {
  69. case MirrorType.Horizontal:
  70. rectTransform.sizeDelta = new Vector2(w * 2, h);
  71. break;
  72. case MirrorType.Vertical:
  73. rectTransform.sizeDelta = new Vector2(w, h * 2);
  74. break;
  75. case MirrorType.Quarter:
  76. rectTransform.sizeDelta = new Vector2(w * 2, h * 2);
  77. break;
  78. }
  79. graphic.SetVerticesDirty();
  80. }
  81. }
  82. }
  83. public override void ModifyMesh(VertexHelper vh)
  84. {
  85. if (!IsActive())
  86. {
  87. return;
  88. }
  89. var output = ListPool<UIVertex>.Get();
  90. vh.GetUIVertexStream(output);
  91. int count = output.Count;
  92. if (graphic is Image)
  93. {
  94. Image.Type type = (graphic as Image).type;
  95. switch (type)
  96. {
  97. case Image.Type.Simple:
  98. DrawSimple(output, count);
  99. break;
  100. case Image.Type.Sliced:
  101. DrawSliced(output, count);
  102. break;
  103. case Image.Type.Tiled:
  104. break;
  105. case Image.Type.Filled:
  106. break;
  107. }
  108. }
  109. else
  110. {
  111. DrawSimple(output, count);
  112. }
  113. vh.Clear();
  114. vh.AddUIVertexTriangleStream(output);
  115. ListPool<UIVertex>.Recycle(output);
  116. }
  117. /// <summary>
  118. /// 绘制Simple版
  119. /// </summary>
  120. /// <param name="output"></param>
  121. /// <param name="count"></param>
  122. protected void DrawSimple(List<UIVertex> output, int count)
  123. {
  124. Rect rect = graphic.GetPixelAdjustedRect();
  125. SimpleScale(rect, output, count);
  126. switch (m_MirrorType)
  127. {
  128. case MirrorType.Horizontal:
  129. ExtendCapacity(output, count);
  130. MirrorVerts(rect, output, count, true);
  131. break;
  132. case MirrorType.Vertical:
  133. ExtendCapacity(output, count);
  134. MirrorVerts(rect, output, count, false);
  135. break;
  136. case MirrorType.Quarter:
  137. ExtendCapacity(output, count * 3);
  138. MirrorVerts(rect, output, count, true);
  139. MirrorVerts(rect, output, count * 2, false);
  140. break;
  141. }
  142. }
  143. /// <summary>
  144. /// 绘制Sliced版
  145. /// </summary>
  146. /// <param name="output"></param>
  147. /// <param name="count"></param>
  148. protected void DrawSliced(List<UIVertex> output, int count)
  149. {
  150. if (!(graphic as Image).hasBorder)
  151. {
  152. DrawSimple(output, count);
  153. }
  154. Rect rect = graphic.GetPixelAdjustedRect();
  155. SlicedScale(rect, output, count);
  156. count = SliceExcludeVerts(output, count);
  157. switch (m_MirrorType)
  158. {
  159. case MirrorType.Horizontal:
  160. ExtendCapacity(output, count);
  161. MirrorVerts(rect, output, count, true);
  162. break;
  163. case MirrorType.Vertical:
  164. ExtendCapacity(output, count);
  165. MirrorVerts(rect, output, count, false);
  166. break;
  167. case MirrorType.Quarter:
  168. ExtendCapacity(output, count * 3);
  169. MirrorVerts(rect, output, count, true);
  170. MirrorVerts(rect, output, count * 2, false);
  171. break;
  172. }
  173. }
  174. /// <summary>
  175. /// 扩展容量
  176. /// </summary>
  177. /// <param name="verts"></param>
  178. /// <param name="addCount"></param>
  179. protected void ExtendCapacity(List<UIVertex> verts, int addCount)
  180. {
  181. var neededCapacity = verts.Count + addCount;
  182. if (verts.Capacity < neededCapacity)
  183. {
  184. verts.Capacity = neededCapacity;
  185. }
  186. }
  187. /// <summary>
  188. /// Simple缩放位移顶点(减半)
  189. /// </summary>
  190. /// <param name="rect"></param>
  191. /// <param name="verts"></param>
  192. /// <param name="count"></param>
  193. protected void SimpleScale(Rect rect, List<UIVertex> verts, int count)
  194. {
  195. for (int i = 0; i < count; i++)
  196. {
  197. UIVertex vertex = verts[i];
  198. Vector3 position = vertex.position;
  199. if (m_MirrorType == MirrorType.Horizontal || m_MirrorType == MirrorType.Quarter)
  200. {
  201. position.x = (position.x + rect.x) * 0.5f;
  202. }
  203. if (m_MirrorType == MirrorType.Vertical || m_MirrorType == MirrorType.Quarter)
  204. {
  205. position.y = (position.y + rect.y) * 0.5f;
  206. }
  207. vertex.position = position;
  208. verts[i] = vertex;
  209. }
  210. }
  211. /// <summary>
  212. /// Sliced缩放位移顶点(减半)
  213. /// </summary>
  214. /// <param name="rect"></param>
  215. /// <param name="verts"></param>
  216. /// <param name="count"></param>
  217. protected void SlicedScale(Rect rect, List<UIVertex> verts, int count)
  218. {
  219. Vector4 border = GetAdjustedBorders(rect);
  220. float halfWidth = rect.width * 0.5f;
  221. float halfHeight = rect.height * 0.5f;
  222. for (int i = 0; i < count; i++)
  223. {
  224. UIVertex vertex = verts[i];
  225. Vector3 position = vertex.position;
  226. if (m_MirrorType == MirrorType.Horizontal || m_MirrorType == MirrorType.Quarter)
  227. {
  228. if (halfWidth < border.x && position.x >= rect.center.x)
  229. {
  230. position.x = rect.center.x;
  231. }
  232. else if (position.x >= border.x)
  233. {
  234. position.x = (position.x + rect.x) * 0.5f;
  235. }
  236. }
  237. if (m_MirrorType == MirrorType.Vertical || m_MirrorType == MirrorType.Quarter)
  238. {
  239. if (halfHeight < border.y && position.y >= rect.center.y)
  240. {
  241. position.y = rect.center.y;
  242. }
  243. else if (position.y >= border.y)
  244. {
  245. position.y = (position.y + rect.y) * 0.5f;
  246. }
  247. }
  248. vertex.position = position;
  249. verts[i] = vertex;
  250. }
  251. }
  252. /// <summary>
  253. /// 镜像顶点
  254. /// </summary>
  255. /// <param name="rect"></param>
  256. /// <param name="verts"></param>
  257. /// <param name="count"></param>
  258. /// <param name="isHorizontal"></param>
  259. protected void MirrorVerts(Rect rect, List<UIVertex> verts, int count, bool isHorizontal = true)
  260. {
  261. for (int i = 0; i < count; i++)
  262. {
  263. UIVertex vertex = verts[i];
  264. Vector3 position = vertex.position;
  265. if (isHorizontal)
  266. {
  267. position.x = rect.center.x * 2 - position.x;
  268. }
  269. else
  270. {
  271. position.y = rect.center.y * 2 - position.y;
  272. }
  273. vertex.position = position;
  274. verts.Add(vertex);
  275. }
  276. }
  277. /// <summary>
  278. /// 清理掉不能成三角面的顶点
  279. /// </summary>
  280. /// <param name="verts"></param>
  281. /// <param name="count"></param>
  282. /// <returns></returns>
  283. protected int SliceExcludeVerts(List<UIVertex> verts, int count)
  284. {
  285. int realCount = count;
  286. int i = 0;
  287. while (i < realCount)
  288. {
  289. UIVertex v1 = verts[i];
  290. UIVertex v2 = verts[i + 1];
  291. UIVertex v3 = verts[i + 2];
  292. if (v1.position == v2.position || v2.position == v3.position || v3.position == v1.position)
  293. {
  294. verts[i] = verts[realCount - 3];
  295. verts[i + 1] = verts[realCount - 2];
  296. verts[i + 2] = verts[realCount - 1];
  297. realCount -= 3;
  298. continue;
  299. }
  300. i += 3;
  301. }
  302. if (realCount < count)
  303. {
  304. verts.RemoveRange(realCount, count - realCount);
  305. }
  306. return realCount;
  307. }
  308. /// <summary>
  309. /// 返回矫正过的范围
  310. /// </summary>
  311. /// <param name="rect"></param>
  312. /// <returns></returns>
  313. protected Vector4 GetAdjustedBorders(Rect rect)
  314. {
  315. Sprite overrideSprite = (graphic as Image).overrideSprite;
  316. Vector4 border = overrideSprite.border;
  317. border = border / (graphic as Image).pixelsPerUnit;
  318. for (int axis = 0; axis <= 1; axis++)
  319. {
  320. float combinedBorders = border[axis] + border[axis + 2];
  321. if (rect.size[axis] < combinedBorders && combinedBorders != 0)
  322. {
  323. float borderScaleRatio = rect.size[axis] / combinedBorders;
  324. border[axis] *= borderScaleRatio;
  325. border[axis + 2] *= borderScaleRatio;
  326. }
  327. }
  328. return border;
  329. }
  330. }
  331. }