using System.Numerics; using System.Runtime.InteropServices; using System.Text; using Raylib_cs; namespace DaggerFramework.Rendering { public class RaylibRenderer : Renderer { public override bool ShouldRun => !WindowShouldClose(); public override Vector2 WindowSize => new Vector2(Raylib.GetScreenWidth(), Raylib.GetScreenHeight()); public override Vector2 MonitorSize => new Vector2(GetMonitorWidth(GetCurrentMonitor()), GetMonitorHeight(GetCurrentMonitor())); public override string WindowTitle { get => _windowTitle; set { SetWindowTitle(value); } } public override int TargetFps { get => _targetFps; set => SetTargetFps(value); } public override bool VSync { get => _vsync; set => SetWindowVSync(value); } public override void CreateWindow(WindowSettings windowSettings) { Raylib.SetTraceLogLevel(TraceLogLevel.LOG_NONE); _windowSize = windowSettings.Size; ConfigFlags windowFlags = 0; windowFlags |= windowSettings.Resizable ? ConfigFlags.FLAG_WINDOW_RESIZABLE : 0; _windowTitle = windowSettings.Title; if (_fullscreen) { var monitorSize = MonitorSize; Raylib.InitWindow((int)monitorSize.X, (int)monitorSize.Y, windowSettings.Title); } else { Raylib.InitWindow((int)_windowSize.X, (int)_windowSize.Y, windowSettings.Title); } Raylib.SetWindowState(windowFlags); } protected override void SetWindowTitle(string title) { Raylib.SetWindowTitle(title); } protected override void SetWindowVSync(bool value) { _vsync = value; // TODO: implement VSync toggle for Raylib. } protected override void SetTargetFps(int fps) { _targetFps = fps; Raylib.SetTargetFPS(fps); } protected override bool WindowShouldClose() { return Raylib.WindowShouldClose(); } public override void Shutdown() { Raylib.CloseWindow(); } public override void BeginFrame() { Raylib.BeginDrawing(); } public override void EndFrame() { Raylib.EndDrawing(); } public override void BeginCamera2d(Vector2 offset, Vector2 target, float rotation, float zoom) { var camera = new Camera2D(offset, target, rotation, zoom); Raylib.BeginMode2D(camera); } public override void EndCamera2d() { Raylib.EndMode2D(); } public override void ClearBackground(Color color) { Raylib.ClearBackground(DaggerColorToRaylibColor(color)); } public override double GetFrameTime() { return (double)Raylib.GetFrameTime(); } public override void DrawCircle(float radius, Color color) { Raylib.DrawCircle((int)_position.X, (int)_position.Y, radius, DaggerColorToRaylibColor(color)); } public override void SetTransform(Vector2 position, Vector2 offset, float rotation = 0) { _position = position; _offset = offset; _rotation = rotation; } public override int LoadTexture(Texture2d texture) { Image image = new Image(); unsafe { fixed (void* dataPtr = texture.Buffer) { image.data = dataPtr; } } image.width = texture.Width; image.height = texture.Height; image.mipmaps = 1; image.format = PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; Texture2D rayTexture; rayTexture = Raylib.LoadTextureFromImage(image); _texturePool.Add(rayTexture); return _texturePool.Count - 1; } public unsafe override int LoadFont(Font font) { // TODO: screw it, let's just load the font directly from the path. I give up. // Raylib_cs.Font fontRay; // string ext = "ttf"; // byte[] extBytes = new byte[Encoding.Default.GetByteCount(ext) + 1]; // Encoding.Default.GetBytes(ext, extBytes); // int fontChars = 0; // unsafe // { // fixed (byte* extP = extBytes) // { // fixed (byte* bufferP = font.Buffer) // { // fontRay = Raylib.LoadFontFromMemory((sbyte*)extP, bufferP, (int)font.BufferSize, font.Size, null, 95); // } // } // } var fontRay = Raylib.LoadFont(font.Path); Raylib.SetTextureFilter(fontRay.texture, TextureFilter.TEXTURE_FILTER_BILINEAR); _fontPool.Add(fontRay); return _fontPool.Count - 1; } public override void DrawTexture(int id, Color tint) { Raylib.DrawTextureV(_texturePool[id], _position, DaggerColorToRaylibColor(tint)); } public override void DrawRectangle(Vector2 size, Color color) { // Raylib.DrawRectangleV(_position, size, SystemColorToRaylibColor(color)); Raylib.DrawRectanglePro(new Rectangle() { x = _position.X, y = _position.Y, width = size.X, height = size.Y }, _offset, _rotation, DaggerColorToRaylibColor(color)); } public override void DrawDebugText(string text, int fontSize, Color color) { Raylib.DrawText(text, (int)_position.X, (int)_position.Y, fontSize, DaggerColorToRaylibColor(color)); } public override void DrawSdfText(string text, int fontSize, Color color) { throw new NotImplementedException(); } public override void Initialize(RendererSettings settings) { _targetFps = settings.TargetFps; ConfigFlags flags = 0; // MSAA flags |= settings.Msaa == Msaa.Msaa4x ? ConfigFlags.FLAG_MSAA_4X_HINT : 0; // VSync flags |= settings.UseVSync ? ConfigFlags.FLAG_VSYNC_HINT : 0; // Fullscreen flags |= settings.Fullscreen ? ConfigFlags.FLAG_WINDOW_MAXIMIZED : 0; flags |= settings.Fullscreen ? ConfigFlags.FLAG_WINDOW_UNDECORATED : 0; _fullscreen = settings.Fullscreen; Raylib.SetConfigFlags(flags); } // TODO public override void SetTransform(Matrix4x4 transform) { } public override void CreateAndInitialize(WindowSettings windowSettings, RendererSettings renderSettings) { Initialize(renderSettings); CreateWindow(windowSettings); } private Raylib_cs.Color DaggerColorToRaylibColor(Color color) { return new Raylib_cs.Color { r = (byte)Math.Round(color.R * 255f), g = (byte)Math.Round(color.G * 255f), b = (byte)Math.Round(color.B * 255f), a = (byte)Math.Round(color.A * 255f) }; } public override void DrawText(int fontId, string text, int fontSize, Color color) { var font = _fontPool[fontId]; Raylib.DrawTextPro(font, text, _position, Vector2.Zero, _rotation, fontSize, 0.0f, DaggerColorToRaylibColor(color)); } protected override int GetMonitorWidth(int monitorId) { return Raylib.GetMonitorWidth(monitorId); } protected override int GetMonitorHeight(int monitorId) { return Raylib.GetMonitorHeight(monitorId); } protected override int GetCurrentMonitor() { return Raylib.GetCurrentMonitor(); } private List _texturePool = new(); private List _fontPool = new(); private Vector2 _position, _offset; private float _rotation; private Vector2 _windowSize; private bool _vsync; private string _windowTitle = string.Empty; private int _targetFps; private bool _fullscreen; } }