Açıklama Yok
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.

ChartHelper.cs 38KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using UnityEngine;
  7. using UnityEngine.EventSystems;
  8. using UnityEngine.UI;
  9. #if dUI_TextMeshPro
  10. using TMPro;
  11. #endif
  12. #if UNITY_EDITOR
  13. using UnityEditor;
  14. #endif
  15. namespace XCharts.Runtime
  16. {
  17. public static class ChartHelper
  18. {
  19. private static StringBuilder s_Builder = new StringBuilder();
  20. private static Vector3 s_DefaultIngoreDataVector3 = Vector3.zero;
  21. public static StringBuilder sb { get { return s_Builder; } }
  22. public static Vector3 ignoreVector3 { get { return s_DefaultIngoreDataVector3; } }
  23. public static bool IsIngore(Vector3 pos)
  24. {
  25. return pos == s_DefaultIngoreDataVector3;
  26. }
  27. public static string Cancat(string str1, string str2)
  28. {
  29. s_Builder.Length = 0;
  30. s_Builder.Append(str1).Append(str2);
  31. return s_Builder.ToString();
  32. }
  33. public static string Cancat(string str1, int i)
  34. {
  35. s_Builder.Length = 0;
  36. s_Builder.Append(str1).Append(ChartCached.IntToStr(i));
  37. return s_Builder.ToString();
  38. }
  39. public static void SetActive(GameObject gameObject, bool active)
  40. {
  41. if (gameObject == null) return;
  42. SetActive(gameObject.transform, active);
  43. }
  44. public static void SetActive(Image image, bool active)
  45. {
  46. if (image == null) return;
  47. SetActive(image.gameObject, active);
  48. }
  49. public static void SetActive(Text text, bool active)
  50. {
  51. if (text == null) return;
  52. SetActive(text.gameObject, active);
  53. }
  54. /// <summary>
  55. /// 通过设置scale实现是否显示,优化性能,减少GC
  56. /// </summary>
  57. /// <param name="transform"></param>
  58. /// <param name="active"></param>
  59. public static void SetActive(Transform transform, bool active)
  60. {
  61. if (transform == null) return;
  62. if (active) transform.localScale = Vector3.one;
  63. else transform.localScale = Vector3.zero;
  64. }
  65. public static void HideAllObject(GameObject obj, string match = null)
  66. {
  67. if (obj == null) return;
  68. HideAllObject(obj.transform, match);
  69. }
  70. public static void HideAllObject(Transform parent, string match = null)
  71. {
  72. if (parent == null) return;
  73. ActiveAllObject(parent, false, match);
  74. }
  75. public static void ActiveAllObject(Transform parent, bool active, string match = null)
  76. {
  77. if (parent == null) return;
  78. for (int i = 0; i < parent.childCount; i++)
  79. {
  80. if (match == null)
  81. SetActive(parent.GetChild(i), active);
  82. else
  83. {
  84. var go = parent.GetChild(i);
  85. if (go.name.StartsWith(match))
  86. {
  87. SetActive(go, active);
  88. }
  89. }
  90. }
  91. }
  92. public static void DestroyAllChildren(Transform parent)
  93. {
  94. if (parent == null) return;
  95. var childCount = parent.childCount;
  96. for (int i = childCount - 1; i >= 0; i--)
  97. {
  98. var go = parent.GetChild(i);
  99. if (go != null)
  100. {
  101. GameObject.DestroyImmediate(go.gameObject, true);
  102. }
  103. }
  104. }
  105. public static void DestoryGameObject(Transform parent, string childName)
  106. {
  107. if (parent == null) return;
  108. var go = parent.Find(childName);
  109. if (go != null)
  110. {
  111. GameObject.DestroyImmediate(go.gameObject, true);
  112. }
  113. }
  114. public static void DestoryGameObjectByMatch(Transform parent, string containString)
  115. {
  116. if (parent == null) return;
  117. var childCount = parent.childCount;
  118. for (int i = childCount - 1; i >= 0; i--)
  119. {
  120. var go = parent.GetChild(i);
  121. if (go != null && go.name.Contains(containString))
  122. {
  123. GameObject.DestroyImmediate(go.gameObject, true);
  124. }
  125. }
  126. }
  127. public static void DestoryGameObject(GameObject go)
  128. {
  129. if (go != null) GameObject.DestroyImmediate(go, true);
  130. }
  131. public static string GetFullName(Transform transform)
  132. {
  133. string name = transform.name;
  134. Transform obj = transform;
  135. while (obj.transform.parent)
  136. {
  137. name = obj.transform.parent.name + "/" + name;
  138. obj = obj.transform.parent;
  139. }
  140. return name;
  141. }
  142. public static void RemoveComponent<T>(GameObject gameObject)
  143. {
  144. var component = gameObject.GetComponent<T>();
  145. if (component != null)
  146. {
  147. #if UNITY_EDITOR
  148. if (!Application.isPlaying)
  149. GameObject.DestroyImmediate(component as GameObject, true);
  150. else
  151. GameObject.Destroy(component as GameObject);
  152. #else
  153. GameObject.Destroy(component as GameObject);
  154. #endif
  155. }
  156. }
  157. public static T GetOrAddComponent<T>(Transform transform) where T : Component
  158. {
  159. return GetOrAddComponent<T>(transform.gameObject);
  160. }
  161. public static T GetOrAddComponent<T>(GameObject gameObject) where T : Component
  162. {
  163. if (gameObject.GetComponent<T>() == null)
  164. {
  165. return gameObject.AddComponent<T>();
  166. }
  167. else
  168. {
  169. return gameObject.GetComponent<T>();
  170. }
  171. }
  172. public static GameObject AddObject(string name, Transform parent, Vector2 anchorMin,
  173. Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta, int replaceIndex = -1)
  174. {
  175. GameObject obj;
  176. if (parent.Find(name))
  177. {
  178. obj = parent.Find(name).gameObject;
  179. SetActive(obj, true);
  180. obj.transform.localPosition = Vector3.zero;
  181. obj.transform.localScale = Vector3.one;
  182. obj.transform.localRotation = Quaternion.Euler(0, 0, 0);
  183. }
  184. else if (replaceIndex >= 0 && replaceIndex < parent.childCount)
  185. {
  186. obj = parent.GetChild(replaceIndex).gameObject;
  187. if (!obj.name.Equals(name)) obj.name = name;
  188. SetActive(obj, true);
  189. }
  190. else
  191. {
  192. obj = new GameObject();
  193. obj.name = name;
  194. obj.transform.SetParent(parent);
  195. obj.transform.localScale = Vector3.one;
  196. obj.transform.localPosition = Vector3.zero;
  197. obj.transform.localRotation = Quaternion.Euler(0, 0, 0);
  198. obj.layer = parent.gameObject.layer;
  199. }
  200. RectTransform rect = GetOrAddComponent<RectTransform>(obj);
  201. rect.localPosition = Vector3.zero;
  202. rect.sizeDelta = sizeDelta;
  203. rect.anchorMin = anchorMin;
  204. rect.anchorMax = anchorMax;
  205. rect.pivot = pivot;
  206. rect.anchoredPosition3D = Vector3.zero;
  207. return obj;
  208. }
  209. public static void UpdateRectTransform(GameObject obj, Vector2 anchorMin,
  210. Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta)
  211. {
  212. if (obj == null) return;
  213. RectTransform rect = GetOrAddComponent<RectTransform>(obj);
  214. rect.sizeDelta = sizeDelta;
  215. rect.anchorMin = anchorMin;
  216. rect.anchorMax = anchorMax;
  217. rect.pivot = pivot;
  218. }
  219. public static ChartText AddTextObject(string objectName, Transform parent, Vector2 anchorMin, Vector2 anchorMax,
  220. Vector2 pivot, Vector2 sizeDelta, TextStyle textStyle, ComponentTheme theme, Color autoColor,
  221. TextAnchor autoAlignment, ChartText chartText = null)
  222. {
  223. GameObject txtObj = AddObject(objectName, parent, anchorMin, anchorMax, pivot, sizeDelta);
  224. txtObj.transform.localEulerAngles = new Vector3(0, 0, textStyle.rotate);
  225. txtObj.layer = parent.gameObject.layer;
  226. if (chartText == null)
  227. chartText = new ChartText();
  228. #if dUI_TextMeshPro
  229. RemoveComponent<Text>(txtObj);
  230. chartText.tmpText = GetOrAddComponent<TextMeshProUGUI>(txtObj);
  231. chartText.tmpText.font = textStyle.tmpFont == null ? theme.tmpFont : textStyle.tmpFont;
  232. chartText.tmpText.fontStyle = textStyle.tmpFontStyle;
  233. chartText.tmpText.richText = true;
  234. chartText.tmpText.raycastTarget = false;
  235. chartText.tmpText.enableWordWrapping = textStyle.autoWrap;
  236. #else
  237. chartText.text = GetOrAddComponent<Text>(txtObj);
  238. chartText.text.font = textStyle.font == null ? theme.font : textStyle.font;
  239. chartText.text.fontStyle = textStyle.fontStyle;
  240. chartText.text.horizontalOverflow = textStyle.autoWrap ? HorizontalWrapMode.Wrap : HorizontalWrapMode.Overflow;
  241. chartText.text.verticalOverflow = VerticalWrapMode.Overflow;
  242. chartText.text.supportRichText = true;
  243. chartText.text.raycastTarget = false;
  244. #endif
  245. if (textStyle.autoColor && autoColor != Color.clear)
  246. chartText.SetColor(autoColor);
  247. else
  248. chartText.SetColor(textStyle.GetColor(theme.textColor));
  249. chartText.SetAlignment(textStyle.autoAlign ? autoAlignment : textStyle.alignment);
  250. chartText.SetFontSize(textStyle.GetFontSize(theme));
  251. chartText.SetText("Text");
  252. chartText.SetLineSpacing(textStyle.lineSpacing);
  253. chartText.SetActive(textStyle.show);
  254. RectTransform rect = GetOrAddComponent<RectTransform>(txtObj);
  255. rect.localPosition = Vector3.zero;
  256. rect.sizeDelta = sizeDelta;
  257. rect.anchorMin = anchorMin;
  258. rect.anchorMax = anchorMax;
  259. rect.pivot = pivot;
  260. return chartText;
  261. }
  262. public static Painter AddPainterObject(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax,
  263. Vector2 pivot, Vector2 sizeDelta, HideFlags hideFlags, int siblingIndex)
  264. {
  265. var painterObj = ChartHelper.AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
  266. painterObj.hideFlags = hideFlags;
  267. painterObj.transform.SetSiblingIndex(siblingIndex);
  268. return ChartHelper.GetOrAddComponent<Painter>(painterObj);
  269. }
  270. public static Image AddIcon(string name, Transform parent, IconStyle iconStyle)
  271. {
  272. return AddIcon(name, parent, iconStyle.width, iconStyle.height, iconStyle.sprite, iconStyle.type);
  273. }
  274. public static Image AddIcon(string name, Transform parent, float width, float height, Sprite sprite = null,
  275. Image.Type type = Image.Type.Simple)
  276. {
  277. var anchorMax = new Vector2(0.5f, 0.5f);
  278. var anchorMin = new Vector2(0.5f, 0.5f);
  279. var pivot = new Vector2(0.5f, 0.5f);
  280. var sizeDelta = new Vector2(width, height);
  281. GameObject iconObj = AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
  282. var img = GetOrAddComponent<Image>(iconObj);
  283. if (img.raycastTarget != false)
  284. img.raycastTarget = false;
  285. if (img.type != type)
  286. img.type = type;
  287. if (sprite != null && img.sprite != sprite)
  288. {
  289. img.sprite = sprite;
  290. if (width == 0 || height == 0)
  291. {
  292. img.SetNativeSize();
  293. }
  294. }
  295. return img;
  296. }
  297. public static void SetBackground(Image background, ImageStyle imageStyle)
  298. {
  299. if (background == null) return;
  300. if (imageStyle.show)
  301. {
  302. background.gameObject.SetActive(true);
  303. background.sprite = imageStyle.sprite;
  304. background.color = imageStyle.color;
  305. background.type = imageStyle.type;
  306. if (imageStyle.width > 0 && imageStyle.height > 0)
  307. {
  308. background.rectTransform.sizeDelta = new Vector2(imageStyle.width, imageStyle.height);
  309. }
  310. }
  311. else
  312. {
  313. background.sprite = null;
  314. background.color = Color.clear;
  315. background.gameObject.SetActive(false);
  316. }
  317. }
  318. public static ChartLabel AddAxisLabelObject(int total, int index, string name, Transform parent,
  319. Vector2 sizeDelta, Axis axis, ComponentTheme theme,
  320. string content, Color autoColor, TextAnchor autoAlignment = TextAnchor.MiddleCenter)
  321. {
  322. var textStyle = axis.axisLabel.textStyle;
  323. var label = AddChartLabel(name, parent, axis.axisLabel, theme, content, autoColor, autoAlignment);
  324. var labelShow = axis.IsNeedShowLabel(index, total);
  325. label.UpdateIcon(axis.axisLabel.icon, axis.GetIcon(index));
  326. label.text.SetActive(labelShow);
  327. return label;
  328. }
  329. public static ChartLabel AddChartLabel(string name, Transform parent, LabelStyle labelStyle,
  330. ComponentTheme theme, string content, Color autoColor, TextAnchor autoAlignment = TextAnchor.MiddleCenter)
  331. {
  332. Vector2 anchorMin, anchorMax, pivot;
  333. var sizeDelta = new Vector2(labelStyle.width, labelStyle.height);
  334. var textStyle = labelStyle.textStyle;
  335. var alignment = textStyle.GetAlignment(autoAlignment);
  336. UpdateAnchorAndPivotByTextAlignment(alignment, out anchorMin, out anchorMax, out pivot);
  337. var labelObj = AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
  338. var label = GetOrAddComponent<ChartLabel>(labelObj);
  339. label.text = AddTextObject("Text", label.gameObject.transform, anchorMin, anchorMax, pivot,
  340. sizeDelta, textStyle, theme, autoColor, autoAlignment, label.text);
  341. label.icon = ChartHelper.AddIcon("Icon", label.gameObject.transform, labelStyle.icon);
  342. label.SetSize(labelStyle.width, labelStyle.height);
  343. label.SetTextPadding(labelStyle.textPadding);
  344. label.SetText(content);
  345. label.UpdateIcon(labelStyle.icon);
  346. if (labelStyle.background.show)
  347. {
  348. label.color = (!labelStyle.background.autoColor || autoColor == Color.clear) ?
  349. labelStyle.background.color : autoColor;
  350. label.sprite = labelStyle.background.sprite;
  351. label.type = labelStyle.background.type;
  352. }
  353. else
  354. {
  355. label.color = Color.clear;
  356. label.sprite = null;
  357. }
  358. label.transform.localEulerAngles = new Vector3(0, 0, labelStyle.rotate);
  359. label.transform.localPosition = labelStyle.offset;
  360. return label;
  361. }
  362. public static ChartLabel AddChartLabel2(string name, Transform parent, LabelStyle labelStyle,
  363. ComponentTheme theme, string content, Color autoColor, TextAnchor autoAlignment = TextAnchor.MiddleCenter)
  364. {
  365. Vector2 anchorMin, anchorMax, pivot;
  366. var sizeDelta = new Vector2(labelStyle.width, labelStyle.height);
  367. var textStyle = labelStyle.textStyle;
  368. var alignment = textStyle.GetAlignment(autoAlignment);
  369. UpdateAnchorAndPivotByTextAlignment(alignment, out anchorMin, out anchorMax, out pivot);
  370. var vector0_5 = new Vector2(0.5f, 0.5f);
  371. var labelObj = AddObject(name, parent, vector0_5, vector0_5, vector0_5, sizeDelta);
  372. var label = GetOrAddComponent<ChartLabel>(labelObj);
  373. label.text = AddTextObject("Text", label.gameObject.transform, anchorMin, anchorMax, pivot,
  374. sizeDelta, textStyle, theme, autoColor, autoAlignment, label.text);
  375. label.icon = ChartHelper.AddIcon("Icon", label.gameObject.transform, labelStyle.icon);
  376. label.SetSize(labelStyle.width, labelStyle.height);
  377. label.SetTextPadding(labelStyle.textPadding);
  378. label.SetText(content);
  379. label.UpdateIcon(labelStyle.icon);
  380. if (labelStyle.background.show)
  381. {
  382. label.color = (!labelStyle.background.autoColor || autoColor == Color.clear) ?
  383. labelStyle.background.color : autoColor;
  384. label.sprite = labelStyle.background.sprite;
  385. label.type = labelStyle.background.type;
  386. }
  387. else
  388. {
  389. label.color = Color.clear;
  390. label.sprite = null;
  391. }
  392. label.transform.localEulerAngles = new Vector3(0, 0, labelStyle.rotate);
  393. label.transform.localPosition = labelStyle.offset;
  394. return label;
  395. }
  396. private static void UpdateAnchorAndPivotByTextAlignment(TextAnchor alignment, out Vector2 anchorMin, out Vector2 anchorMax,
  397. out Vector2 pivot)
  398. {
  399. switch (alignment)
  400. {
  401. case TextAnchor.LowerLeft:
  402. anchorMin = new Vector2(0f, 0f);
  403. anchorMax = new Vector2(0f, 0f);
  404. pivot = new Vector2(0f, 0f);
  405. break;
  406. case TextAnchor.UpperLeft:
  407. anchorMin = new Vector2(0f, 1f);
  408. anchorMax = new Vector2(0f, 1f);
  409. pivot = new Vector2(0f, 1f);
  410. break;
  411. case TextAnchor.MiddleLeft:
  412. anchorMin = new Vector2(0f, 0.5f);
  413. anchorMax = new Vector2(0f, 0.5f);
  414. pivot = new Vector2(0f, 0.5f);
  415. break;
  416. case TextAnchor.LowerRight:
  417. anchorMin = new Vector2(1f, 0f);
  418. anchorMax = new Vector2(1f, 0f);
  419. pivot = new Vector2(1f, 0f);
  420. break;
  421. case TextAnchor.UpperRight:
  422. anchorMin = new Vector2(1f, 1f);
  423. anchorMax = new Vector2(1f, 1f);
  424. pivot = new Vector2(1f, 1f);
  425. break;
  426. case TextAnchor.MiddleRight:
  427. anchorMin = new Vector2(1, 0.5f);
  428. anchorMax = new Vector2(1, 0.5f);
  429. pivot = new Vector2(1, 0.5f);
  430. break;
  431. case TextAnchor.LowerCenter:
  432. anchorMin = new Vector2(0.5f, 0f);
  433. anchorMax = new Vector2(0.5f, 0f);
  434. pivot = new Vector2(0.5f, 0f);
  435. break;
  436. case TextAnchor.UpperCenter:
  437. anchorMin = new Vector2(0.5f, 1f);
  438. anchorMax = new Vector2(0.5f, 1f);
  439. pivot = new Vector2(0.5f, 1f);
  440. break;
  441. case TextAnchor.MiddleCenter:
  442. anchorMin = new Vector2(0.5f, 0.5f);
  443. anchorMax = new Vector2(0.5f, 0.5f);
  444. pivot = new Vector2(0.5f, 0.5f);
  445. break;
  446. default:
  447. anchorMin = new Vector2(0.5f, 0.5f);
  448. anchorMax = new Vector2(0.5f, 0.5f);
  449. pivot = new Vector2(0.5f, 0.5f);
  450. break;
  451. }
  452. }
  453. internal static ChartLabel AddTooltipIndicatorLabel(Tooltip tooltip, string name, Transform parent,
  454. ThemeStyle theme, TextAnchor alignment, LabelStyle labelStyle)
  455. {
  456. var label = ChartHelper.AddChartLabel(name, parent, labelStyle, theme.tooltip,
  457. "", Color.clear, alignment);
  458. label.SetActive(tooltip.show && labelStyle.show);
  459. return label;
  460. }
  461. public static void GetPointList(ref List<Vector3> posList, Vector3 sp, Vector3 ep, float k = 30f)
  462. {
  463. Vector3 dir = (ep - sp).normalized;
  464. float dist = Vector3.Distance(sp, ep);
  465. int segment = (int) (dist / k);
  466. posList.Clear();
  467. posList.Add(sp);
  468. for (int i = 1; i < segment; i++)
  469. {
  470. posList.Add(sp + dir * dist * i / segment);
  471. }
  472. posList.Add(ep);
  473. }
  474. public static bool IsValueEqualsColor(Color32 color1, Color32 color2)
  475. {
  476. return color1.a == color2.a &&
  477. color1.b == color2.b &&
  478. color1.g == color2.g &&
  479. color1.r == color2.r;
  480. }
  481. public static bool IsValueEqualsColor(Color color1, Color color2)
  482. {
  483. return color1.a == color2.a &&
  484. color1.b == color2.b &&
  485. color1.g == color2.g &&
  486. color1.r == color2.r;
  487. }
  488. public static bool IsValueEqualsString(string str1, string str2)
  489. {
  490. if (str1 == null && str2 == null) return true;
  491. else if (str1 != null && str2 != null) return str1.Equals(str2);
  492. else return false;
  493. }
  494. public static bool IsValueEqualsVector2(Vector2 v1, Vector2 v2)
  495. {
  496. return v1.x == v2.x && v1.y == v2.y;
  497. }
  498. public static bool IsValueEqualsVector3(Vector3 v1, Vector3 v2)
  499. {
  500. return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
  501. }
  502. public static bool IsValueEqualsList<T>(List<T> list1, List<T> list2)
  503. {
  504. if (list1 == null || list2 == null) return false;
  505. if (list1.Count != list2.Count) return false;
  506. for (int i = 0; i < list1.Count; i++)
  507. {
  508. if (list1[i] == null && list2[i] == null) { }
  509. else
  510. {
  511. if (list1[i] != null)
  512. {
  513. if (!list1[i].Equals(list2[i])) return false;
  514. }
  515. else
  516. {
  517. if (!list2[i].Equals(list1[i])) return false;
  518. }
  519. }
  520. }
  521. return true;
  522. }
  523. public static bool IsEquals(double d1, double d2)
  524. {
  525. return Math.Abs(d1 - d2) < 0.000001d;
  526. }
  527. public static bool IsEquals(float d1, float d2)
  528. {
  529. return Math.Abs(d1 - d2) < 0.000001f;
  530. }
  531. public static bool IsClearColor(Color32 color)
  532. {
  533. return color.a == 0 && color.b == 0 && color.g == 0 && color.r == 0;
  534. }
  535. public static bool IsClearColor(Color color)
  536. {
  537. return color.a == 0 && color.b == 0 && color.g == 0 && color.r == 0;
  538. }
  539. public static bool IsZeroVector(Vector3 pos)
  540. {
  541. return pos.x == 0 && pos.y == 0 && pos.z == 0;
  542. }
  543. public static bool CopyList<T>(List<T> toList, List<T> fromList)
  544. {
  545. if (toList == null || fromList == null) return false;
  546. toList.Clear();
  547. foreach (var item in fromList) toList.Add(item);
  548. return true;
  549. }
  550. public static bool CopyArray<T>(T[] toList, T[] fromList)
  551. {
  552. if (toList == null || fromList == null) return false;
  553. if (toList.Length != fromList.Length)
  554. {
  555. toList = new T[fromList.Length];
  556. }
  557. for (int i = 0; i < fromList.Length; i++) toList[i] = fromList[i];
  558. return true;
  559. }
  560. public static List<float> ParseFloatFromString(string jsonData)
  561. {
  562. List<float> list = new List<float>();
  563. if (string.IsNullOrEmpty(jsonData)) return list;
  564. int startIndex = jsonData.IndexOf("[");
  565. int endIndex = jsonData.IndexOf("]");
  566. string temp = jsonData.Substring(startIndex + 1, endIndex - startIndex - 1);
  567. if (temp.IndexOf("],") > -1 || temp.IndexOf("] ,") > -1)
  568. {
  569. string[] datas = temp.Split(new string[] { "],", "] ," }, StringSplitOptions.RemoveEmptyEntries);
  570. for (int i = 0; i < datas.Length; i++)
  571. {
  572. temp = datas[i];
  573. }
  574. return list;
  575. }
  576. else
  577. {
  578. string[] datas = temp.Split(',');
  579. for (int i = 0; i < datas.Length; i++)
  580. {
  581. list.Add(float.Parse(datas[i].Trim()));
  582. }
  583. return list;
  584. }
  585. }
  586. public static List<string> ParseStringFromString(string jsonData)
  587. {
  588. List<string> list = new List<string>();
  589. if (string.IsNullOrEmpty(jsonData)) return list;
  590. string pattern = "[\"'](.*?)[\"']";
  591. if (Regex.IsMatch(jsonData, pattern))
  592. {
  593. MatchCollection m = Regex.Matches(jsonData, pattern);
  594. foreach (Match match in m)
  595. {
  596. list.Add(match.Groups[1].Value);
  597. }
  598. }
  599. return list;
  600. }
  601. public static Color32 GetColor(string hexColorStr)
  602. {
  603. Color color;
  604. ColorUtility.TryParseHtmlString(hexColorStr, out color);
  605. return (Color32) color;
  606. }
  607. public static double GetMaxDivisibleValue(double max, double ceilRate)
  608. {
  609. if (max == 0) return 0;
  610. if (max > -1 && max < 1)
  611. {
  612. int count = 1;
  613. int intvalue = (int) (max * Mathf.Pow(10, count));
  614. while (intvalue == 0 && count < 12)
  615. {
  616. count++;
  617. intvalue = (int) (max * Mathf.Pow(10, count));
  618. }
  619. var pow = Mathf.Pow(10, count);
  620. if (max > 0) return (int) ((max * pow + 1)) / pow;
  621. else return (int) ((max * pow - 1)) / pow;
  622. }
  623. if (ceilRate == 0)
  624. {
  625. var bigger = Math.Ceiling(Math.Abs(max));
  626. int n = 1;
  627. while (bigger / (Mathf.Pow(10, n)) > 10)
  628. {
  629. n++;
  630. }
  631. double mm = bigger;
  632. var pown = Mathf.Pow(10, n);
  633. var powmax = Mathf.Pow(10, n + 1);
  634. var aliquot = mm % pown == 0;
  635. if (mm > 10 && n < 38)
  636. {
  637. mm = bigger - bigger % pown;
  638. if (!aliquot)
  639. mm += max > 0 ? pown : -pown;
  640. }
  641. var mmm = mm;
  642. if (max > 100 && !aliquot && (max / mm < 0.8f))
  643. mmm -= Mathf.Pow(10, n) / 2;
  644. if (mmm >= (powmax - pown) && mmm < powmax)
  645. mmm = powmax;
  646. if (max < 0) return -Math.Ceiling(mmm > -max ? mmm : mm);
  647. else return Math.Ceiling(mmm > max ? mmm : mm);
  648. }
  649. else
  650. {
  651. var mod = max % ceilRate;
  652. int rate = (int) (max / ceilRate);
  653. return mod == 0 ? max : (max < 0 ? rate : rate + 1) * ceilRate;
  654. }
  655. }
  656. public static double GetMinDivisibleValue(double min, double ceilRate)
  657. {
  658. if (min == 0) return 0;
  659. if (min > -1 && min < 1)
  660. {
  661. int count = 1;
  662. int intvalue = (int) (min * Mathf.Pow(10, count));
  663. while (intvalue == 0 && count < 12)
  664. {
  665. count++;
  666. intvalue = (int) (min * Mathf.Pow(10, count));
  667. }
  668. var pow = Mathf.Pow(10, count);
  669. if (min > 0) return (int) ((min * pow + 1)) / pow;
  670. else return (int) ((min * pow - 1)) / pow;
  671. }
  672. if (ceilRate == 0)
  673. {
  674. var bigger = min < 0 ? Math.Ceiling(Math.Abs(min)) : Math.Floor(Math.Abs(min));
  675. int n = 1;
  676. while (bigger / (Mathf.Pow(10, n)) > 10)
  677. {
  678. n++;
  679. }
  680. double mm = bigger;
  681. if (mm > 10 && n < 38)
  682. {
  683. mm = bigger - bigger % (Mathf.Pow(10, n));
  684. mm += min < 0 ? Mathf.Pow(10, n) : -Mathf.Pow(10, n);
  685. }
  686. if (min < 0) return -Math.Floor(mm);
  687. else return Math.Floor(mm);
  688. }
  689. else
  690. {
  691. var mod = min % ceilRate;
  692. int rate = (int) (min / ceilRate);
  693. return mod == 0 ? min : (min < 0 ? rate - 1 : rate) * ceilRate;
  694. }
  695. }
  696. public static double GetMaxLogValue(double value, float logBase, bool isLogBaseE, out int splitNumber)
  697. {
  698. splitNumber = 0;
  699. if (value <= 0) return 0;
  700. double max = 0;
  701. while (max < value)
  702. {
  703. if (isLogBaseE)
  704. {
  705. max = Math.Exp(splitNumber);
  706. }
  707. else
  708. {
  709. max = Math.Pow(logBase, splitNumber);
  710. }
  711. splitNumber++;
  712. }
  713. return max;
  714. }
  715. public static double GetMinLogValue(double value, float logBase, bool isLogBaseE, out int splitNumber)
  716. {
  717. splitNumber = 0;
  718. if (value > 1) return 1;
  719. double min = 1;
  720. while (min > value)
  721. {
  722. if (isLogBaseE)
  723. {
  724. min = Math.Exp(-splitNumber);
  725. }
  726. else
  727. {
  728. min = Math.Pow(logBase, -splitNumber);
  729. }
  730. splitNumber++;
  731. }
  732. return min;
  733. }
  734. public static int GetFloatAccuracy(double value)
  735. {
  736. if (value > 1 || value < -1) return 0;
  737. int count = 1;
  738. int intvalue = (int) (value * Mathf.Pow(10, count));
  739. while (intvalue == 0 && count < 38)
  740. {
  741. count++;
  742. intvalue = (int) (value * Mathf.Pow(10, count));
  743. }
  744. if (count == 38 && (value == 0 || value == 1)) return 1;
  745. else return count;
  746. }
  747. public static void AddEventListener(GameObject obj, EventTriggerType type,
  748. UnityEngine.Events.UnityAction<BaseEventData> call)
  749. {
  750. EventTrigger trigger = GetOrAddComponent<EventTrigger>(obj.gameObject);
  751. EventTrigger.Entry entry = new EventTrigger.Entry();
  752. entry.eventID = type;
  753. entry.callback = new EventTrigger.TriggerEvent();
  754. entry.callback.AddListener(call);
  755. trigger.triggers.Add(entry);
  756. }
  757. public static void ClearEventListener(GameObject obj)
  758. {
  759. EventTrigger trigger = obj.GetComponent<EventTrigger>();
  760. if (trigger != null)
  761. {
  762. trigger.triggers.Clear();
  763. }
  764. }
  765. public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
  766. {
  767. Vector3 point = Quaternion.AngleAxis(angle, axis) * (position - center);
  768. Vector3 resultVec3 = center + point;
  769. return resultVec3;
  770. }
  771. public static Vector3 GetPosition(Vector3 center, float angle, float radius)
  772. {
  773. var rad = angle * Mathf.Deg2Rad;
  774. var px = Mathf.Sin(rad) * radius;
  775. var py = Mathf.Cos(rad) * radius;
  776. return center + new Vector3(px, py);
  777. }
  778. /// <summary>
  779. /// 获得0-360的角度(12点钟方向为0度)
  780. /// </summary>
  781. /// <param name="from"></param>
  782. /// <param name="to"></param>
  783. /// <returns></returns>
  784. public static float GetAngle360(Vector2 from, Vector2 to)
  785. {
  786. float angle;
  787. Vector3 cross = Vector3.Cross(from, to);
  788. angle = Vector2.Angle(from, to);
  789. angle = cross.z > 0 ? -angle : angle;
  790. angle = (angle + 360) % 360;
  791. return angle;
  792. }
  793. public static Vector3 GetPos(Vector3 center, float radius, float angle, bool isDegree = false)
  794. {
  795. angle = isDegree ? angle * Mathf.Deg2Rad : angle;
  796. return new Vector3(center.x + radius * Mathf.Sin(angle), center.y + radius * Mathf.Cos(angle));
  797. }
  798. public static Vector3 GetDire(float angle, bool isDegree = false)
  799. {
  800. angle = isDegree ? angle * Mathf.Deg2Rad : angle;
  801. return new Vector3(Mathf.Sin(angle), Mathf.Cos(angle));
  802. }
  803. public static Vector3 GetVertialDire(Vector3 dire)
  804. {
  805. if (dire.x == 0)
  806. {
  807. return new Vector3(-1, 0, 0);
  808. }
  809. if (dire.y == 0)
  810. {
  811. return new Vector3(0, -1, 0);
  812. }
  813. else
  814. {
  815. return new Vector3(-dire.y / dire.x, 1, 0).normalized;
  816. }
  817. }
  818. public static Vector3 GetLastValue(List<Vector3> list)
  819. {
  820. if (list.Count <= 0) return Vector3.zero;
  821. else return list[list.Count - 1];
  822. }
  823. public static void SetColorOpacity(ref Color32 color, float opacity)
  824. {
  825. if (color.a != 0 && opacity != 1)
  826. {
  827. color.a = (byte) (color.a * opacity);
  828. }
  829. }
  830. public static Color32 GetHighlightColor(Color32 color, float rate = 0.8f)
  831. {
  832. var newColor = color;
  833. newColor.r = (byte) (color.r * rate);
  834. newColor.g = (byte) (color.g * rate);
  835. newColor.b = (byte) (color.b * rate);
  836. return newColor;
  837. }
  838. public static Color32 GetBlurColor(Color32 color, float a = 0.3f)
  839. {
  840. var newColor = color;
  841. newColor.a = (byte) (a * 255);
  842. return newColor;
  843. }
  844. public static Color32 GetSelectColor(Color32 color, float rate = 0.8f)
  845. {
  846. var newColor = color;
  847. newColor.r = (byte) (color.r * rate);
  848. newColor.g = (byte) (color.g * rate);
  849. newColor.b = (byte) (color.b * rate);
  850. return newColor;
  851. }
  852. public static bool IsPointInQuadrilateral(Vector3 P, Vector3 A, Vector3 B, Vector3 C, Vector3 D)
  853. {
  854. Vector3 v0 = Vector3.Cross(A - D, P - D);
  855. Vector3 v1 = Vector3.Cross(B - A, P - A);
  856. Vector3 v2 = Vector3.Cross(C - B, P - B);
  857. Vector3 v3 = Vector3.Cross(D - C, P - C);
  858. if (Vector3.Dot(v0, v1) < 0 || Vector3.Dot(v0, v2) < 0 || Vector3.Dot(v0, v3) < 0)
  859. {
  860. return false;
  861. }
  862. else
  863. {
  864. return true;
  865. }
  866. }
  867. public static bool IsInRect(Vector3 pos, float xMin, float xMax, float yMin, float yMax)
  868. {
  869. return pos.x >= xMin && pos.x <= xMax && pos.y <= yMax && pos.y >= yMin;
  870. }
  871. public static bool IsColorAlphaZero(Color color)
  872. {
  873. return !ChartHelper.IsClearColor(color) && color.a == 0;
  874. }
  875. public static float GetActualValue(float valueOrRate, float total, float maxRate = 1.5f)
  876. {
  877. if (valueOrRate >= -maxRate && valueOrRate <= maxRate) return valueOrRate * total;
  878. else return valueOrRate;
  879. }
  880. #if UNITY_WEBGL
  881. [DllImport("__Internal")]
  882. private static extern void Download(string base64str, string fileName);
  883. #endif
  884. public static Texture2D SaveAsImage(RectTransform rectTransform, Canvas canvas, string imageType = "png", string path = "")
  885. {
  886. var cam = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
  887. var pos = RectTransformUtility.WorldToScreenPoint(cam, rectTransform.position);
  888. var width = rectTransform.rect.width * canvas.scaleFactor;
  889. var height = rectTransform.rect.height * canvas.scaleFactor;
  890. var posX = pos.x + rectTransform.rect.xMin * canvas.scaleFactor;
  891. var posY = pos.y + rectTransform.rect.yMin * canvas.scaleFactor;
  892. var rect = new Rect(posX, posY, width, height);
  893. var tex = new Texture2D((int) width, (int) height, TextureFormat.RGBA32, false);
  894. tex.ReadPixels(rect, 0, 0);
  895. tex.Apply();
  896. byte[] bytes;
  897. switch (imageType)
  898. {
  899. case "png":
  900. bytes = tex.EncodeToPNG();
  901. break;
  902. case "jpg":
  903. bytes = tex.EncodeToJPG();
  904. break;
  905. case "exr":
  906. bytes = tex.EncodeToEXR();
  907. break;
  908. default:
  909. Debug.LogError("SaveAsImage ERROR: not support image type:" + imageType);
  910. return null;
  911. }
  912. var fileName = rectTransform.name + "." + imageType;
  913. #if UNITY_WEBGL
  914. string base64str = Convert.ToBase64String(bytes);
  915. Download(base64str, fileName);
  916. Debug.Log("SaveAsImage: download by brower:" + fileName);
  917. return tex;
  918. #else
  919. if (string.IsNullOrEmpty(path))
  920. {
  921. var dir = Application.persistentDataPath + "/SavedImage";
  922. #if UNITY_EDITOR
  923. dir = Application.dataPath + "/../SavedImage";
  924. #else
  925. dir = Application.persistentDataPath + "/SavedImage";
  926. #endif
  927. if (!System.IO.Directory.Exists(dir))
  928. {
  929. System.IO.Directory.CreateDirectory(dir);
  930. }
  931. path = dir + "/" + fileName;
  932. }
  933. System.IO.File.WriteAllBytes(path, bytes);
  934. Debug.Log("SaveAsImage:" + path);
  935. return tex;
  936. #endif
  937. }
  938. }
  939. }