feat(studio): headless --screenshot mode (render panel to PNG + exit)
Add `--screenshot <path>` to the UI Studio: when set the window is created hidden (WindowOptions.IsVisible = false), the panel is loaded and rendered into PanelFbo on the first OnRender tick, pixels are read back with the new PanelFbo.ReadColorRgba(), rows are flipped (GL bottom-left → PNG top-left), and the result is saved via ImageSharp SaveAsPng before calling _window.Close(). Render size is derived from the loaded root's Width/Height (clamped 256–2048 px); falls back to 1280×720 when the root has no explicit size. In headless mode ImGui, the inspector, and input wiring are all skipped — only PanelFbo is created. Interactive path is unchanged. SixLabors.ImageSharp 3.1.12 was already a direct dep of AcDream.App (Phase O-T7); no new PackageReference needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e3de7f0dab
commit
f778b100b7
3 changed files with 133 additions and 24 deletions
|
|
@ -67,6 +67,34 @@ public sealed unsafe class PanelFbo : IDisposable
|
|||
return _colorTex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the FBO color attachment back to CPU as a flat RGBA8 byte array.
|
||||
/// Must be called AFTER <see cref="Render"/> for the same <paramref name="width"/> and
|
||||
/// <paramref name="height"/> (so the FBO exists and is the right size).
|
||||
///
|
||||
/// <para>FBO origin is bottom-left (GL convention). The caller is responsible for
|
||||
/// flipping rows vertically before saving as a top-left-origin image format (PNG).</para>
|
||||
///
|
||||
/// <para>Returns an empty array when the FBO is not ready.</para>
|
||||
/// </summary>
|
||||
public unsafe byte[] ReadColorRgba(int width, int height)
|
||||
{
|
||||
if (_fbo == 0 || width <= 0 || height <= 0) return Array.Empty<byte>();
|
||||
|
||||
int byteCount = width * height * 4;
|
||||
var buf = new byte[byteCount];
|
||||
|
||||
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, _fbo);
|
||||
fixed (byte* p = buf)
|
||||
{
|
||||
_gl.ReadPixels(0, 0, (uint)width, (uint)height,
|
||||
PixelFormat.Rgba, PixelType.UnsignedByte, p);
|
||||
}
|
||||
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// ── FBO lifecycle (mirrors PaperdollViewportRenderer.EnsureFramebuffer) ──────
|
||||
|
||||
private void EnsureFramebuffer(int width, int height)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue