Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
BlazorBitmapRenderSurfaceComponent.razor.cs
3using Microsoft.AspNetCore.Components;
4using Microsoft.JSInterop;
5
7
27{
28 private ElementReference _canvasRef;
29 private IJSObjectReference? _module;
30 private DotNetObjectReference<BlazorBitmapRenderSurfaceComponent>? _dotNetRef;
31 private bool _moduleLoaded;
32
34 public BlazorBitmapRenderSurfaceAdapter Adapter { get; private set; } = null!;
35
37 public RenderSurfaceHost<BitmapBackbuffer> Host { get; private set; } = null!;
38
39 internal override ValueTask<CanvasOffset> GetCanvasOffsetAsync()
40 => _module is null ? ValueTask.FromResult(default(CanvasOffset))
41 : _module.InvokeAsync<CanvasOffset>("getCanvasOffset", _canvasRef);
42
43 internal override RenderSurfaceAdapterBase? InputSurfaceAdapter => Adapter;
44
46 protected override void OnInitialized()
47 {
49 Host = new RenderSurfaceHost<BitmapBackbuffer>(Adapter);
50 }
51
53 protected override async Task OnAfterRenderAsync(bool firstRender)
54 {
55 if (!firstRender) return;
56
57 _module = await JS.InvokeAsync<IJSObjectReference>(
58 "import", "./_content/Gondwana.Blazor/gondwana-blazor.js");
59 _moduleLoaded = true;
60 _dotNetRef = DotNetObjectReference.Create(this);
61
62 await _module.InvokeVoidAsync("observeCanvasSize", _canvasRef, _dotNetRef);
63
64 // Get the actual canvas size and update the adapter
65 await UpdateCanvasSizeAsync();
66
67 // Request focus so keyboard events are received without requiring a click.
68 try
69 {
70 await _canvasRef.FocusAsync();
71 }
72 catch
73 {
74 // Focus request is best-effort; ignore failures (e.g. server-side pre-render).
75 }
76 }
77
82 internal async Task UpdateCanvasSizeAsync()
83 {
84 if (!_moduleLoaded || _module is null) return;
85
86 try
87 {
88 var size = await _module.InvokeAsync<CanvasSize>("getCanvasSize", _canvasRef);
89 if (size.Width > 0 && size.Height > 0)
90 {
91 Adapter.UpdateSize(size.Width, size.Height);
92 }
93 }
94 catch
95 {
96 // Size query failed; adapter remains at default 1x1
97 }
98 }
99
105 [JSInvokable]
106 public void OnCanvasSizeChanged(int width, int height)
107 {
108 if (width > 0 && height > 0)
109 {
110 Adapter.UpdateSize(width, height);
111 PresentRetainedFrame();
112 }
113 }
114
125 internal void EnqueueFrame(byte[] rgbaPixels, int width, int height, int x, int y, int canvasWidth, int canvasHeight)
126 {
127 if (!_moduleLoaded || _module is null) return;
128
129 if (_module is IJSInProcessObjectReference inProcessModule)
130 {
131 try
132 {
133 inProcessModule.InvokeVoid("putImageData", _canvasRef, canvasWidth, canvasHeight, width, height, x, y, rgbaPixels, Adapter.Width, Adapter.Height,
134 Adapter.Presentation.DestinationRect.Left, Adapter.Presentation.DestinationRect.Top,
135 Adapter.Presentation.DestinationRect.Width, Adapter.Presentation.DestinationRect.Height,
136 Engine.Instance.Configuration.RenderScalingFilter == RenderScalingFilter.NearestNeighbor);
137 return;
138 }
139 catch
140 {
141 // Fall back to the async path if sync interop is unavailable or fails.
142 }
143 }
144
145 _ = InvokeAsync(async () =>
146 {
147 if (!_moduleLoaded || _module is null) return;
148 await _module.InvokeVoidAsync("putImageData", _canvasRef, canvasWidth, canvasHeight, width, height, x, y, rgbaPixels, Adapter.Width, Adapter.Height,
149 Adapter.Presentation.DestinationRect.Left, Adapter.Presentation.DestinationRect.Top,
150 Adapter.Presentation.DestinationRect.Width, Adapter.Presentation.DestinationRect.Height,
151 Engine.Instance.Configuration.RenderScalingFilter == RenderScalingFilter.NearestNeighbor);
152 });
153 }
154
155 private void PresentRetainedFrame()
156 {
157 if (_module is null) return;
158 var rect = Adapter.Presentation.DestinationRect;
159 _ = _module.InvokeVoidAsync("presentBitmap", _canvasRef, Adapter.Width, Adapter.Height,
160 rect.Left, rect.Top, rect.Width, rect.Height,
161 Engine.Instance.Configuration.RenderScalingFilter == RenderScalingFilter.NearestNeighbor);
162 }
163
165 public override void Dispose()
166 {
167 if (_moduleLoaded && _module is not null)
168 {
169 try
170 {
171 if (_module is IJSInProcessObjectReference inProcessModule)
172 {
173 inProcessModule.InvokeVoid("unobserveCanvasSize", _canvasRef);
174 }
175 else
176 {
177 _ = _module.InvokeVoidAsync("unobserveCanvasSize", _canvasRef);
178 }
179 }
180 catch
181 {
182 // Observer cleanup is best-effort during disposal.
183 }
184 }
185
186 _dotNetRef?.Dispose();
187 _dotNetRef = null;
188 _ = _module?.DisposeAsync();
189 _module = null;
190 _moduleLoaded = false;
191
192 Adapter?.Dispose();
193 Host?.Dispose();
194 }
195
196 private sealed class CanvasSize
197 {
201 public int Width { get; set; }
202
206 public int Height { get; set; }
207 }
208}
Provides a bitmap (CPU) render surface adapter for Blazor that presents each frame by converting pixe...
A Blazor component that presents Gondwana game frames on an HTML <canvas> element and forwards keyboa...
void OnCanvasSizeChanged(int width, int height)
Updates the adapter after JavaScript observes a canvas client-size change.
BlazorBitmapRenderSurfaceAdapter Adapter
Gets the render surface adapter that drives this component.
RenderSurfaceHost< BitmapBackbuffer > Host
Gets the RenderSurfaceHost<T> bound to this component.
Provides the shared DOM input surface used by Gondwana's Blazor bitmap and GPU render components.
Represents the core game engine singleton responsible for managing the main update loop,...
Definition Engine.cs:36
static Engine Instance
Gets the singleton instance of the Engine.
Definition Engine.cs:49
EngineConfiguration Configuration
Gets the current engine configuration settings.
Definition Engine.cs:928
Represents the abstract base class for render surface adapters that present backbuffer output to a de...
int Width
Gets the current width of the render surface in pixels.
PresentationTransform Presentation
Current immutable aspect-preserving mapping of Backbuffer ScreenPx to adapter pixels.
int Height
Gets the current height of the render surface in pixels.
RenderScalingFilter
Filtering used only when presenting the finished Backbuffer.