Guest User

Untitled

a guest
Aug 28th, 2020
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.51 KB | None | 0 0
  1. using SDL2;
  2. namespace ScenesSandbox
  3. {
  4. interface IPainter
  5. {
  6. int32 Width { get; } int32 Height { get; }
  7. void Update(Engine.Context context);
  8. void HandleEvent(SDL.Event event, out bool quitApplication);
  9. }
  10. interface IPlotter : IPainter
  11. {
  12. int32 Resolution { get; }
  13. uint32 Plot(int x, int y);
  14. }
  15.  
  16. class Engine
  17. {
  18. static let format = SDL.AllocFormat(SDL.PIXELFORMAT_ARGB8888);
  19. public static uint32 PixelFormat { get { return (uint32)format.format; } }
  20.  
  21. public static void Run(IPainter painter)
  22. {
  23. Context c = scope .();
  24.  
  25. SDL.Init(.Video);
  26. c.Window = SDL.CreateWindow(null, .Undefined, .Undefined, painter.Width, painter.Height, .Shown);
  27. c.Renderer = SDL.CreateRenderer(c.Window, -1, .Accelerated);
  28.  
  29. while (readEvents(painter)) using(c.FrameTracker())
  30. {
  31. SDL.SetRenderDrawColor(c.Renderer, 0, 0, 0, 255);
  32. SDL.RenderClear(c.Renderer);
  33.  
  34. painter.Update(c);
  35.  
  36. SDL.RenderPresent(c.Renderer);
  37. SDL.Delay(1);
  38. }
  39.  
  40. SDL.DestroyRenderer(c.Renderer);
  41. SDL.Quit();
  42. }
  43.  
  44. public static void Run(IPlotter plotter)
  45. {
  46. Context c = scope .();
  47. let painter = (IPainter)plotter;
  48.  
  49. SDL.Init(.Video);
  50. c.Window = SDL.CreateWindow(null, .Undefined, .Undefined, painter.Width, painter.Height, .Shown);
  51. c.Renderer = SDL.CreateRenderer(c.Window, -1, .Accelerated);
  52.  
  53. let sw = painter.Width / plotter.Resolution;
  54. let sh = painter.Height / plotter.Resolution;
  55.  
  56. let texture = SDL.CreateTexture(c.Renderer, PixelFormat, (int32)SDL.TextureAccess.Streaming, sw, sh);
  57. let sourceRect = scope SDL.Rect(0, 0, sw, sh);
  58. let targetRect = scope SDL.Rect(0, 0, painter.Width, painter.Height);
  59.  
  60. var framesRecorded = 0;
  61. while (readEvents(plotter)) using(c.FrameTracker())
  62. {
  63. void* pixelsPointer; int32 pitch;
  64. SDL.LockTexture(texture, sourceRect, out pixelsPointer, out pitch);
  65. let pixels = (uint32*)pixelsPointer;
  66.  
  67. var i = 0;
  68. for (var y = 0; y < sh; y++) for (var x = 0; x < sw; x++)
  69. pixels[i++] = plotter.Plot(x * plotter.Resolution, y * plotter.Resolution);
  70. plotter.Update(c);
  71.  
  72. if(c.Recording)
  73. {
  74. let surface = SDL.CreateRGBSurfaceWithFormatFrom(pixels, sw, sh, 0, pitch, (uint32)format.format);
  75. let fname = scope System.String(); fname.AppendF(@"c:\temp\out_{0:000}.png", framesRecorded++);
  76. SDLImage.SavePNG(surface, fname);
  77. }
  78.  
  79. SDL.UnlockTexture(texture);
  80. SDL.RenderCopy(c.Renderer, texture, sourceRect, targetRect);
  81.  
  82. SDL.RenderPresent(c.Renderer);
  83. SDL.Delay(1);
  84. }
  85.  
  86. SDL.DestroyRenderer(c.Renderer);
  87. SDL.Quit();
  88. }
  89.  
  90. static bool readEvents(IPainter painter)
  91. {
  92. SDL.Event event; bool quit = false;
  93. while (!quit && SDL.PollEvent(out event) != 0)
  94. painter.HandleEvent(event, out quit);
  95. return !quit;
  96. }
  97.  
  98. public static uint32 MapRGB(uint8 r, uint8 g, uint8 b, uint8 a = 255)
  99. {
  100. return (uint32)SDL.MapRGBA(format, r, g, b, a);
  101. }
  102.  
  103. public static uint32 MapHSL(float h, float s, float l, uint8 a = 255)
  104. {
  105. let (r, g, b) = HSLtoRGB(h, s, l);
  106. return MapRGB(r, g, b, a);
  107. }
  108.  
  109. static (uint8 r, uint8 g, uint8 b) HSLtoRGB(float h, float s, float l)
  110. {
  111. float r, g, b;
  112. if (s == 0f)
  113. r = g = b = l * 255f;
  114. else
  115. {
  116. var q = l < 0.5f ? l * (1f + s) : l + s - l * s;
  117. var p = 2f * l - q;
  118. r = hueToRGB(p, q, h + 1f / 3f);
  119. g = hueToRGB(p, q, h);
  120. b = hueToRGB(p, q, h - 1f / 3f);
  121. }
  122. return (round(r), round(g), round(b));
  123. }
  124.  
  125.  
  126. static uint8 round(float n) => (uint8)System.Math.Round(n * 255f);
  127. static float hueToRGB(float p, float q, float tt)
  128. {
  129. float t = tt;
  130. if (t < 0f) t += 1f;
  131. if (t > 1f) t -= 1f;
  132. if (t < 1f / 6f) return p + (q - p) * 6f * t;
  133. if (t < 1f / 2f) return q;
  134. if (t < 2f / 3f) return p + (q - p) * (2f / 3f - t) * 6f;
  135. return p;
  136. }
  137.  
  138. public class Context
  139. {
  140. System.Collections.List<int64> fpsSamples = new .() ~ delete _;
  141.  
  142. public SDL.Window* Window;
  143. public SDL.Renderer* Renderer;
  144.  
  145. public uint64 FrameCount;
  146. public int64 lastFrameTick = System.DateTime.Now.Ticks;
  147. public int64 thisFrameTick;
  148.  
  149. public bool Recording;
  150.  
  151. public float FrameDurationInMilliSeconds { get { return (thisFrameTick - lastFrameTick) / 1e4f; } }
  152. public float FrameDurationInSeconds { get { return (thisFrameTick - lastFrameTick) / 1e7f; } }
  153. public float CurrentFPS { get { return 1f / FrameDurationInSeconds; } }
  154. public float AverageFPS
  155. {
  156. get
  157. {
  158. float sum = 0f;
  159. for (var s in fpsSamples) sum += 1e7f / s;
  160. return System.Math.Round(sum / fpsSamples.Count);
  161. }
  162. }
  163.  
  164. public System.IDisposable FrameTracker()
  165. {
  166. return new FrameTracker(this);
  167. }
  168.  
  169. public void SetDrawColorRGB(uint8 r, uint8 g, uint8 b, uint8 a = 255)
  170. {
  171. SDL.SetRenderDrawColor(Renderer, r, g, b, a);
  172. }
  173. public void SetDrawColorHSL(float h, float s, float l, uint8 a = 255)
  174. {
  175. let (r, g, b) = HSLtoRGB(h, s, l);
  176. SDL.SetRenderDrawColor(Renderer, r, g, b, a);
  177. }
  178.  
  179. private class FrameTracker : System.IDisposable
  180. {
  181. Engine.Context context;
  182. public this(Engine.Context context)
  183. {
  184. context.FrameCount++;
  185. context.thisFrameTick = System.DateTime.Now.Ticks;
  186. context.fpsSamples.Add(context.thisFrameTick - context.lastFrameTick);
  187. if(context.fpsSamples.Count == 50) context.fpsSamples.RemoveAt(0);
  188. this.context = context;
  189. }
  190. public void Dispose()
  191. {
  192. context.lastFrameTick = context.thisFrameTick;
  193. delete this;
  194. }
  195. }
  196. }
  197. }
  198. }
Advertisement
Add Comment
Please, Sign In to add comment