Clear ADV History presentation on exit

This commit is contained in:
gamer147
2026-07-19 11:32:36 -04:00
parent c30cf6cb08
commit 538e87d368
7 changed files with 46 additions and 3 deletions

View File

@@ -1393,6 +1393,12 @@ Label and independently animated wait marker. Native rendering gets this layerin
part of retained composition; the port must state it explicitly because those two elements are separate part of retained composition; the port must state it explicitly because those two elements are separate
Godot overlays. They reappear with the same parked page after the modal frame returns. Godot overlays. They reappear with the same parked page after the modal frame returns.
History's target-layout render batches are likewise presentation bindings, not part of the retained backlog.
`HISTORY.BIN@0x1100` re-enables recording with op `0x1bb(1)` after erasing its object range and releasing
surfaces `0xc0/0xc1`; that existing exit boundary now tells the host to discard all bound History batches.
The semantic text/index records remain untouched, so reopening History rebuilds fresh rows while exiting
cannot leave the old labels above the resumed ADV page.
History's remaining work is stored voice replay through `0x1bd` and the `0xd3/0xd4/0xd5` smooth-scroll History's remaining work is stored voice replay through `0x1bd` and the `0xd3/0xd4/0xd5` smooth-scroll
callback scheduler. None changes backlog ownership or requires choosing a save/profile backend. callback scheduler. None changes backlog ownership or requires choosing a save/profile backend.

View File

@@ -1801,6 +1801,12 @@ class of inherited-state bridges.
Godot also suppresses the parked page's ordinary dialogue Label and wait indicator while any nested timed Godot also suppresses the parked page's ordinary dialogue Label and wait indicator while any nested timed
raw-input frame owns the modal screen, then restores them on return. Root Control anchor presets are now raw-input frame owns the modal screen, then restores them on return. Root Control anchor presets are now
applied after parenting, removing the remaining occurrence of the associated runtime layout diagnostic. applied after parenting, removing the remaining occurrence of the associated runtime layout diagnostic.
A follow-up exit check found that the host retained the last History render batches after the script had
erased its objects and re-enabled recording. Op `0x1bb(1)` at `HISTORY.BIN@0x1100` is now the presentation
end boundary: it clears only the host's transient layout bindings, leaving the engine-owned backlog intact
for the next opening. The real interaction regression requires zero active History batches after return.
Validation: engine 198/198, zero-warning Godot build, threaded `SELFTEST OK`, and vm0 RECOVER clean. Validation: engine 198/198, zero-warning Godot build, threaded `SELFTEST OK`, and vm0 RECOVER clean.
**Next:** manually recheck the five History rows and overlay cleanup against the original. If they match, proceed **Next:** manually recheck the five History rows and overlay cleanup against the original. If they match, proceed

View File

@@ -167,6 +167,8 @@ public class HistoryInteractionOpsTests
Assert.True(host.SawRenderedText); Assert.True(host.SawRenderedText);
Assert.True(host.HistoryReturned); Assert.True(host.HistoryReturned);
Assert.Equal(1, host.Waits); // the enclosing ADV page was never released or re-entered Assert.Equal(1, host.Waits); // the enclosing ADV page was never released or re-entered
Assert.Equal(1, host.HistoryPresentationEnds);
Assert.Empty(host.ActiveHistoryRenders);
var historyButtons = host.FirstHistoryFrame var historyButtons = host.FirstHistoryFrame
.Where(render => render.Handle >= 0xd2fa && render.Handle <= 0xd300) .Where(render => render.Handle >= 0xd2fa && render.Handle <= 0xd300)

View File

