refactor(runtime): extract the live object frame

This commit is contained in:
Erik 2026-07-22 00:42:26 +02:00
parent 99a3e819c4
commit 4e4aac2c5a
27 changed files with 1217 additions and 371 deletions

View file

@ -228,6 +228,16 @@ public sealed class UpdateFrameOrchestratorTests
FieldInfo[] ownerFields = owner.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.DoesNotContain(ownerFields, field => field.FieldType == typeof(GameWindow));
if (owner == typeof(AcDream.App.Input.RetailLocalPlayerFrameController))
{
// Checkpoint B deliberately leaves this single legacy callback
// composition for D/F, which own input capture and the mutable
// player-mode/controller slot. No other phase owner may add one.
Assert.Contains(
ownerFields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
continue;
}
Assert.DoesNotContain(
ownerFields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
@ -274,6 +284,71 @@ public sealed class UpdateFrameOrchestratorTests
Assert.Equal(1, source.Split("PublishTime(", StringSplitOptions.None).Length - 1);
}
[Fact]
public void ExtractedLiveObjectSource_PinsRetailAndRegisteredAdaptationOrder()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Update",
"LiveObjectFrameController.cs"));
AssertAppearsInOrder(
source,
"_localPlayerFrame.AdvanceBeforeNetwork",
"_selectionInteractions?.DrainOutbound",
"_animations.Tick",
"_staticAnimations.Tick",
"_animationPresenter.Present",
"_equippedChildren.Tick",
"_staticAnimations.ProcessHooks",
"_effects.Tick");
AssertAppearsInOrder(
source,
"_translucencyFades.AdvanceAll",
"_animationHooks.Drain",
"_entityEffects.RefreshLiveOwnerPoses",
"_particleSink.RefreshAttachedEmitters",
"_lights.Refresh",
"_particleVisibility.Apply",
"_particles.Tick",
"_scripts.Tick");
AssertAppearsInOrder(
source,
"public void Reconcile()",
"_entityEffects.RefreshLiveOwnerPoses",
"_equippedChildren.Tick",
"_particleSink.RefreshAttachedEmitters",
"_lights.Refresh");
Assert.Equal(1, CountOccurrences(source, "_staticAnimations.Tick("));
Assert.Equal(1, CountOccurrences(source, "_staticAnimations.ProcessHooks("));
Assert.Equal(1, CountOccurrences(source, "_effects.Tick("));
Assert.Equal(1, CountOccurrences(source, "_particles.Tick("));
Assert.Equal(1, CountOccurrences(source, "_scripts.Tick("));
}
[Fact]
public void GameWindow_ComposesTheLiveFrameOwnersWithoutOwningTheirBodies()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
Assert.Contains("new AcDream.App.Update.LiveObjectFrameController(", source);
Assert.Contains("new AcDream.App.Update.LiveSpatialPresentationReconciler(", source);
Assert.Contains("new AcDream.App.World.RetailLiveFrameCoordinator(", source);
Assert.DoesNotContain("AdvanceLiveObjectRuntime", source, StringComparison.Ordinal);
Assert.DoesNotContain("ReconcileLiveObjectSpatialPresentation", source,
StringComparison.Ordinal);
Assert.DoesNotContain("ILiveAnimationPresentationContext", source,
StringComparison.Ordinal);
}
private static UpdateFrameOrchestrator Create(
List<string> calls,
RecordingTeardown? teardown = null,
@ -432,4 +507,19 @@ public sealed class UpdateFrameOrchestratorTests
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
}
private static void AssertAppearsInOrder(string source, params string[] markers)
{
int previous = -1;
foreach (string marker in markers)
{
int current = source.IndexOf(marker, previous + 1, StringComparison.Ordinal);
Assert.True(current >= 0, $"Missing source marker: {marker}");
Assert.True(current > previous, $"Out-of-order source marker: {marker}");
previous = current;
}
}
private static int CountOccurrences(string source, string marker) =>
source.Split(marker, StringSplitOptions.None).Length - 1;
}