Files
Voile/Voile/Source/Rendering/RaylibRenderSystem.cs
2024-10-14 20:01:01 +02:00

296 lines
8.9 KiB
C#

using System.Numerics;
using System.Text;
using Raylib_cs;
namespace Voile.Rendering
{
public class RaylibRenderSystem : RenderSystem
{
public override bool ShouldRun => !WindowShouldClose();
public override Vector2 WindowSize
{
get
{
return new Vector2(Raylib.GetScreenWidth(), Raylib.GetScreenHeight());
}
set
{
Raylib.SetWindowSize((int)value.X, (int)value.Y);
}
}
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 bool Fullscreen { get => _fullscreen; set => SetFullscreen(value); }
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 = settings.Fullscreen;
_defaultFlags = flags;
Raylib.SetConfigFlags(flags);
}
public override void CreateAndInitializeWithWindow(RendererSettings settings)
{
Initialize(settings);
CreateWindow(settings.WindowSettings);
}
public override void CreateWindow(WindowSettings windowSettings)
{
Raylib.SetTraceLogLevel(TraceLogLevel.LOG_NONE);
_defaultWindowSettings = windowSettings;
_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);
Fullscreen = true;
}
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();
}
protected 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(VoileColorToRaylibColor(color));
}
protected override double GetFrameTime()
{
return (double)Raylib.GetFrameTime();
}
public override void DrawCircle(float radius, Color color)
{
Raylib.DrawCircle((int)transformPosition.X, (int)transformPosition.Y, radius, VoileColorToRaylibColor(color));
}
public override void DrawTexture(Texture2d texture, Color tint)
{
if (texture.Handle == -1)
{
LoadTexture(texture);
}
Raylib.DrawTextureV(_texturePool[texture.Handle], transformPosition, VoileColorToRaylibColor(tint));
}
public override void DrawRectangle(Vector2 size, Color color)
{
Raylib.DrawRectanglePro(new Rectangle()
{
x = transformPosition.X,
y = transformPosition.Y,
width = size.X,
height = size.Y
}, transformPivot, transformRotation, VoileColorToRaylibColor(color));
}
public override void DrawDebugText(string text, int fontSize, Color color)
{
Raylib.DrawText(text, (int)transformPosition.X, (int)transformPosition.Y, fontSize, VoileColorToRaylibColor(color));
}
public override void DrawSdfText(string text, int fontSize, Color color)
{
throw new NotImplementedException();
}
private void SetFullscreen(bool fullscreen)
{
// var flags = _defaultFlags;
// if (fullscreen && !Raylib.IsWindowFullscreen())
// {
// WindowSize = MonitorSize;
// Raylib.ToggleFullscreen();
// }
// else if (Raylib.IsWindowFullscreen())
// {
// // Raylib.ToggleFullscreen();
// WindowSize = _windowSize;
// }
_fullscreen = fullscreen;
}
// TODO
public override void SetTransform(Matrix4x4 transform) { }
private Raylib_cs.Color VoileColorToRaylibColor(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(Font font, string text, Color color)
{
if (font.Handle == -1)
{
LoadFont(font);
}
var rayFont = _fontPool[font.Handle];
Raylib.DrawTextPro(rayFont, text, transformPosition, transformPivot, transformRotation, font.Size, 0.0f, VoileColorToRaylibColor(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 unsafe void LoadFont(Font font)
{
Raylib_cs.Font fontRay;
ReadOnlySpan<char> ext = ".ttf"; // TODO: don't use a hardcoded extension.
Span<byte> extBytes = new byte[Encoding.Default.GetByteCount(ext) + 1];
Encoding.Default.GetBytes(ext, extBytes);
int fontChars = 2048; // TODO: control this dynamically to not load the entire font.
unsafe
{
fixed (byte* extP = extBytes)
{
fixed (byte* bufferP = font.Buffer)
{
fontRay = Raylib.LoadFontFromMemory((sbyte*)extP, bufferP, (int)font.BufferSize, font.Size, null, fontChars);
}
}
}
Raylib.GenTextureMipmaps(ref fontRay.texture);
Raylib.SetTextureFilter(fontRay.texture, TextureFilter.TEXTURE_FILTER_BILINEAR);
_fontPool.Add(fontRay);
font.Handle = _fontPool.Count - 1;
}
private void LoadTexture(Texture2d texture)
{
Image image = new();
unsafe
{
fixed (void* dataPtr = texture.Buffer)
{
image.data = dataPtr;
}
}
image.width = texture.Width;
image.height = texture.Height;
image.mipmaps = texture.Mipmaps;
image.format = (PixelFormat)texture.Format;
Texture2D rayTexture;
rayTexture = Raylib.LoadTextureFromImage(image);
_texturePool.Add(rayTexture);
texture.Handle = _texturePool.Count - 1;
}
private List<Texture2D> _texturePool = new();
private List<Raylib_cs.Font> _fontPool = new();
private Vector2 _windowSize;
private bool _vsync;
private string _windowTitle = string.Empty;
private int _targetFps;
private bool _fullscreen;
private WindowSettings _defaultWindowSettings;
private ConfigFlags _defaultFlags;
}
}