@@ -18,6 +18,8 @@ internal class RecordingHost : IHost
public readonly List<(int Slot, int X, int Y)> TextCursors = new(); public readonly List<(int Slot, int X, int Y)> TextCursors = new();
public readonly List<(int Surface, int X, int Y, string Text)> SurfaceStrings = new(); public readonly List<(int Surface, int X, int Y, string Text)> SurfaceStrings = new();
public readonly List<AdvTextHistoryRenderBatch> HistoryRenders = new(); public readonly List<AdvTextHistoryRenderBatch> HistoryRenders = new();
public readonly Dictionary<int, AdvTextHistoryRenderBatch> ActiveHistoryRenders = new();
public int HistoryPresentationEnds;
public readonly List<int> ClearedTextLayouts = new(); public readonly List<int> ClearedTextLayouts = new();
public readonly List<SurfaceRectFill> SurfaceFills = new(); public readonly List<SurfaceRectFill> SurfaceFills = new();
public readonly List<(long First, long Count)> PresentedRanges = new(); public readonly List<(long First, long Count)> PresentedRanges = new();
@@ -38,8 +40,21 @@ internal class RecordingHost : IHost
=> SurfaceStrings.Add((surfaceSlot, x, y, text)); => SurfaceStrings.Add((surfaceSlot, x, y, text));
public void DrawStringToSurface(int surfaceSlot, int x, int y, string text, AdvTextStyle style) public void DrawStringToSurface(int surfaceSlot, int x, int y, string text, AdvTextStyle style)
=> SurfaceStrings.Add((surfaceSlot, x, y, text)); => SurfaceStrings.Add((surfaceSlot, x, y, text));
public void ClearRenderedAdvTextLayout(int layoutSlot) => ClearedTextLayouts.Add(layoutSlot); public void ClearRenderedAdvTextLayout(int layoutSlot)
public void RenderTextHistory(AdvTextHistoryRenderBatch batch) => HistoryRenders.Add(batch); {
ClearedTextLayouts.Add(layoutSlot);
ActiveHistoryRenders.Remove(layoutSlot);
}
public void RenderTextHistory(AdvTextHistoryRenderBatch batch)
{
HistoryRenders.Add(batch);
ActiveHistoryRenders[batch.LayoutSlot] = batch;
}
public void EndTextHistoryPresentation()
{
HistoryPresentationEnds++;
ActiveHistoryRenders.Clear();
}
public int MessageWindowAlphaSetting { get; set; } public int MessageWindowAlphaSetting { get; set; }
public void FillSurfaceRect(SurfaceRectFill fill) => SurfaceFills.Add(fill); public void FillSurfaceRect(SurfaceRectFill fill) => SurfaceFills.Add(fill);
public void PresentObjectRange(GfxState gfx, long firstHandle, long count) public void PresentObjectRange(GfxState gfx, long firstHandle, long count)

View File

@@ -24,6 +24,9 @@ public interface IHost
=> DrawStringToSurface(surfaceSlot, x, y, text); => DrawStringToSurface(surfaceSlot, x, y, text);
void ClearRenderedAdvTextLayout(int layoutSlot) { } void ClearRenderedAdvTextLayout(int layoutSlot) { }
void RenderTextHistory(AdvTextHistoryRenderBatch batch) { } void RenderTextHistory(AdvTextHistoryRenderBatch batch) { }
// History render batches are transient bindings, unlike the retained backlog itself. HISTORY.BIN's
// recording re-enable at exit ends that presentation and drops every bound target layout.
void EndTextHistoryPresentation() { }
int MessageWindowAlphaSetting => 0; int MessageWindowAlphaSetting => 0;
void FillSurfaceRect(SurfaceRectFill fill) { } void FillSurfaceRect(SurfaceRectFill fill) { }
void PresentObjectRange(GfxState gfx, long firstHandle, long count) { } void PresentObjectRange(GfxState gfx, long firstHandle, long count) { }

View File

@@ -772,7 +772,12 @@ public sealed class VirtualMachine
case "reset-message-voice-state": // 0x1bc resets native per-message voice/queued-voice state case "reset-message-voice-state": // 0x1bc resets native per-message voice/queued-voice state
_autoVoicePending = false; return pc + 1; _autoVoicePending = false; return pc + 1;
case "set-text-history-recording": // 0x1bb: HISTORY.BIN suppresses recording its own UI case "set-text-history-recording": // 0x1bb: HISTORY.BIN suppresses recording its own UI
if (Read(a[0]) is 0 or 1) TextHistory.SetRecordingEnabled(Read(a[0]) == 1); if (Read(a[0]) is 0 or 1)
{
bool enabled = Read(a[0]) == 1;
TextHistory.SetRecordingEnabled(enabled);
if (enabled) _host.EndTextHistoryPresentation();
}
return pc + 1; return pc + 1;
case "append-text-history-metadata": // 0x1d2: typed value attached to the current group case "append-text-history-metadata": // 0x1d2: typed value attached to the current group
TextHistory.AppendMetadata(Read(a[0]), Read(a[1]), _advTextStyle); return pc + 1; TextHistory.AppendMetadata(Read(a[0]), Read(a[1]), _advTextStyle); return pc + 1;

View File

@@ -149,6 +149,12 @@ public sealed class GodotAdvHost : IHost
}); });
} }
public void EndTextHistoryPresentation()
{
lock (_textLock) _historyText.Clear();
_timeline?.Event("history-presentation-end");
}
public IReadOnlyList<AdvTextHistoryRenderBatch> SnapshotRenderedTextHistory() public IReadOnlyList<AdvTextHistoryRenderBatch> SnapshotRenderedTextHistory()
{ {
lock (_textLock) return _historyText.Values.OrderBy(batch => batch.LayoutSlot).ToArray(); lock (_textLock) return _historyText.Values.OrderBy(batch => batch.LayoutSlot).ToArray();