fix(rendering): retain withdrawn attachment identities
Separate attached-child spatial withdrawal from logical teardown. ProjectionRemoved now deactivates the retained scene identity, allowing residency or destination-pose callbacks to reactivate it; resource unregister remains the sole destruction edge. Release gate: 3,735 App tests / 3 skips; 8,219 complete-solution tests / 5 skips. Co-Authored-By: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
bb1f4a64bf
commit
81e2f1a575
4 changed files with 81 additions and 12 deletions
|
|
@ -140,13 +140,14 @@ public sealed class LiveRenderProjectionJournalTests
|
|||
Assert.Equal(
|
||||
incarnation,
|
||||
harness.Journal.Pending[0].Record.OwnerIncarnation);
|
||||
Assert.True(harness.Runtime.WithdrawLiveEntityProjection(Guid));
|
||||
harness.Projections.OnProjectionRemoved(record.WorldEntity.Id);
|
||||
harness.Projections.OnProjectionRemoved(record.WorldEntity.Id);
|
||||
Assert.Equal(2, harness.Journal.Count);
|
||||
Assert.Equal(
|
||||
RenderProjectionDeltaKind.Unregister,
|
||||
RenderProjectionDeltaKind.UpdateFlags,
|
||||
harness.Journal.Pending[1].Kind);
|
||||
Assert.Equal(0, harness.Projections.ProjectionCount);
|
||||
Assert.Equal(1, harness.Projections.ProjectionCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -266,7 +267,7 @@ public sealed class LiveRenderProjectionJournalTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void SynchronizeActiveSources_DoesNotResurrectRemovedAttachment()
|
||||
public void SynchronizeActiveSources_DoesNotReactivateWithdrawnAttachment()
|
||||
{
|
||||
Harness harness = CreateHarness(loadLandblock: true);
|
||||
LiveEntityRecord record = Materialize(
|
||||
|
|
@ -277,13 +278,18 @@ public sealed class LiveRenderProjectionJournalTests
|
|||
Assert.True(harness.Projections.OnEntityReady(
|
||||
LiveEntityReadyCandidate.Capture(record)));
|
||||
harness.Journal.DrainTo(harness.Scene);
|
||||
Assert.True(harness.Runtime.WithdrawLiveEntityProjection(Guid));
|
||||
harness.Projections.OnProjectionRemoved(record.WorldEntity!.Id);
|
||||
harness.Journal.DrainTo(harness.Scene);
|
||||
|
||||
harness.Projections.SynchronizeActiveSources();
|
||||
|
||||
Assert.Equal(0, harness.Journal.Count);
|
||||
Assert.Equal(0, harness.Projections.ProjectionCount);
|
||||
Assert.Equal(1, harness.Projections.ProjectionCount);
|
||||
Assert.True(harness.Scene.OpenQuery().TryGet(
|
||||
LiveRenderProjectionJournal.ProjectionId(record.WorldEntity!.Id),
|
||||
out RenderProjectionRecord inactive));
|
||||
Assert.True((inactive.Flags & RenderProjectionFlags.Draw) == 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -298,20 +304,46 @@ public sealed class LiveRenderProjectionJournalTests
|
|||
Assert.True(harness.Projections.OnEntityReady(
|
||||
LiveEntityReadyCandidate.Capture(record)));
|
||||
harness.Journal.DrainTo(harness.Scene);
|
||||
Assert.True(harness.Runtime.WithdrawLiveEntityProjection(Guid));
|
||||
harness.Projections.OnProjectionRemoved(record.WorldEntity!.Id);
|
||||
harness.Journal.DrainTo(harness.Scene);
|
||||
Assert.True(harness.Runtime.RebucketLiveEntity(Guid, CellId));
|
||||
|
||||
harness.Projections.OnProjectionPoseReady(record.ServerGuid);
|
||||
|
||||
RenderProjectionDelta recovered =
|
||||
Assert.Single(harness.Journal.Pending.ToArray());
|
||||
Assert.Equal(RenderProjectionDeltaKind.Register, recovered.Kind);
|
||||
Assert.Equal(
|
||||
RenderProjectionClass.EquippedChild,
|
||||
recovered.Record.ProjectionClass);
|
||||
RenderProjectionDelta recovered = Assert.Single(
|
||||
harness.Journal.Pending.ToArray(),
|
||||
delta => delta.Kind is RenderProjectionDeltaKind.UpdateFlags);
|
||||
Assert.Equal(record.LocalEntityId, recovered.Record.Source.LocalEntityId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WithdrawnAttachment_LogicalTeardownUnregistersRetainedIdentity()
|
||||
{
|
||||
Harness harness = CreateHarness(loadLandblock: true);
|
||||
const ushort instance = 11;
|
||||
LiveEntityRecord record = Materialize(
|
||||
harness,
|
||||
Guid,
|
||||
instance,
|
||||
projectionKind: LiveEntityProjectionKind.Attached);
|
||||
Assert.True(harness.Projections.OnEntityReady(
|
||||
LiveEntityReadyCandidate.Capture(record)));
|
||||
harness.Journal.DrainTo(harness.Scene);
|
||||
Assert.True(harness.Runtime.WithdrawLiveEntityProjection(Guid));
|
||||
harness.Projections.OnProjectionRemoved(record.WorldEntity!.Id);
|
||||
harness.Journal.DrainTo(harness.Scene);
|
||||
|
||||
Assert.True(harness.Runtime.UnregisterLiveEntity(
|
||||
new DeleteObject.Parsed(Guid, instance),
|
||||
isLocalPlayer: false));
|
||||
|
||||
RenderProjectionDelta removed =
|
||||
Assert.Single(harness.Journal.Pending.ToArray());
|
||||
Assert.Equal(RenderProjectionDeltaKind.Unregister, removed.Kind);
|
||||
Assert.Equal(0, harness.Projections.ProjectionCount);
|
||||
}
|
||||
|
||||
private static Harness CreateHarness(bool loadLandblock)
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue