mirror of
https://github.com/Stone-Red-Code/RemSox.git
synced 2026-09-04 09:06:23 +02:00
Implement full canvas compositing and redraw only on state change
This commit is contained in:
@@ -1,57 +1,102 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using Cosmos.Kernel.System.Graphics;
|
||||
|
||||
namespace RemSox.UI.GUI.Rendering;
|
||||
|
||||
public sealed class CanvasRenderSource : IRenderSource
|
||||
{
|
||||
private static readonly Dictionary<int, Canvas> windowCanvases = new();
|
||||
private static readonly Dictionary<int, Point> windowPositions = new();
|
||||
|
||||
public void Render(IEnumerable<RenderCommand> commands)
|
||||
{
|
||||
Canvas canvas = FullScreenCanvas.GetFullScreenCanvas();
|
||||
|
||||
foreach (RenderCommand command in commands)
|
||||
{
|
||||
if (command.ElementType == "Window")
|
||||
{
|
||||
RenderWindow(canvas, command);
|
||||
Size size = command.Properties.TryGetValue("Size", out object? rawSize) && rawSize is Size windowSize
|
||||
? windowSize
|
||||
: new Size(160, 120);
|
||||
|
||||
if (!windowCanvases.TryGetValue(command.WindowId, out Canvas? currentCanvas) ||
|
||||
currentCanvas.Mode.Width != size.Width ||
|
||||
currentCanvas.Mode.Height != size.Height)
|
||||
{
|
||||
windowCanvases[command.WindowId] = new Canvas(size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
|
||||
if (!windowCanvases.ContainsKey(command.WindowId))
|
||||
{
|
||||
windowCanvases[command.WindowId] = new Canvas(160, 120);
|
||||
}
|
||||
|
||||
Canvas windowCanvas = windowCanvases[command.WindowId];
|
||||
|
||||
if (command.ElementType == "Window")
|
||||
{
|
||||
RenderWindow(windowCanvas, command);
|
||||
windowPositions[command.WindowId] = command.Position;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.ElementType == "WindowMove")
|
||||
{
|
||||
windowPositions[command.WindowId] = command.Position;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.ElementType == "Circle")
|
||||
{
|
||||
RenderCircle(canvas, command);
|
||||
RenderCircle(windowCanvas, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CompositeAndDisplay(Canvas screenCanvas, Point pointerPosition)
|
||||
{
|
||||
screenCanvas.Clear(Color.Black);
|
||||
|
||||
foreach (var kvp in windowPositions)
|
||||
{
|
||||
int windowId = kvp.Key;
|
||||
Point position = kvp.Value;
|
||||
if (windowCanvases.TryGetValue(windowId, out Canvas? windowCanvas))
|
||||
{
|
||||
screenCanvas.DrawCanvas(windowCanvas, position.X, position.Y);
|
||||
}
|
||||
}
|
||||
|
||||
screenCanvas.DrawFilledCircle(Color.White, pointerPosition.X, pointerPosition.Y, 5);
|
||||
screenCanvas.Display();
|
||||
}
|
||||
|
||||
private static void RenderWindow(Canvas canvas, RenderCommand command)
|
||||
{
|
||||
int x = command.Position.X;
|
||||
int y = command.Position.Y;
|
||||
|
||||
Size size = command.Properties.TryGetValue(nameof(Size), out object? rawSize) && rawSize is Size windowSize
|
||||
Size size = command.Properties.TryGetValue("Size", out object? rawSize) && rawSize is Size windowSize
|
||||
? windowSize
|
||||
: new Size(160, 120);
|
||||
|
||||
bool isFocused = command.Properties.TryGetValue(nameof(Windows.Window.IsFocused), out object? rawFocused) && rawFocused is bool focused && focused;
|
||||
bool isFocused = command.Properties.TryGetValue("IsFocused", out object? rawFocused) && rawFocused is bool focused && focused;
|
||||
|
||||
Color borderColor = isFocused ? Color.White : Color.DarkGray;
|
||||
Color bodyColor = Color.FromArgb(32, 32, 32);
|
||||
Color titleColor = isFocused ? Color.FromArgb(0, 120, 215) : Color.FromArgb(80, 80, 80);
|
||||
|
||||
canvas.DrawFilledRectangle(bodyColor, x, y, size.Width, size.Height);
|
||||
canvas.DrawFilledRectangle(titleColor, x, y, size.Width, 18);
|
||||
canvas.DrawRectangle(borderColor, x, y, size.Width, size.Height);
|
||||
canvas.DrawFilledRectangle(bodyColor, 0, 0, size.Width, size.Height);
|
||||
canvas.DrawFilledRectangle(titleColor, 0, 0, size.Width, 18);
|
||||
canvas.DrawRectangle(borderColor, 0, 0, size.Width, size.Height);
|
||||
}
|
||||
|
||||
private static void RenderCircle(Canvas canvas, RenderCommand command)
|
||||
{
|
||||
Color color = command.Properties.TryGetValue(nameof(Color), out object? rawColor) && rawColor is Color circleColor
|
||||
Color color = command.Properties.TryGetValue("Color", out object? rawColor) && rawColor is Color circleColor
|
||||
? circleColor
|
||||
: Color.White;
|
||||
|
||||
int radius = command.Properties.TryGetValue(nameof(Radius), out object? rawRadius) && rawRadius is int circleRadius
|
||||
int radius = command.Properties.TryGetValue("Radius", out object? rawRadius) && rawRadius is int circleRadius
|
||||
? circleRadius
|
||||
: 10;
|
||||
|
||||
@@ -60,6 +105,4 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
|
||||
canvas.DrawFilledCircle(color, centerX, centerY, radius);
|
||||
}
|
||||
|
||||
private static string Radius => nameof(Radius);
|
||||
}
|
||||
Reference in New Issue
Block a user