VeldridContent.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using EventBus;
  2. using FontStashSharp;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Threading;
  9. using Veldrid.Common.Tools;
  10. using Veldrid.Common.VeldridRender.TextRender;
  11. namespace Veldrid.Common
  12. {
  13. public sealed partial class VeldridContent : IVeldridContent
  14. {
  15. private bool sizechanged = false;
  16. private Boolean first = true;
  17. private Stopwatch stopwatch = new Stopwatch();
  18. private GraphicsManger graphicsManger;
  19. private double fps = 0;
  20. private VeldridText fpstext;
  21. private DateTime lastTime;
  22. private CancellationTokenSource tokenSource = new CancellationTokenSource();
  23. private Boolean OnlyCompute = false;
  24. public VeldridContent(Boolean onlyCompute = false)
  25. {
  26. OnlyCompute = onlyCompute;
  27. graphicsManger = new GraphicsManger();
  28. if (!onlyCompute)
  29. {
  30. FontManger.Instance.AddFontDirectory(AppDomain.CurrentDomain.BaseDirectory + "Fonts");
  31. InitEvent();
  32. fpstext = new VeldridText(this, true, false);
  33. fpstext.Visibily = false;
  34. fpstext.CreateResources();
  35. fpstext.FontSize = 10;
  36. fpstext.Color = Color.Black;
  37. fpstext.BackColor = Color.FromArgb(100, Color.Yellow);
  38. fpstext.Local = new PointF(graphicsManger.DefaultLineRange.MinX + 20, graphicsManger.DefaultLineRange.MinY + 20);
  39. fpstext.VerticalAlignment = VerticalAlignment.Bottom;
  40. fpstext.HorizontalAlignment = HorizontalAlignment.Left;
  41. lastTime = DateTime.Now;
  42. }
  43. }
  44. public Boolean FPSVisibily { get => fpstext.Visibily; set => fpstext.Visibily = value; }
  45. GraphicsManger IVeldridContent.GraphicsManger => graphicsManger;
  46. public double FPS => fps;
  47. public List<IAxis> Axes { get; } = new List<IAxis>();
  48. public List<ISeries> Series { get; } = new List<ISeries>();
  49. public List<ICursor> Cursors { get; } = new List<ICursor>();
  50. public bool IsInitialized { get; private set; }
  51. public void Init()
  52. {
  53. if (!graphicsManger.IsExists) return;
  54. if (!IsInitialized)
  55. {
  56. System.Threading.Tasks.Task.Run(() => MainRender(), tokenSource.Token);
  57. IsInitialized = true;
  58. }
  59. }
  60. Object locker = new Object();
  61. private void MainRender()
  62. {
  63. if (OnlyCompute) return;
  64. while (!tokenSource.IsCancellationRequested)
  65. {
  66. if (graphicsManger.Window.Exists && !disposedValue)
  67. {
  68. try
  69. {
  70. var deltaSeconds = (DateTime.Now - lastTime).TotalMilliseconds / 1000f;
  71. lastTime = DateTime.Now;
  72. if (sizechanged || first)
  73. {
  74. if (graphicsManger.Window.Width != 0 && graphicsManger.Window.Height != 0)
  75. {
  76. lock (locker)
  77. {
  78. graphicsManger.SetWindowSize();
  79. Series.ForEach(x => x.WindowSizeState = true);
  80. Axes.ForEach(y => y.WindowSizeState = true);
  81. Cursors.ForEach(x => x.WindowSizeState = true);
  82. Sundries.ForEach(y => y.WindowSizeState = true);
  83. fpstext.WindowSizeState = true;
  84. sizechanged = false;
  85. first = false;
  86. Render();
  87. }
  88. }
  89. }
  90. graphicsManger.Camera.Update((float)deltaSeconds, graphicsManger.Window.PumpEvents());
  91. }
  92. catch (Exception ex)
  93. {
  94. EventBroker.Instance.GetEvent<LogEventArgs>().Publish(this, new LogEventArgs(ex, LogLevel.Error));
  95. }
  96. }
  97. Thread.Sleep(10);
  98. }
  99. }
  100. private void Render()
  101. {
  102. if (!graphicsManger.IsExists || !IsInitialized || first) return;
  103. try
  104. {
  105. if (graphicsManger.CommandList.IsDisposed)
  106. {
  107. return;
  108. }
  109. stopwatch.Restart();
  110. graphicsManger.CommandList.Begin();
  111. graphicsManger.CommandList.SetFramebuffer(graphicsManger.Device.MainSwapchain.Framebuffer);
  112. graphicsManger.CommandList.ClearColorTarget(0, _backColor);
  113. Axes.OrderBy(x => x.ZIndex).ToList().ForEach(x => x.Draw());
  114. Series.OrderBy(x => x.ZIndex).ToList().ForEach(x => x.Draw());
  115. Cursors.OrderBy(x => x.ZIndex).ToList().ForEach(x => x.Draw());
  116. Sundries.OrderBy(x => x.ZIndex).ToList().ForEach(y => y.Draw());
  117. RenderEventHandler?.Invoke(this, EventArgs.Empty);
  118. fpstext.Draw();
  119. graphicsManger.CommandList.End();
  120. graphicsManger.Device.SubmitCommands(graphicsManger.CommandList);
  121. graphicsManger.Device.SwapBuffers();
  122. stopwatch.Stop();
  123. if (stopwatch.Elapsed.TotalMilliseconds == 0)
  124. {
  125. fps = 1000;
  126. }
  127. else fps = Math.Round(1000 / stopwatch.Elapsed.TotalMilliseconds, 2);
  128. fpstext.Text = $"Render:{String.Format("{0:0000.00}", fps)}FPS/{String.Format("{0:000.00}", stopwatch.Elapsed.TotalMilliseconds)}ms";
  129. //fpstext.Text = "AB";
  130. }
  131. catch (Exception ex)
  132. {
  133. EventBroker.Instance.GetEvent<LogEventArgs>().Publish(this, new LogEventArgs(ex, LogLevel.Error));
  134. }
  135. }
  136. public void DoRender()
  137. {
  138. lock (locker)
  139. {
  140. Render();
  141. }
  142. }
  143. RgbaFloat _backColor;
  144. public Color BackColor
  145. {
  146. get => backColor;
  147. set
  148. {
  149. backColor = value;
  150. _backColor = value.ColorConverToRGBA();
  151. }
  152. }
  153. public Size WindowSize
  154. {
  155. get => new Size(graphicsManger.Window.Width, graphicsManger.Window.Height);
  156. set => graphicsManger.Window.SetWindowSize(value.Width, value.Height);
  157. }
  158. public List<IRender> Sundries { get; } = new List<IRender>();
  159. private Boolean disposedValue;
  160. private Color backColor = Color.Black;
  161. private void Dispose(bool disposing)
  162. {
  163. tokenSource.Cancel();
  164. // _Locker.Wait();
  165. lock (locker)
  166. {
  167. if (!disposedValue)
  168. {
  169. IsInitialized = false;
  170. if (disposing)
  171. {
  172. this.ClearEventHandle();
  173. graphicsManger.Device.WaitForIdle();
  174. Axes.ForEach(x => x.Dispose());
  175. Series.ForEach(x => x.Dispose());
  176. Cursors.ForEach(x => x.Dispose());
  177. Sundries.ForEach(x => x.Dispose());
  178. fpstext.DisposeResources();
  179. graphicsManger.Dispose();
  180. // TODO: 释放托管状态(托管对象)
  181. }
  182. // TODO: 释放未托管的资源(未托管的对象)并重写终结器
  183. // TODO: 将大型字段设置为 null
  184. disposedValue = true;
  185. }
  186. }
  187. //_Locker.Dispose();
  188. }
  189. // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
  190. // ~VeldridContent()
  191. // {
  192. // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
  193. // Dispose(disposing: false);
  194. // }
  195. public void Dispose()
  196. {
  197. // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
  198. Dispose(disposing: true);
  199. GC.SuppressFinalize(this);
  200. }
  201. }
  202. }