DrawSerieLiquid.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /************************************************/
  2. /* */
  3. /* Copyright (c) 2018 - 2021 monitor1394 */
  4. /* https://github.com/monitor1394 */
  5. /* */
  6. /************************************************/
  7. using UnityEngine;
  8. using UnityEngine.UI;
  9. using UnityEngine.EventSystems;
  10. using XUGL;
  11. namespace XCharts
  12. {
  13. internal class DrawSerieLiquid : IDrawSerie
  14. {
  15. public BaseChart chart;
  16. private bool m_UpdateLabelText = false;
  17. public DrawSerieLiquid(BaseChart chart)
  18. {
  19. this.chart = chart;
  20. }
  21. public void InitComponent()
  22. {
  23. //UpdateRuntimeData();
  24. //SerieLabelHelper.UpdateLabelText(chart.series, chart.theme, m_LegendRealShowName);
  25. }
  26. public void CheckComponent()
  27. {
  28. }
  29. public void Update()
  30. {
  31. if (m_UpdateLabelText)
  32. {
  33. m_UpdateLabelText = false;
  34. foreach (var serie in chart.series.list)
  35. {
  36. if (serie.type == SerieType.Liquid)
  37. {
  38. var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
  39. SerieLabelHelper.SetLiquidLabelText(serie, chart.theme, colorIndex);
  40. }
  41. }
  42. }
  43. }
  44. public void DrawBase(VertexHelper vh)
  45. {
  46. }
  47. public void DrawSerie(VertexHelper vh, Serie serie)
  48. {
  49. if (serie.type != SerieType.Liquid) return;
  50. UpdateRuntimeData(serie);
  51. DrawVesselBackground(vh, serie);
  52. DrawLiquid(vh, serie);
  53. DrawVessel(vh, serie);
  54. }
  55. public void RefreshLabel()
  56. {
  57. }
  58. public bool CheckTootipArea(Vector2 local)
  59. {
  60. return false;
  61. }
  62. public bool OnLegendButtonClick(int index, string legendName, bool show)
  63. {
  64. return false;
  65. }
  66. public bool OnLegendButtonEnter(int index, string legendName)
  67. {
  68. return false;
  69. }
  70. public bool OnLegendButtonExit(int index, string legendName)
  71. {
  72. return false;
  73. }
  74. public void OnPointerDown(PointerEventData eventData)
  75. {
  76. }
  77. private void UpdateRuntimeData()
  78. {
  79. foreach (var vessel in chart.vessels)
  80. {
  81. VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
  82. }
  83. }
  84. private void UpdateRuntimeData(Serie serie)
  85. {
  86. var vessel = chart.GetVessel(serie.vesselIndex);
  87. if (vessel != null)
  88. {
  89. VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
  90. }
  91. }
  92. private void DrawVesselBackground(VertexHelper vh, Serie serie)
  93. {
  94. var vessel = chart.GetVessel(serie.vesselIndex);
  95. if (vessel != null)
  96. {
  97. if (vessel.backgroundColor.a != 0)
  98. {
  99. switch (vessel.shape)
  100. {
  101. case Vessel.Shape.Circle:
  102. var cenPos = vessel.runtimeCenterPos;
  103. var radius = vessel.runtimeRadius;
  104. UGL.DrawCricle(vh, cenPos, vessel.runtimeInnerRadius + vessel.gap, vessel.backgroundColor,
  105. chart.settings.cicleSmoothness);
  106. UGL.DrawDoughnut(vh, cenPos, vessel.runtimeInnerRadius, vessel.runtimeInnerRadius + vessel.gap,
  107. vessel.backgroundColor, Color.clear, chart.settings.cicleSmoothness);
  108. break;
  109. case Vessel.Shape.Rect:
  110. UGL.DrawRectangle(vh, vessel.runtimeCenterPos, vessel.runtimeWidth / 2, vessel.runtimeHeight / 2,
  111. vessel.backgroundColor);
  112. break;
  113. default:
  114. break;
  115. }
  116. }
  117. }
  118. }
  119. private void DrawVessel(VertexHelper vh, Serie serie)
  120. {
  121. var vessel = chart.GetVessel(serie.vesselIndex);
  122. if (vessel != null)
  123. {
  124. switch (vessel.shape)
  125. {
  126. case Vessel.Shape.Circle:
  127. DrawCirleVessel(vh, vessel);
  128. break;
  129. case Vessel.Shape.Rect:
  130. DrawRectVessel(vh, vessel);
  131. break;
  132. default:
  133. DrawCirleVessel(vh, vessel);
  134. break;
  135. }
  136. }
  137. }
  138. private void DrawCirleVessel(VertexHelper vh, Vessel vessel)
  139. {
  140. var cenPos = vessel.runtimeCenterPos;
  141. var radius = vessel.runtimeRadius;
  142. var serie = SeriesHelper.GetSerieByVesselIndex(chart.series, vessel.index);
  143. var vesselColor = VesselHelper.GetColor(vessel, serie, chart.theme, chart.m_LegendRealShowName);
  144. if (vessel.gap != 0)
  145. {
  146. UGL.DrawDoughnut(vh, cenPos, vessel.runtimeInnerRadius, vessel.runtimeInnerRadius + vessel.gap,
  147. vessel.backgroundColor, Color.clear, chart.settings.cicleSmoothness);
  148. }
  149. UGL.DrawDoughnut(vh, cenPos, radius - vessel.shapeWidth, radius, vesselColor, Color.clear,
  150. chart.settings.cicleSmoothness);
  151. }
  152. private void DrawRectVessel(VertexHelper vh, Vessel vessel)
  153. {
  154. var serie = SeriesHelper.GetSerieByVesselIndex(chart.series, vessel.index);
  155. var vesselColor = VesselHelper.GetColor(vessel, serie, chart.theme, chart.m_LegendRealShowName);
  156. if (vessel.gap != 0)
  157. {
  158. UGL.DrawBorder(vh, vessel.runtimeCenterPos, vessel.runtimeWidth,
  159. vessel.runtimeHeight, vessel.gap, vessel.backgroundColor, 0, vessel.cornerRadius);
  160. }
  161. UGL.DrawBorder(vh, vessel.runtimeCenterPos, vessel.runtimeWidth + 2 * vessel.gap,
  162. vessel.runtimeHeight + 2 * vessel.gap, vessel.shapeWidth, vesselColor, 0, vessel.cornerRadius);
  163. }
  164. private void DrawLiquid(VertexHelper vh, Serie serie)
  165. {
  166. if (!serie.show) return;
  167. if (serie.animation.HasFadeOut()) return;
  168. var vessel = chart.GetVessel(serie.vesselIndex);
  169. if (vessel == null) return;
  170. switch (vessel.shape)
  171. {
  172. case Vessel.Shape.Circle:
  173. DrawCirleLiquid(vh, serie, vessel);
  174. break;
  175. case Vessel.Shape.Rect:
  176. DrawRectLiquid(vh, serie, vessel);
  177. break;
  178. default:
  179. DrawCirleLiquid(vh, serie, vessel);
  180. break;
  181. }
  182. }
  183. private void DrawCirleLiquid(VertexHelper vh, Serie serie, Vessel vessel)
  184. {
  185. var cenPos = vessel.runtimeCenterPos;
  186. var radius = vessel.runtimeInnerRadius;
  187. var serieData = serie.GetSerieData(0);
  188. if (serieData == null) return;
  189. var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  190. var value = serieData.GetCurrData(1, dataChangeDuration);
  191. if (serie.runtimeCheckValue != value)
  192. {
  193. serie.runtimeCheckValue = value;
  194. m_UpdateLabelText = true;
  195. }
  196. if (serieData.labelPosition != cenPos)
  197. {
  198. serieData.labelPosition = cenPos;
  199. m_UpdateLabelText = true;
  200. }
  201. if (value <= 0) return;
  202. var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
  203. var realHig = (float)((value - serie.min) / (serie.max - serie.min) * radius * 2);
  204. serie.animation.InitProgress(1, 0, realHig);
  205. var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail();
  206. var a = Mathf.Abs(radius - hig + (hig > radius ? serie.waveHeight : -serie.waveHeight));
  207. var diff = Mathf.Sqrt(radius * radius - Mathf.Pow(a, 2));
  208. var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
  209. var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
  210. var isNeedGradient = !ChartHelper.IsValueEqualsColor(color, toColor);
  211. var isFull = hig >= 2 * radius;
  212. if (hig >= 2 * radius) hig = 2 * radius;
  213. if (isFull && !isNeedGradient)
  214. {
  215. UGL.DrawCricle(vh, cenPos, radius, toColor, chart.settings.cicleSmoothness);
  216. }
  217. else
  218. {
  219. var startY = cenPos.y - radius + hig;
  220. var waveStartPos = new Vector3(cenPos.x - diff, startY);
  221. var waveEndPos = new Vector3(cenPos.x + diff, startY);
  222. var startX = hig > radius ? cenPos.x - radius : waveStartPos.x;
  223. var endX = hig > radius ? cenPos.x + radius : waveEndPos.x;
  224. var step = vessel.smoothness;
  225. if (step < 0.5f) step = 0.5f;
  226. var lup = hig > radius ? new Vector3(cenPos.x - radius, cenPos.y) : waveStartPos;
  227. var ldp = lup;
  228. var nup = Vector3.zero;
  229. var ndp = Vector3.zero;
  230. var angle = 0f;
  231. serie.runtimeWaveSpeed += serie.waveSpeed * Time.deltaTime;
  232. var isStarted = false;
  233. var isEnded = false;
  234. var waveHeight = isFull ? 0 : serie.waveHeight;
  235. while (startX < endX)
  236. {
  237. startX += step;
  238. if (startX > endX) startX = endX;
  239. if (startX > waveStartPos.x && !isStarted)
  240. {
  241. startX = waveStartPos.x;
  242. isStarted = true;
  243. }
  244. if (startX > waveEndPos.x && !isEnded)
  245. {
  246. startX = waveEndPos.x;
  247. isEnded = true;
  248. }
  249. var py = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2));
  250. if (startX < waveStartPos.x || startX > waveEndPos.x)
  251. {
  252. nup = new Vector3(startX, cenPos.y + py);
  253. }
  254. else
  255. {
  256. var py2 = waveHeight * Mathf.Sin(1 / serie.waveLength * angle + serie.runtimeWaveSpeed + serie.waveOffset);
  257. var nupY = waveStartPos.y + py2;
  258. if (nupY > cenPos.y + py) nupY = cenPos.y + py;
  259. else if (nupY < cenPos.y - py) nupY = cenPos.y - py;
  260. nup = new Vector3(startX, nupY);
  261. angle += step;
  262. }
  263. ndp = new Vector3(startX, cenPos.y - py);
  264. if (!ChartHelper.IsValueEqualsColor(color, toColor))
  265. {
  266. var colorMin = cenPos.y - radius;
  267. var colorMax = startY + serie.waveHeight;
  268. var tcolor1 = Color32.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin));
  269. var tcolor2 = Color32.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin));
  270. UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, tcolor1, tcolor2);
  271. }
  272. else
  273. {
  274. UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, color);
  275. }
  276. lup = nup;
  277. ldp = ndp;
  278. }
  279. }
  280. if (serie.waveSpeed != 0 && Application.isPlaying && !isFull)
  281. {
  282. chart.RefreshPainter(serie);
  283. }
  284. if (!serie.animation.IsFinish())
  285. {
  286. serie.animation.CheckProgress(realHig);
  287. chart.m_IsPlayingAnimation = true;
  288. chart.RefreshPainter(serie);
  289. }
  290. }
  291. private void DrawRectLiquid(VertexHelper vh, Serie serie, Vessel vessel)
  292. {
  293. var cenPos = vessel.runtimeCenterPos;
  294. var serieData = serie.GetSerieData(0);
  295. if (serieData == null) return;
  296. var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  297. var value = serieData.GetCurrData(1, dataChangeDuration);
  298. if (serie.runtimeCheckValue != value)
  299. {
  300. serie.runtimeCheckValue = value;
  301. m_UpdateLabelText = true;
  302. }
  303. if (serieData.labelPosition != cenPos)
  304. {
  305. serieData.labelPosition = cenPos;
  306. m_UpdateLabelText = true;
  307. }
  308. if (value <= 0) return;
  309. var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
  310. var realHig = (value - serie.min) / (serie.max - serie.min) * vessel.runtimeHeight;
  311. serie.animation.InitProgress(1, 0, (float)realHig);
  312. var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail();
  313. var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
  314. var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
  315. var isNeedGradient = !ChartHelper.IsValueEqualsColor(color, toColor);
  316. var isFull = hig >= vessel.runtimeHeight;
  317. if (hig >= vessel.runtimeHeight) hig = vessel.runtimeHeight;
  318. if (isFull && !isNeedGradient)
  319. {
  320. UGL.DrawRectangle(vh, cenPos, vessel.runtimeWidth / 2, vessel.runtimeHeight / 2, toColor);
  321. }
  322. else
  323. {
  324. var startY = (float)(cenPos.y - vessel.runtimeHeight / 2 + hig);
  325. var waveStartPos = new Vector3(cenPos.x - vessel.runtimeWidth / 2, startY);
  326. var waveEndPos = new Vector3(cenPos.x + vessel.runtimeWidth / 2, startY);
  327. var startX = waveStartPos.x;
  328. var endX = waveEndPos.x;
  329. var step = vessel.smoothness;
  330. if (step < 0.5f) step = 0.5f;
  331. var lup = waveStartPos;
  332. var ldp = new Vector3(startX, vessel.runtimeCenterPos.y - vessel.runtimeHeight / 2);
  333. var nup = Vector3.zero;
  334. var ndp = Vector3.zero;
  335. var angle = 0f;
  336. var isStarted = false;
  337. var isEnded = false;
  338. var waveHeight = isFull ? 0 : serie.waveHeight;
  339. serie.runtimeWaveSpeed += serie.waveSpeed * Time.deltaTime;
  340. while (startX < endX)
  341. {
  342. startX += step;
  343. if (startX > endX) startX = endX;
  344. if (startX > waveStartPos.x && !isStarted)
  345. {
  346. startX = waveStartPos.x;
  347. isStarted = true;
  348. }
  349. if (startX > waveEndPos.x && !isEnded)
  350. {
  351. startX = waveEndPos.x;
  352. isEnded = true;
  353. }
  354. var py = Mathf.Sqrt(Mathf.Pow(vessel.runtimeHeight, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2));
  355. if (startX < waveStartPos.x || startX > waveEndPos.x)
  356. {
  357. nup = new Vector3(startX, cenPos.y + py);
  358. }
  359. else
  360. {
  361. var py2 = waveHeight * Mathf.Sin(1 / serie.waveLength * angle + serie.runtimeWaveSpeed + serie.waveOffset);
  362. var nupY = waveStartPos.y + py2;
  363. nup = new Vector3(startX, nupY);
  364. angle += step;
  365. }
  366. ndp = new Vector3(startX, cenPos.y - vessel.runtimeHeight / 2);
  367. if (nup.y > cenPos.y + vessel.runtimeHeight / 2)
  368. {
  369. nup.y = cenPos.y + vessel.runtimeHeight / 2;
  370. }
  371. if (nup.y < cenPos.y - vessel.runtimeHeight / 2)
  372. {
  373. nup.y = cenPos.y - vessel.runtimeHeight / 2;
  374. }
  375. if (!ChartHelper.IsValueEqualsColor(color, toColor))
  376. {
  377. var colorMin = cenPos.y - vessel.runtimeHeight;
  378. var colorMax = startY + serie.waveHeight;
  379. var tcolor1 = Color32.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin));
  380. var tcolor2 = Color32.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin));
  381. UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, tcolor1, tcolor2);
  382. }
  383. else
  384. {
  385. UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, color);
  386. }
  387. lup = nup;
  388. ldp = ndp;
  389. }
  390. }
  391. if (serie.waveSpeed != 0 && Application.isPlaying && !isFull)
  392. {
  393. chart.RefreshPainter(serie);
  394. }
  395. if (!serie.animation.IsFinish())
  396. {
  397. serie.animation.CheckProgress(realHig);
  398. chart.m_IsPlayingAnimation = true;
  399. chart.RefreshPainter(serie);
  400. }
  401. }
  402. }
  403. }