ChartHelper.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  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 = EnsureComponent<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 void SetBackground(Image background, Background imageStyle)
  343. {
  344. if (background == null) return;
  345. if (imageStyle.show)
  346. {
  347. background.gameObject.SetActive(true);
  348. background.sprite = imageStyle.image;
  349. background.color = imageStyle.imageColor;
  350. background.type = imageStyle.imageType;
  351. if (imageStyle.imageWidth > 0 && imageStyle.imageHeight > 0)
  352. {
  353. background.rectTransform.sizeDelta = new Vector2(imageStyle.imageWidth, imageStyle.imageHeight);
  354. }
  355. }
  356. else
  357. {
  358. background.sprite = null;
  359. background.color = Color.clear;
  360. background.gameObject.SetActive(false);
  361. }
  362. }
  363. public static ChartLabel AddAxisLabelObject(int total, int index, string name, Transform parent,
  364. Vector2 sizeDelta, Axis axis, ComponentTheme theme,
  365. string content, Color autoColor, TextAnchor autoAlignment = TextAnchor.MiddleCenter, Color32 iconDefaultColor = default(Color32))
  366. {
  367. var textStyle = axis.axisLabel.textStyle;
  368. var label = AddChartLabel(name, parent, axis.axisLabel, theme, content, autoColor, autoAlignment);
  369. var labelShow = axis.IsNeedShowLabel(index, total);
  370. label.UpdateIcon(axis.axisLabel.icon, axis.GetIcon(index), iconDefaultColor);
  371. label.text.SetActive(labelShow);
  372. return label;
  373. }
  374. public static ChartLabel AddChartLabel(string name, Transform parent, LabelStyle labelStyle,
  375. ComponentTheme theme, string content, Color autoColor, TextAnchor autoAlignment = TextAnchor.MiddleCenter)
  376. {
  377. Vector2 anchorMin, anchorMax, pivot;
  378. var sizeDelta = new Vector2(labelStyle.width, labelStyle.height);
  379. var textStyle = labelStyle.textStyle;
  380. var alignment = textStyle.GetAlignment(autoAlignment);
  381. UpdateAnchorAndPivotByTextAlignment(alignment, out anchorMin, out anchorMax, out pivot);
  382. var labelObj = AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
  383. //ChartHelper.RemoveComponent<Text>(labelObj);
  384. var label = EnsureComponent<ChartLabel>(labelObj);
  385. label.text = AddTextObject("Text", label.gameObject.transform, anchorMin, anchorMax, pivot,
  386. sizeDelta, textStyle, theme, autoColor, autoAlignment, label.text);
  387. label.icon = ChartHelper.AddIcon("Icon", label.gameObject.transform, labelStyle.icon);
  388. label.SetSize(labelStyle.width, labelStyle.height);
  389. label.SetTextPadding(labelStyle.textPadding);
  390. label.SetText(content);
  391. label.UpdateIcon(labelStyle.icon);
  392. if (labelStyle.background.show)
  393. {
  394. label.color = (!labelStyle.background.autoColor || autoColor == Color.clear) ?
  395. labelStyle.background.color : autoColor;
  396. label.sprite = labelStyle.background.sprite;
  397. label.type = labelStyle.background.type;
  398. }
  399. else
  400. {
  401. label.color = Color.clear;
  402. label.sprite = null;
  403. }
  404. label.transform.localEulerAngles = new Vector3(0, 0, labelStyle.rotate);
  405. label.transform.localPosition = labelStyle.offset;
  406. return label;
  407. }
  408. public static ChartLabel AddChartLabel2(string name, Transform parent, LabelStyle labelStyle,
  409. ComponentTheme theme, string content, Color autoColor, TextAnchor autoAlignment = TextAnchor.MiddleCenter)
  410. {
  411. Vector2 anchorMin, anchorMax, pivot;
  412. var sizeDelta = new Vector2(labelStyle.width, labelStyle.height);
  413. var textStyle = labelStyle.textStyle;
  414. var alignment = textStyle.GetAlignment(autoAlignment);
  415. UpdateAnchorAndPivotByTextAlignment(alignment, out anchorMin, out anchorMax, out pivot);
  416. var vector0_5 = new Vector2(0.5f, 0.5f);
  417. var labelObj = AddObject(name, parent, vector0_5, vector0_5, vector0_5, sizeDelta);
  418. var label = EnsureComponent<ChartLabel>(labelObj);
  419. label.text = AddTextObject("Text", label.gameObject.transform, anchorMin, anchorMax, pivot,
  420. sizeDelta, textStyle, theme, autoColor, autoAlignment, label.text);
  421. label.icon = ChartHelper.AddIcon("Icon", label.gameObject.transform, labelStyle.icon);
  422. label.SetSize(labelStyle.width, labelStyle.height);
  423. label.SetTextPadding(labelStyle.textPadding);
  424. label.SetText(content);
  425. label.UpdateIcon(labelStyle.icon);
  426. if (labelStyle.background.show)
  427. {
  428. label.color = (!labelStyle.background.autoColor || autoColor == Color.clear) ?
  429. labelStyle.background.color : autoColor;
  430. label.sprite = labelStyle.background.sprite;
  431. if(label.type != labelStyle.background.type)
  432. label.type = labelStyle.background.type;
  433. }
  434. else
  435. {
  436. label.color = Color.clear;
  437. label.sprite = null;
  438. }
  439. label.transform.localEulerAngles = new Vector3(0, 0, labelStyle.rotate);
  440. label.transform.localPosition = labelStyle.offset;
  441. return label;
  442. }
  443. private static void UpdateAnchorAndPivotByTextAlignment(TextAnchor alignment, out Vector2 anchorMin, out Vector2 anchorMax,
  444. out Vector2 pivot)
  445. {
  446. switch (alignment)
  447. {
  448. case TextAnchor.LowerLeft:
  449. anchorMin = new Vector2(0f, 0f);
  450. anchorMax = new Vector2(0f, 0f);
  451. pivot = new Vector2(0f, 0f);
  452. break;
  453. case TextAnchor.UpperLeft:
  454. anchorMin = new Vector2(0f, 1f);
  455. anchorMax = new Vector2(0f, 1f);
  456. pivot = new Vector2(0f, 1f);
  457. break;
  458. case TextAnchor.MiddleLeft:
  459. anchorMin = new Vector2(0f, 0.5f);
  460. anchorMax = new Vector2(0f, 0.5f);
  461. pivot = new Vector2(0f, 0.5f);
  462. break;
  463. case TextAnchor.LowerRight:
  464. anchorMin = new Vector2(1f, 0f);
  465. anchorMax = new Vector2(1f, 0f);
  466. pivot = new Vector2(1f, 0f);
  467. break;
  468. case TextAnchor.UpperRight:
  469. anchorMin = new Vector2(1f, 1f);
  470. anchorMax = new Vector2(1f, 1f);
  471. pivot = new Vector2(1f, 1f);
  472. break;
  473. case TextAnchor.MiddleRight:
  474. anchorMin = new Vector2(1, 0.5f);
  475. anchorMax = new Vector2(1, 0.5f);
  476. pivot = new Vector2(1, 0.5f);
  477. break;
  478. case TextAnchor.LowerCenter:
  479. anchorMin = new Vector2(0.5f, 0f);
  480. anchorMax = new Vector2(0.5f, 0f);
  481. pivot = new Vector2(0.5f, 0f);
  482. break;
  483. case TextAnchor.UpperCenter:
  484. anchorMin = new Vector2(0.5f, 1f);
  485. anchorMax = new Vector2(0.5f, 1f);
  486. pivot = new Vector2(0.5f, 1f);
  487. break;
  488. case TextAnchor.MiddleCenter:
  489. anchorMin = new Vector2(0.5f, 0.5f);
  490. anchorMax = new Vector2(0.5f, 0.5f);
  491. pivot = new Vector2(0.5f, 0.5f);
  492. break;
  493. default:
  494. anchorMin = new Vector2(0.5f, 0.5f);
  495. anchorMax = new Vector2(0.5f, 0.5f);
  496. pivot = new Vector2(0.5f, 0.5f);
  497. break;
  498. }
  499. }
  500. internal static ChartLabel AddTooltipIndicatorLabel(Tooltip tooltip, string name, Transform parent,
  501. ThemeStyle theme, TextAnchor alignment, LabelStyle labelStyle)
  502. {
  503. var label = ChartHelper.AddChartLabel(name, parent, labelStyle, theme.tooltip,
  504. "", Color.clear, alignment);
  505. label.SetActive(tooltip.show && labelStyle.show);
  506. return label;
  507. }
  508. public static void GetPointList(ref List<Vector3> posList, Vector3 sp, Vector3 ep, float k = 30f)
  509. {
  510. Vector3 dir = (ep - sp).normalized;
  511. float dist = Vector3.Distance(sp, ep);
  512. int segment = (int)(dist / k);
  513. posList.Clear();
  514. posList.Add(sp);
  515. for (int i = 1; i < segment; i++)
  516. {
  517. posList.Add(sp + dir * dist * i / segment);
  518. }
  519. posList.Add(ep);
  520. }
  521. public static bool IsValueEqualsColor(Color32 color1, Color32 color2)
  522. {
  523. return color1.a == color2.a &&
  524. color1.b == color2.b &&
  525. color1.g == color2.g &&
  526. color1.r == color2.r;
  527. }
  528. public static bool IsValueEqualsColor(Color color1, Color color2)
  529. {
  530. return color1.a == color2.a &&
  531. color1.b == color2.b &&
  532. color1.g == color2.g &&
  533. color1.r == color2.r;
  534. }
  535. public static bool IsValueEqualsString(string str1, string str2)
  536. {
  537. if (str1 == null && str2 == null) return true;
  538. else if (str1 != null && str2 != null) return str1.Equals(str2);
  539. else return false;
  540. }
  541. public static bool IsValueEqualsVector2(Vector2 v1, Vector2 v2)
  542. {
  543. return v1.x == v2.x && v1.y == v2.y;
  544. }
  545. public static bool IsValueEqualsVector3(Vector3 v1, Vector3 v2)
  546. {
  547. return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
  548. }
  549. public static bool IsValueEqualsList<T>(List<T> list1, List<T> list2)
  550. {
  551. if (list1 == null || list2 == null) return false;
  552. if (list1.Count != list2.Count) return false;
  553. for (int i = 0; i < list1.Count; i++)
  554. {
  555. if (list1[i] == null && list2[i] == null) { }
  556. else
  557. {
  558. if (list1[i] != null)
  559. {
  560. if (!list1[i].Equals(list2[i])) return false;
  561. }
  562. else
  563. {
  564. if (!list2[i].Equals(list1[i])) return false;
  565. }
  566. }
  567. }
  568. return true;
  569. }
  570. public static bool IsEquals(double d1, double d2)
  571. {
  572. return Math.Abs(d1 - d2) < 0.000001d;
  573. }
  574. public static bool IsEquals(float d1, float d2)
  575. {
  576. return Math.Abs(d1 - d2) < 0.000001f;
  577. }
  578. public static bool IsClearColor(Color32 color)
  579. {
  580. return color.a == 0 && color.b == 0 && color.g == 0 && color.r == 0;
  581. }
  582. public static bool IsClearColor(Color color)
  583. {
  584. return color.a == 0 && color.b == 0 && color.g == 0 && color.r == 0;
  585. }
  586. public static bool IsZeroVector(Vector3 pos)
  587. {
  588. return pos.x == 0 && pos.y == 0 && pos.z == 0;
  589. }
  590. public static bool CopyList<T>(List<T> toList, List<T> fromList)
  591. {
  592. if (toList == null || fromList == null) return false;
  593. toList.Clear();
  594. foreach (var item in fromList) toList.Add(item);
  595. return true;
  596. }
  597. public static bool CopyArray<T>(T[] toList, T[] fromList)
  598. {
  599. if (toList == null || fromList == null) return false;
  600. if (toList.Length != fromList.Length)
  601. {
  602. toList = new T[fromList.Length];
  603. }
  604. for (int i = 0; i < fromList.Length; i++) toList[i] = fromList[i];
  605. return true;
  606. }
  607. public static List<float> ParseFloatFromString(string jsonData)
  608. {
  609. List<float> list = new List<float>();
  610. if (string.IsNullOrEmpty(jsonData)) return list;
  611. int startIndex = jsonData.IndexOf("[");
  612. int endIndex = jsonData.IndexOf("]");
  613. string temp = jsonData.Substring(startIndex + 1, endIndex - startIndex - 1);
  614. if (temp.IndexOf("],") > -1 || temp.IndexOf("] ,") > -1)
  615. {
  616. string[] datas = temp.Split(new string[] { "],", "] ," }, StringSplitOptions.RemoveEmptyEntries);
  617. for (int i = 0; i < datas.Length; i++)
  618. {
  619. temp = datas[i];
  620. }
  621. return list;
  622. }
  623. else
  624. {
  625. string[] datas = temp.Split(',');
  626. for (int i = 0; i < datas.Length; i++)
  627. {
  628. list.Add(float.Parse(datas[i].Trim()));
  629. }
  630. return list;
  631. }
  632. }
  633. public static List<string> ParseStringFromString(string jsonData)
  634. {
  635. List<string> list = new List<string>();
  636. if (string.IsNullOrEmpty(jsonData)) return list;
  637. string pattern = "[\"'](.*?)[\"']";
  638. if (Regex.IsMatch(jsonData, pattern))
  639. {
  640. MatchCollection m = Regex.Matches(jsonData, pattern);
  641. foreach (Match match in m)
  642. {
  643. list.Add(match.Groups[1].Value);
  644. }
  645. }
  646. return list;
  647. }
  648. public static Color32 GetColor(string hexColorStr)
  649. {
  650. Color color;
  651. ColorUtility.TryParseHtmlString(hexColorStr, out color);
  652. return (Color32)color;
  653. }
  654. public static double GetMaxDivisibleValue(double max, double ceilRate)
  655. {
  656. if (max == 0) return 0;
  657. double pow = 1;
  658. if (max > -1 && max < 1)
  659. {
  660. pow = Mathf.Pow(10, MathUtil.GetPrecision(max));
  661. max *= pow;
  662. }
  663. if (ceilRate == 0)
  664. {
  665. var bigger = Math.Ceiling(Math.Abs(max));
  666. int n = 1;
  667. while (bigger / (Mathf.Pow(10, n)) > 10)
  668. {
  669. n++;
  670. }
  671. double mm = bigger;
  672. var pown = Mathf.Pow(10, n);
  673. var powmax = Mathf.Pow(10, n + 1);
  674. var aliquot = mm % pown == 0;
  675. if (mm > 10 && n < 38)
  676. {
  677. mm = bigger - bigger % pown;
  678. if (!aliquot)
  679. mm += max > 0 ? pown : -pown;
  680. }
  681. var mmm = mm;
  682. if (max > 100 && !aliquot && (max / mm < 0.8f))
  683. mmm -= Mathf.Pow(10, n) / 2;
  684. if (mmm >= (powmax - pown) && mmm < powmax)
  685. mmm = powmax;
  686. if (max < 0) return -Math.Ceiling(mmm > -max ? mmm : mm);
  687. else return Math.Ceiling(mmm > max ? mmm : mm) / pow;
  688. }
  689. else
  690. {
  691. return GetMaxCeilRate(max, ceilRate) / pow;
  692. }
  693. }
  694. public static double GetMaxCeilRate(double value, double ceilRate)
  695. {
  696. if (ceilRate == 0) return value;
  697. var mod = value % ceilRate;
  698. int rate = (int)(value / ceilRate);
  699. return mod == 0 ? value : (value < 0 ? rate : rate + 1) * ceilRate;
  700. }
  701. public static double GetMinCeilRate(double value, double ceilRate)
  702. {
  703. if (ceilRate == 0) return value;
  704. var mod = value % ceilRate;
  705. int rate = (int)(value / ceilRate);
  706. return mod == 0 ? value : (value < 0 ? rate - 1 : rate) * ceilRate;
  707. }
  708. public static double GetMinDivisibleValue(double min, double ceilRate)
  709. {
  710. if (min == 0) return 0;
  711. double pow = 1;
  712. if (min > -1 && min < 1)
  713. {
  714. pow = Mathf.Pow(10, MathUtil.GetPrecision(min));
  715. min *= pow;
  716. }
  717. if (ceilRate == 0)
  718. {
  719. var bigger = min < 0 ? Math.Ceiling(Math.Abs(min)) : Math.Floor(Math.Abs(min));
  720. int n = 1;
  721. while (bigger / (Mathf.Pow(10, n)) > 10)
  722. {
  723. n++;
  724. }
  725. double mm = bigger;
  726. if (mm > 10 && n < 38)
  727. {
  728. mm = bigger - bigger % (Mathf.Pow(10, n));
  729. mm += min < 0 ? Mathf.Pow(10, n) : -Mathf.Pow(10, n);
  730. }
  731. if (min < 0) return -Math.Floor(mm) / pow;
  732. else return Math.Floor(mm) / pow;
  733. }
  734. else
  735. {
  736. return GetMinCeilRate(min, ceilRate) / pow;
  737. }
  738. }
  739. public static double GetMaxLogValue(double value, float logBase, bool isLogBaseE, out int splitNumber)
  740. {
  741. splitNumber = 1;
  742. if (value <= 0) return 0;
  743. double max = isLogBaseE ? Math.Exp(splitNumber) : Math.Pow(logBase, splitNumber);
  744. while (max < value)
  745. {
  746. splitNumber++;
  747. max = isLogBaseE ? Math.Exp(splitNumber) : Math.Pow(logBase, splitNumber);
  748. }
  749. return max;
  750. }
  751. public static double GetMinLogValue(double value, float logBase, bool isLogBaseE, out int splitNumber)
  752. {
  753. splitNumber = 0;
  754. if (value <= 0) return 0;
  755. if (value > 1) return 1;
  756. double min = isLogBaseE ? Math.Exp(-splitNumber) : Math.Pow(logBase, -splitNumber);
  757. while (min > value)
  758. {
  759. splitNumber++;
  760. min = isLogBaseE ? Math.Exp(-splitNumber) : Math.Pow(logBase, -splitNumber);
  761. }
  762. return min;
  763. }
  764. public static void AddEventListener(GameObject obj, EventTriggerType type,
  765. UnityEngine.Events.UnityAction<BaseEventData> call)
  766. {
  767. EventTrigger trigger = EnsureComponent<EventTrigger>(obj.gameObject);
  768. EventTrigger.Entry entry = new EventTrigger.Entry();
  769. entry.eventID = type;
  770. entry.callback = new EventTrigger.TriggerEvent();
  771. entry.callback.AddListener(call);
  772. trigger.triggers.Add(entry);
  773. }
  774. public static void ClearEventListener(GameObject obj)
  775. {
  776. EventTrigger trigger = obj.GetComponent<EventTrigger>();
  777. if (trigger != null)
  778. {
  779. trigger.triggers.Clear();
  780. }
  781. }
  782. public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
  783. {
  784. Vector3 point = Quaternion.AngleAxis(angle, axis) * (position - center);
  785. Vector3 resultVec3 = center + point;
  786. return resultVec3;
  787. }
  788. public static Vector3 GetPosition(Vector3 center, float angle, float radius)
  789. {
  790. var rad = angle * Mathf.Deg2Rad;
  791. var px = Mathf.Sin(rad) * radius;
  792. var py = Mathf.Cos(rad) * radius;
  793. return center + new Vector3(px, py);
  794. }
  795. /// <summary>
  796. /// 获得0-360的角度(12点钟方向为0度)
  797. /// </summary>
  798. /// <param name="from"></param>
  799. /// <param name="to"></param>
  800. /// <returns></returns>
  801. public static float GetAngle360(Vector2 from, Vector2 to)
  802. {
  803. float angle;
  804. Vector3 cross = Vector3.Cross(from, to);
  805. angle = Vector2.Angle(from, to);
  806. angle = cross.z > 0 ? -angle : angle;
  807. angle = (angle + 360) % 360;
  808. return angle;
  809. }
  810. public static Vector3 GetPos(Vector3 center, float radius, float angle, bool isDegree = false)
  811. {
  812. angle = isDegree ? angle * Mathf.Deg2Rad : angle;
  813. return new Vector3(center.x + radius * Mathf.Sin(angle), center.y + radius * Mathf.Cos(angle));
  814. }
  815. public static Vector3 GetDire(float angle, bool isDegree = false)
  816. {
  817. angle = isDegree ? angle * Mathf.Deg2Rad : angle;
  818. return new Vector3(Mathf.Sin(angle), Mathf.Cos(angle));
  819. }
  820. public static Vector3 GetVertialDire(Vector3 dire)
  821. {
  822. if (dire.x == 0)
  823. {
  824. return new Vector3(-1, 0, 0);
  825. }
  826. if (dire.y == 0)
  827. {
  828. return new Vector3(0, -1, 0);
  829. }
  830. else
  831. {
  832. return new Vector3(-dire.y / dire.x, 1, 0).normalized;
  833. }
  834. }
  835. public static Vector3 GetLastValue(List<Vector3> list)
  836. {
  837. if (list.Count <= 0) return Vector3.zero;
  838. else return list[list.Count - 1];
  839. }
  840. public static void SetColorOpacity(ref Color32 color, float opacity)
  841. {
  842. if (color.a != 0 && opacity != 1)
  843. {
  844. color.a = (byte)(color.a * opacity);
  845. }
  846. }
  847. public static Color32 GetHighlightColor(Color32 color, float rate = 0.8f)
  848. {
  849. var newColor = color;
  850. newColor.r = (byte)(color.r * rate);
  851. newColor.g = (byte)(color.g * rate);
  852. newColor.b = (byte)(color.b * rate);
  853. return newColor;
  854. }
  855. public static Color32 GetBlurColor(Color32 color, float a = 0.3f)
  856. {
  857. var newColor = color;
  858. newColor.a = (byte)(a * 255);
  859. return newColor;
  860. }
  861. public static Color32 GetSelectColor(Color32 color, float rate = 0.8f)
  862. {
  863. var newColor = color;
  864. newColor.r = (byte)(color.r * rate);
  865. newColor.g = (byte)(color.g * rate);
  866. newColor.b = (byte)(color.b * rate);
  867. return newColor;
  868. }
  869. public static bool IsPointInQuadrilateral(Vector3 P, Vector3 A, Vector3 B, Vector3 C, Vector3 D)
  870. {
  871. Vector3 v0 = Vector3.Cross(A - D, P - D);
  872. Vector3 v1 = Vector3.Cross(B - A, P - A);
  873. Vector3 v2 = Vector3.Cross(C - B, P - B);
  874. Vector3 v3 = Vector3.Cross(D - C, P - C);
  875. if (Vector3.Dot(v0, v1) < 0 || Vector3.Dot(v0, v2) < 0 || Vector3.Dot(v0, v3) < 0)
  876. {
  877. return false;
  878. }
  879. else
  880. {
  881. return true;
  882. }
  883. }
  884. public static bool IsInRect(Vector3 pos, float xMin, float xMax, float yMin, float yMax)
  885. {
  886. return pos.x >= xMin && pos.x <= xMax && pos.y <= yMax && pos.y >= yMin;
  887. }
  888. public static bool IsColorAlphaZero(Color color)
  889. {
  890. return !ChartHelper.IsClearColor(color) && color.a == 0;
  891. }
  892. public static float GetActualValue(float valueOrRate, float total, float maxRate = 1.5f)
  893. {
  894. if (valueOrRate >= -maxRate && valueOrRate <= maxRate) return valueOrRate * total;
  895. else return valueOrRate;
  896. }
  897. #if UNITY_WEBGL
  898. [DllImport("__Internal")]
  899. private static extern void Download(string base64str, string fileName);
  900. #endif
  901. public static Texture2D SaveAsImage(RectTransform rectTransform, Canvas canvas, string imageType = "png", string path = "")
  902. {
  903. var cam = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
  904. var pos = RectTransformUtility.WorldToScreenPoint(cam, rectTransform.position);
  905. var width = rectTransform.rect.width * canvas.scaleFactor;
  906. var height = rectTransform.rect.height * canvas.scaleFactor;
  907. var posX = pos.x + rectTransform.rect.xMin * canvas.scaleFactor;
  908. var posY = pos.y + rectTransform.rect.yMin * canvas.scaleFactor;
  909. var rect = new Rect(posX, posY, width, height);
  910. var tex = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false);
  911. tex.ReadPixels(rect, 0, 0);
  912. tex.Apply();
  913. byte[] bytes;
  914. switch (imageType)
  915. {
  916. case "png":
  917. bytes = tex.EncodeToPNG();
  918. break;
  919. case "jpg":
  920. bytes = tex.EncodeToJPG();
  921. break;
  922. case "exr":
  923. bytes = tex.EncodeToEXR();
  924. break;
  925. default:
  926. Debug.LogError("SaveAsImage ERROR: not support image type:" + imageType);
  927. return null;
  928. }
  929. var fileName = rectTransform.name + "." + imageType;
  930. #if UNITY_WEBGL
  931. string base64str = Convert.ToBase64String(bytes);
  932. Download(base64str, fileName);
  933. Debug.Log("SaveAsImage: download by brower:" + fileName);
  934. return tex;
  935. #else
  936. if (string.IsNullOrEmpty(path))
  937. {
  938. var dir = Application.persistentDataPath + "/SavedImage";
  939. #if UNITY_EDITOR
  940. dir = Application.dataPath + "/../SavedImage";
  941. #else
  942. dir = Application.persistentDataPath + "/SavedImage";
  943. #endif
  944. if (!System.IO.Directory.Exists(dir))
  945. {
  946. System.IO.Directory.CreateDirectory(dir);
  947. }
  948. path = dir + "/" + fileName;
  949. }
  950. System.IO.File.WriteAllBytes(path, bytes);
  951. Debug.Log("SaveAsImage:" + path);
  952. return tex;
  953. #endif
  954. }
  955. }
  956. }