Render assessed creatures through the shared private viewport with retail heading, bounding-box camera, and light. Build the exact authored nine-row stat list and resolve creature names from the retail EnumMapper while keeping remaining font/sequencer adaptations explicit. Co-authored-by: Codex <codex@openai.com>
172 lines
5.8 KiB
C#
172 lines
5.8 KiB
C#
using System.Numerics;
|
|
using AcDream.App.Diagnostics;
|
|
using AcDream.App.Streaming;
|
|
using AcDream.App.UI;
|
|
using Silk.NET.Input;
|
|
|
|
namespace AcDream.App.Rendering;
|
|
|
|
internal interface IPrivatePortalViewport
|
|
{
|
|
void Draw(int width, int height);
|
|
}
|
|
|
|
internal interface IPrivateEntityViewportFrame
|
|
{
|
|
void Render();
|
|
}
|
|
|
|
internal interface IRetainedGameplayUiFrame
|
|
{
|
|
void Render(double deltaSeconds, int width, int height);
|
|
}
|
|
|
|
internal interface IPrivateFrameScreenshot
|
|
{
|
|
bool CapturePending(int width, int height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws the private and 2-D presentation layers after the world alpha scope
|
|
/// has closed: portal CreatureMode, paperdoll FBO, retained gameplay UI,
|
|
/// developer UI, then the complete-frame screenshot.
|
|
/// </summary>
|
|
internal sealed class PrivatePresentationRenderer : IPrivatePresentationFramePhase
|
|
{
|
|
private readonly IPrivatePortalViewport _portal;
|
|
private readonly IRenderFrameFoundationSource _foundation;
|
|
private readonly IPrivateEntityViewportFrame? _entityViewports;
|
|
private readonly IRetainedGameplayUiFrame? _gameplayUi;
|
|
private readonly IDevToolsFrameLifecycle? _devTools;
|
|
private readonly IPrivateFrameScreenshot? _screenshots;
|
|
|
|
public PrivatePresentationRenderer(
|
|
IPrivatePortalViewport portal,
|
|
IRenderFrameFoundationSource foundation,
|
|
IPrivateEntityViewportFrame? entityViewports,
|
|
IRetainedGameplayUiFrame? gameplayUi,
|
|
IDevToolsFrameLifecycle? devTools,
|
|
IPrivateFrameScreenshot? screenshots)
|
|
{
|
|
_portal = portal ?? throw new ArgumentNullException(nameof(portal));
|
|
_foundation = foundation
|
|
?? throw new ArgumentNullException(nameof(foundation));
|
|
_entityViewports = entityViewports;
|
|
_gameplayUi = gameplayUi;
|
|
_devTools = devTools;
|
|
_screenshots = screenshots;
|
|
}
|
|
|
|
public PrivatePresentationFrameOutcome Render(
|
|
RenderFrameInput input,
|
|
WorldRenderFrameOutcome world)
|
|
{
|
|
_ = world;
|
|
// Foundation is the immutable result of this frame's clear phase.
|
|
// Snapshot it before drawing so a portal transition raised by a
|
|
// private layer cannot relabel the viewport that was just presented.
|
|
bool portalViewportVisible =
|
|
_foundation.Foundation.PortalViewportVisible;
|
|
_portal.Draw(input.ViewportWidth, input.ViewportHeight);
|
|
_entityViewports?.Render();
|
|
_gameplayUi?.Render(
|
|
input.DeltaSeconds,
|
|
input.ViewportWidth,
|
|
input.ViewportHeight);
|
|
_devTools?.Render(
|
|
input.DeltaSeconds,
|
|
input.ViewportWidth,
|
|
input.ViewportHeight);
|
|
bool screenshotCaptured = _screenshots?.CapturePending(
|
|
input.ViewportWidth,
|
|
input.ViewportHeight) == true;
|
|
return new PrivatePresentationFrameOutcome(
|
|
portalViewportVisible,
|
|
screenshotCaptured);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ordered private creature-view presentation. Retail renders each visible
|
|
/// <c>CreatureMode</c> before the retained 2-D tree that displays its texture.
|
|
/// </summary>
|
|
internal sealed class PrivateEntityViewportFrameGroup :
|
|
IPrivateEntityViewportFrame
|
|
{
|
|
private readonly IPrivateEntityViewportFrame[] _frames;
|
|
|
|
public PrivateEntityViewportFrameGroup(
|
|
params IPrivateEntityViewportFrame?[] frames)
|
|
{
|
|
_frames = frames.Where(static frame => frame is not null)
|
|
.Cast<IPrivateEntityViewportFrame>()
|
|
.ToArray();
|
|
}
|
|
|
|
public void Render()
|
|
{
|
|
foreach (IPrivateEntityViewportFrame frame in _frames)
|
|
frame.Render();
|
|
}
|
|
}
|
|
|
|
/// <summary>Typed portal viewport adapter over the canonical teleport owner.</summary>
|
|
internal sealed class LocalPlayerPortalViewport : IPrivatePortalViewport
|
|
{
|
|
private readonly LocalPlayerTeleportController _teleport;
|
|
private readonly CameraController _camera;
|
|
|
|
public LocalPlayerPortalViewport(
|
|
LocalPlayerTeleportController teleport,
|
|
CameraController camera)
|
|
{
|
|
_teleport = teleport ?? throw new ArgumentNullException(nameof(teleport));
|
|
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
|
|
}
|
|
|
|
public void Draw(int width, int height) =>
|
|
_teleport.DrawPortalViewport(width, height, _camera.Active.Projection);
|
|
}
|
|
|
|
/// <summary>
|
|
/// One retained-gameplay-UI tick/cursor/draw transaction. This is the explicit
|
|
/// boundary where the render graph reaches the retained UI composition owner;
|
|
/// <see cref="RetailUiRuntime"/> intentionally retains its documented state and
|
|
/// command bindings. The distinction between direct frame ownership and
|
|
/// recursive shared-owner reachability is recorded in
|
|
/// docs/architecture/code-structure.md.
|
|
/// </summary>
|
|
internal sealed class RetainedGameplayUiFrame : IRetainedGameplayUiFrame
|
|
{
|
|
private readonly RetailUiRuntime _runtime;
|
|
private readonly IInputContext? _input;
|
|
|
|
public RetainedGameplayUiFrame(
|
|
RetailUiRuntime runtime,
|
|
IInputContext? input)
|
|
{
|
|
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
|
_input = input;
|
|
}
|
|
|
|
public void Render(double deltaSeconds, int width, int height)
|
|
{
|
|
_runtime.Tick(deltaSeconds);
|
|
if (_input is not null)
|
|
_runtime.UpdateCursor(_input.Mice);
|
|
_runtime.Draw(new Vector2(width, height));
|
|
}
|
|
}
|
|
|
|
/// <summary>Optional complete-frame capture adapter.</summary>
|
|
internal sealed class PrivateFrameScreenshot : IPrivateFrameScreenshot
|
|
{
|
|
private readonly FrameScreenshotController _screenshots;
|
|
|
|
public PrivateFrameScreenshot(FrameScreenshotController screenshots) =>
|
|
_screenshots = screenshots
|
|
?? throw new ArgumentNullException(nameof(screenshots));
|
|
|
|
public bool CapturePending(int width, int height) =>
|
|
_screenshots.CapturePending(width, height);
|
|
}
|