Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using SDL2;
- namespace ScenesSandbox
- {
- interface IPainter
- {
- int32 Width { get; } int32 Height { get; }
- void Update(Engine.Context context);
- void HandleEvent(SDL.Event event, out bool quitApplication);
- }
- interface IPlotter : IPainter
- {
- int32 Resolution { get; }
- uint32 Plot(int x, int y);
- }
- class Engine
- {
- static let format = SDL.AllocFormat(SDL.PIXELFORMAT_ARGB8888);
- public static uint32 PixelFormat { get { return (uint32)format.format; } }
- public static void Run(IPainter painter)
- {
- Context c = scope .();
- SDL.Init(.Video);
- c.Window = SDL.CreateWindow(null, .Undefined, .Undefined, painter.Width, painter.Height, .Shown);
- c.Renderer = SDL.CreateRenderer(c.Window, -1, .Accelerated);
- while (readEvents(painter)) using(c.FrameTracker())
- {
- SDL.SetRenderDrawColor(c.Renderer, 0, 0, 0, 255);
- SDL.RenderClear(c.Renderer);
- painter.Update(c);
- SDL.RenderPresent(c.Renderer);
- SDL.Delay(1);
- }
- SDL.DestroyRenderer(c.Renderer);
- SDL.Quit();
- }
- public static void Run(IPlotter plotter)
- {
- Context c = scope .();
- let painter = (IPainter)plotter;
- SDL.Init(.Video);
- c.Window = SDL.CreateWindow(null, .Undefined, .Undefined, painter.Width, painter.Height, .Shown);
- c.Renderer = SDL.CreateRenderer(c.Window, -1, .Accelerated);
- let sw = painter.Width / plotter.Resolution;
- let sh = painter.Height / plotter.Resolution;
- let texture = SDL.CreateTexture(c.Renderer, PixelFormat, (int32)SDL.TextureAccess.Streaming, sw, sh);
- let sourceRect = scope SDL.Rect(0, 0, sw, sh);
- let targetRect = scope SDL.Rect(0, 0, painter.Width, painter.Height);
- var framesRecorded = 0;
- while (readEvents(plotter)) using(c.FrameTracker())
- {
- void* pixelsPointer; int32 pitch;
- SDL.LockTexture(texture, sourceRect, out pixelsPointer, out pitch);
- let pixels = (uint32*)pixelsPointer;
- var i = 0;
- for (var y = 0; y < sh; y++) for (var x = 0; x < sw; x++)
- pixels[i++] = plotter.Plot(x * plotter.Resolution, y * plotter.Resolution);
- plotter.Update(c);
- if(c.Recording)
- {
- let surface = SDL.CreateRGBSurfaceWithFormatFrom(pixels, sw, sh, 0, pitch, (uint32)format.format);
- let fname = scope System.String(); fname.AppendF(@"c:\temp\out_{0:000}.png", framesRecorded++);
- SDLImage.SavePNG(surface, fname);
- }
- SDL.UnlockTexture(texture);
- SDL.RenderCopy(c.Renderer, texture, sourceRect, targetRect);
- SDL.RenderPresent(c.Renderer);
- SDL.Delay(1);
- }
- SDL.DestroyRenderer(c.Renderer);
- SDL.Quit();
- }
- static bool readEvents(IPainter painter)
- {
- SDL.Event event; bool quit = false;
- while (!quit && SDL.PollEvent(out event) != 0)
- painter.HandleEvent(event, out quit);
- return !quit;
- }
- public static uint32 MapRGB(uint8 r, uint8 g, uint8 b, uint8 a = 255)
- {
- return (uint32)SDL.MapRGBA(format, r, g, b, a);
- }
- public static uint32 MapHSL(float h, float s, float l, uint8 a = 255)
- {
- let (r, g, b) = HSLtoRGB(h, s, l);
- return MapRGB(r, g, b, a);
- }
- static (uint8 r, uint8 g, uint8 b) HSLtoRGB(float h, float s, float l)
- {
- float r, g, b;
- if (s == 0f)
- r = g = b = l * 255f;
- else
- {
- var q = l < 0.5f ? l * (1f + s) : l + s - l * s;
- var p = 2f * l - q;
- r = hueToRGB(p, q, h + 1f / 3f);
- g = hueToRGB(p, q, h);
- b = hueToRGB(p, q, h - 1f / 3f);
- }
- return (round(r), round(g), round(b));
- }
- static uint8 round(float n) => (uint8)System.Math.Round(n * 255f);
- static float hueToRGB(float p, float q, float tt)
- {
- float t = tt;
- if (t < 0f) t += 1f;
- if (t > 1f) t -= 1f;
- if (t < 1f / 6f) return p + (q - p) * 6f * t;
- if (t < 1f / 2f) return q;
- if (t < 2f / 3f) return p + (q - p) * (2f / 3f - t) * 6f;
- return p;
- }
- public class Context
- {
- System.Collections.List<int64> fpsSamples = new .() ~ delete _;
- public SDL.Window* Window;
- public SDL.Renderer* Renderer;
- public uint64 FrameCount;
- public int64 lastFrameTick = System.DateTime.Now.Ticks;
- public int64 thisFrameTick;
- public bool Recording;
- public float FrameDurationInMilliSeconds { get { return (thisFrameTick - lastFrameTick) / 1e4f; } }
- public float FrameDurationInSeconds { get { return (thisFrameTick - lastFrameTick) / 1e7f; } }
- public float CurrentFPS { get { return 1f / FrameDurationInSeconds; } }
- public float AverageFPS
- {
- get
- {
- float sum = 0f;
- for (var s in fpsSamples) sum += 1e7f / s;
- return System.Math.Round(sum / fpsSamples.Count);
- }
- }
- public System.IDisposable FrameTracker()
- {
- return new FrameTracker(this);
- }
- public void SetDrawColorRGB(uint8 r, uint8 g, uint8 b, uint8 a = 255)
- {
- SDL.SetRenderDrawColor(Renderer, r, g, b, a);
- }
- public void SetDrawColorHSL(float h, float s, float l, uint8 a = 255)
- {
- let (r, g, b) = HSLtoRGB(h, s, l);
- SDL.SetRenderDrawColor(Renderer, r, g, b, a);
- }
- private class FrameTracker : System.IDisposable
- {
- Engine.Context context;
- public this(Engine.Context context)
- {
- context.FrameCount++;
- context.thisFrameTick = System.DateTime.Now.Ticks;
- context.fpsSamples.Add(context.thisFrameTick - context.lastFrameTick);
- if(context.fpsSamples.Count == 50) context.fpsSamples.RemoveAt(0);
- this.context = context;
- }
- public void Dispose()
- {
- context.lastFrameTick = context.thisFrameTick;
- delete this;
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment