HyperTextBase.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using HyperlinkText;
  5. using UnityEngine.EventSystems;
  6. namespace UnityEngine.UI
  7. {
  8. [ExecuteInEditMode]
  9. public abstract class HyperTextBase : BaseMeshEffect, ICanvasRaycastFilter
  10. {
  11. private Canvas RootCanvas
  12. {
  13. get
  14. {
  15. Canvas result;
  16. if ((result = this._rootCanvas) == null)
  17. {
  18. result = (this._rootCanvas = base.GetComponentInParent<Canvas>());
  19. }
  20. return result;
  21. }
  22. }
  23. protected Text text
  24. {
  25. get
  26. {
  27. Text result;
  28. if ((result = this.m_TextComp) == null)
  29. {
  30. result = (this.m_TextComp = base.GetComponent<Text>());
  31. }
  32. return result;
  33. }
  34. }
  35. protected void RegisterClickable(int startIndex, int wordLength, string returnString, Color color, Action<string> onClick, Action<HyperTextBase.ClickableEntry> onEnter = null, Action<HyperTextBase.ClickableEntry> onExit = null)
  36. {
  37. if (onClick == null)
  38. {
  39. Debug.LogWarning("クリック時のイベントにnullが指定されました");
  40. return;
  41. }
  42. if (startIndex < 0 || wordLength < 0 || startIndex + wordLength > this.text.text.Length)
  43. {
  44. Debug.LogWarning("テキストの文字数範囲外です");
  45. return;
  46. }
  47. this._entries.Add(new HyperTextBase.ClickableEntry(this.text.text.Substring(startIndex, wordLength), startIndex, returnString, color, onClick, onEnter, onExit));
  48. }
  49. public virtual void RemoveClickable()
  50. {
  51. this._entries.Clear();
  52. }
  53. protected abstract void RegisterClickable();
  54. public override void ModifyMesh(VertexHelper vertexHelper)
  55. {
  56. this._entries.Clear();
  57. this.RegisterClickable();
  58. List<UIVertex> list = HyperTextBase._verticesPool.Get();
  59. vertexHelper.GetUIVertexStream(list);
  60. this.Modify(ref list);
  61. vertexHelper.Clear();
  62. vertexHelper.AddUIVertexTriangleStream(list);
  63. HyperTextBase._verticesPool.Release(list);
  64. if (Application.isPlaying)
  65. {
  66. base.StartCoroutine(this.CreateLinkObject());
  67. }
  68. }
  69. protected void Modify(ref List<UIVertex> vertices)
  70. {
  71. if (!base.enabled)
  72. {
  73. return;
  74. }
  75. int count = vertices.Count;
  76. int i = 0;
  77. int count2 = this._entries.Count;
  78. while (i < count2)
  79. {
  80. HyperTextBase.ClickableEntry value = this._entries[i];
  81. value.CharVertices.Clear();
  82. int j = value.StartIndex;
  83. int num = value.StartIndex + value.ClickableWord.Length;
  84. while (j < num)
  85. {
  86. int num2 = j * 6;
  87. if (num2 + 6 > count)
  88. {
  89. break;
  90. }
  91. char c = this.text.text[j];
  92. if (c != '\n' && c != '\r')
  93. {
  94. Vector2 min = Vector2.one * float.MaxValue;
  95. Vector2 max = Vector2.one * float.MinValue;
  96. for (int k = 0; k < 6; k++)
  97. {
  98. UIVertex uivertex = vertices[num2 + k];
  99. Vector3 position = vertices[num2 + k].position;
  100. if (position.y < min.y)
  101. {
  102. min.y = position.y;
  103. }
  104. if (position.x < min.x)
  105. {
  106. min.x = position.x;
  107. }
  108. if (position.y > max.y)
  109. {
  110. max.y = position.y;
  111. }
  112. if (position.x > max.x)
  113. {
  114. max.x = position.x;
  115. }
  116. value.CharVertices.Add(uivertex);
  117. uivertex.position = Vector3.zero;
  118. vertices[num2 + k] = uivertex;
  119. }
  120. value.Rects.Add(new Rect
  121. {
  122. min = min,
  123. max = max
  124. });
  125. }
  126. j++;
  127. }
  128. List<Rect> list = new List<Rect>();
  129. foreach (List<Rect> rects in this.SplitRectsByRow(value.Rects))
  130. {
  131. list.Add(this.CalculateAABB(rects));
  132. }
  133. value.Rects = list;
  134. this._entries[i] = value;
  135. i++;
  136. }
  137. }
  138. private List<List<Rect>> SplitRectsByRow(List<Rect> rects)
  139. {
  140. List<List<Rect>> list = new List<List<Rect>>();
  141. int num = 0;
  142. int i = 1;
  143. int count = rects.Count;
  144. while (i < count)
  145. {
  146. if (rects[i].xMin < rects[i - 1].xMin)
  147. {
  148. list.Add(rects.GetRange(num, i - num));
  149. num = i;
  150. }
  151. i++;
  152. }
  153. if (num < rects.Count)
  154. {
  155. list.Add(rects.GetRange(num, rects.Count - num));
  156. }
  157. return list;
  158. }
  159. private Rect CalculateAABB(List<Rect> rects)
  160. {
  161. Vector2 min = Vector2.one * float.MaxValue;
  162. Vector2 max = Vector2.one * float.MinValue;
  163. int i = 0;
  164. int count = rects.Count;
  165. while (i < count)
  166. {
  167. if (rects[i].xMin < min.x)
  168. {
  169. min.x = rects[i].xMin;
  170. }
  171. if (rects[i].yMin < min.y)
  172. {
  173. min.y = rects[i].yMin;
  174. }
  175. if (rects[i].xMax > max.x)
  176. {
  177. max.x = rects[i].xMax;
  178. }
  179. if (rects[i].yMax > max.y)
  180. {
  181. max.y = rects[i].yMax;
  182. }
  183. i++;
  184. }
  185. return new Rect
  186. {
  187. min = min,
  188. max = max
  189. };
  190. }
  191. private IEnumerator CreateLinkObject()
  192. {
  193. yield return null;
  194. if (!base.enabled)
  195. {
  196. yield break;
  197. }
  198. int i = 0;
  199. while (i < this._entries.Count)
  200. {
  201. HyperTextBase.ClickableEntry entry = this._entries[i];
  202. bool flag = entry.Rects.Count <= 0;
  203. Rect rect = this.CalculateAABB(entry.Rects);
  204. GameObject gameObject;
  205. if (base.transform.childCount <= i)
  206. {
  207. gameObject = new GameObject("clickable");
  208. gameObject.transform.SetParent(base.transform, false);
  209. goto IL_FE;
  210. }
  211. gameObject = base.transform.GetChild(i).gameObject;
  212. if (!flag)
  213. {
  214. goto IL_FE;
  215. }
  216. gameObject.SetActive(false);
  217. IL_25F:
  218. i++;
  219. continue;
  220. IL_FE:
  221. gameObject.name = entry.ClickableWord;
  222. if (!gameObject.activeSelf)
  223. {
  224. gameObject.SetActive(true);
  225. }
  226. RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
  227. if (rectTransform == null)
  228. {
  229. rectTransform = gameObject.AddComponent<RectTransform>();
  230. }
  231. Text text = gameObject.GetComponent<Text>();
  232. if (text == null)
  233. {
  234. text = gameObject.AddComponent<Text>();
  235. Button button = gameObject.AddComponent<Button>();
  236. ColorBlock colors = button.colors;
  237. colors.normalColor = Color.cyan;
  238. colors.fadeDuration = 0.1f;
  239. colors.colorMultiplier = 3f;
  240. button.colors = colors;
  241. Navigation navigation = button.navigation;
  242. navigation.mode = Navigation.Mode.None;
  243. button.navigation = navigation;
  244. }
  245. text.text = entry.ClickableWord;
  246. text.font = this.text.font;
  247. text.fontSize = this.text.fontSize;
  248. text.supportRichText = true;
  249. text.horizontalOverflow = HorizontalWrapMode.Overflow;
  250. text.verticalOverflow = VerticalWrapMode.Overflow;
  251. HyperTextBase.LinkObject linkObject = gameObject.GetComponent<HyperTextBase.LinkObject>();
  252. if (linkObject == null)
  253. {
  254. linkObject = gameObject.AddComponent<HyperTextBase.LinkObject>();
  255. }
  256. linkObject.entry = entry;
  257. rectTransform.pivot = Vector2.zero;
  258. rectTransform.sizeDelta = rect.size;
  259. rectTransform.localPosition = rect.position;
  260. goto IL_25F;
  261. }
  262. for (int j = this._entries.Count; j < base.transform.childCount; j++)
  263. {
  264. base.transform.GetChild(j).gameObject.SetActive(false);
  265. }
  266. yield break;
  267. }
  268. private Vector3 ToLocalPosition(Vector3 position, Camera camera)
  269. {
  270. if (!this.RootCanvas)
  271. {
  272. return Vector3.zero;
  273. }
  274. if (this.RootCanvas.renderMode == RenderMode.ScreenSpaceOverlay)
  275. {
  276. return base.transform.InverseTransformPoint(position);
  277. }
  278. Vector2 zero = Vector2.zero;
  279. RectTransformUtility.ScreenPointToLocalPointInRectangle(this.text.rectTransform, position, camera, out zero);
  280. return zero;
  281. }
  282. public bool IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera)
  283. {
  284. Vector3 point = this.ToLocalPosition(screenPos, eventCamera);
  285. for (int i = 0; i < this._entries.Count; i++)
  286. {
  287. for (int j = 0; j < this._entries[i].Rects.Count; j++)
  288. {
  289. if (this._entries[i].Rects[j].Contains(point))
  290. {
  291. return true;
  292. }
  293. }
  294. }
  295. return false;
  296. }
  297. private Canvas _rootCanvas;
  298. private Text m_TextComp;
  299. private const int CHAR_VERTS_NUM = 6;
  300. private readonly List<HyperTextBase.ClickableEntry> _entries = new List<HyperTextBase.ClickableEntry>();
  301. private static readonly ObjectPool<List<UIVertex>> _verticesPool = new ObjectPool<List<UIVertex>>(null, delegate(List<UIVertex> l)
  302. {
  303. l.Clear();
  304. });
  305. public struct ClickableEntry
  306. {
  307. public ClickableEntry(string clickableWord, int startIndex, string returnString, Color color, Action<string> onClick, Action<HyperTextBase.ClickableEntry> onEnter, Action<HyperTextBase.ClickableEntry> onExit)
  308. {
  309. this.ClickableWord = clickableWord;
  310. this.StartIndex = startIndex;
  311. this.ReturnString = returnString;
  312. this.Color = color;
  313. this.OnClick = onClick;
  314. this.OnEnter = onEnter;
  315. this.OnExit = onExit;
  316. this.isOverrideColor = true;
  317. this.Rects = new List<Rect>();
  318. this.CharVertices = new List<UIVertex>();
  319. }
  320. public string ClickableWord;
  321. public int StartIndex;
  322. public Color Color;
  323. public bool isOverrideColor;
  324. public string ReturnString;
  325. public Action<string> OnClick;
  326. public Action<HyperTextBase.ClickableEntry> OnEnter;
  327. public Action<HyperTextBase.ClickableEntry> OnExit;
  328. public List<Rect> Rects;
  329. public List<UIVertex> CharVertices;
  330. }
  331. public class LinkObject : BaseMeshEffect, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler, IEventSystemHandler
  332. {
  333. public void OnPointerClick(PointerEventData eventData)
  334. {
  335. this.entry.OnClick(this.entry.ReturnString);
  336. }
  337. public void OnPointerEnter(PointerEventData eventData)
  338. {
  339. this.entry.OnEnter(this.entry);
  340. }
  341. public void OnPointerExit(PointerEventData eventData)
  342. {
  343. this.entry.OnExit(this.entry);
  344. }
  345. public override void ModifyMesh(VertexHelper vertexHelper)
  346. {
  347. vertexHelper.Clear();
  348. List<UIVertex> list = HyperTextBase._verticesPool.Get();
  349. list.AddRange(this.entry.CharVertices);
  350. for (int i = 0; i < list.Count; i++)
  351. {
  352. UIVertex value = list[i];
  353. value.position -= base.transform.localPosition;
  354. list[i] = value;
  355. }
  356. vertexHelper.AddUIVertexTriangleStream(list);
  357. HyperTextBase._verticesPool.Release(list);
  358. }
  359. public HyperTextBase.ClickableEntry entry;
  360. }
  361. }
  362. }