refactor(app): compose atomic frame roots

Move the complete update/render construction graph into a typed Phase-8 owner, explicitly carry the content dependencies it consumes, and publish both roots through one exact lease. Extract lifecycle resource sampling and frame-owned late bindings so partial startup and shutdown withdraw the same generation without window callbacks.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 19:02:08 +02:00
parent 826f9ea9b5
commit 3628aeb520
21 changed files with 1052 additions and 374 deletions

View file

@ -40,10 +40,11 @@ internal interface ISessionPlayerCompositionPhase<in THost, in TContent, in TWor
TLive live);
}
internal interface IFrameRootCompositionPhase<in THost, in TSettings, in TWorld, in TInteraction, in TLive, in TSession, out TResult>
internal interface IFrameRootCompositionPhase<in THost, in TContent, in TSettings, in TWorld, in TInteraction, in TLive, in TSession, out TResult>
{
TResult Compose(
THost host,
TContent content,
TSettings settings,
TWorld world,
TInteraction interaction,
@ -79,7 +80,7 @@ internal sealed class GameWindowCompositionPipeline<
private readonly IInteractionUiCompositionPhase<THost, TContent, TSettings, TWorld, TInteraction> _interaction;
private readonly ILivePresentationCompositionPhase<THost, TContent, TWorld, TInteraction, TLive> _live;
private readonly ISessionPlayerCompositionPhase<THost, TContent, TWorld, TInteraction, TLive, TSession> _session;
private readonly IFrameRootCompositionPhase<THost, TSettings, TWorld, TInteraction, TLive, TSession, TFrame> _frame;
private readonly IFrameRootCompositionPhase<THost, TContent, TSettings, TWorld, TInteraction, TLive, TSession, TFrame> _frame;
private readonly ISessionStartCompositionPhase<TFrame> _start;
public GameWindowCompositionPipeline(
@ -90,7 +91,7 @@ internal sealed class GameWindowCompositionPipeline<
IInteractionUiCompositionPhase<THost, TContent, TSettings, TWorld, TInteraction> interaction,
ILivePresentationCompositionPhase<THost, TContent, TWorld, TInteraction, TLive> live,
ISessionPlayerCompositionPhase<THost, TContent, TWorld, TInteraction, TLive, TSession> session,
IFrameRootCompositionPhase<THost, TSettings, TWorld, TInteraction, TLive, TSession, TFrame> frame,
IFrameRootCompositionPhase<THost, TContent, TSettings, TWorld, TInteraction, TLive, TSession, TFrame> frame,
ISessionStartCompositionPhase<TFrame> start)
{
_host = host ?? throw new ArgumentNullException(nameof(host));
@ -113,7 +114,14 @@ internal sealed class GameWindowCompositionPipeline<
TInteraction interaction = _interaction.Compose(host, content, settings, world);
TLive live = _live.Compose(host, content, world, interaction);
TSession session = _session.Compose(host, content, world, interaction, live);
TFrame frame = _frame.Compose(host, settings, world, interaction, live, session);
TFrame frame = _frame.Compose(
host,
content,
settings,
world,
interaction,
live,
session);
_start.Start(frame);
}
}