暫無描述
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

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