Split input host contract

This commit is contained in:
gamer147
2026-08-03 10:56:47 -04:00
parent 3d807e6115
commit c5204341a3
4 changed files with 62 additions and 38 deletions

View File

@@ -169,7 +169,9 @@ simple hosts. `engine/Age.Engine/Hosting/IMovieHost.cs` owns ordinary, positione
and modal movie playback contracts. `IHost` inherits all four focused contracts; their required and default and modal movie playback contracts. `IHost` inherits all four focused contracts; their required and default
behavior is unchanged. `engine/Age.Engine/Hosting/IGraphicsHost.cs` owns mutable surfaces, retained-range/frame behavior is unchanged. `engine/Age.Engine/Hosting/IGraphicsHost.cs` owns mutable surfaces, retained-range/frame
presentation, transitions, texture lifecycle, pixel capture/replace, draw, and size contracts; `IHost` also presentation, transitions, texture lifecycle, pixel capture/replace, draw, and size contracts; `IHost` also
inherits this focused surface without changing existing hosts. The neutral inherits this focused surface without changing existing hosts. `engine/Age.Engine/Hosting/IInputHost.cs` owns
modal fullwidth entry, ADV waits/callback servicing, input clock, cursor resources, and skip-state interaction;
its required wait and overload/default chains remain unchanged. The neutral
`engine/Age.Engine/Model/MovieMaskTransitionRequest.cs` record carries movie mask work between the VM, host, and `engine/Age.Engine/Model/MovieMaskTransitionRequest.cs` record carries movie mask work between the VM, host, and
retained graphics without making `Model` depend on `Hosting`. retained graphics without making `Model` depend on `Hosting`.
`engine/Age.Engine/Model/RgbaImage.cs` owns the format-independent packed RGBA image transported between SYS4 `engine/Age.Engine/Model/RgbaImage.cs` owns the format-independent packed RGBA image transported between SYS4

View File

@@ -798,6 +798,12 @@ do not mix mechanical moves with semantic changes.
imported `Model`, so no call sites changed; surface request shape, enum values, and graphics behavior remain imported `Model`, so no call sites changed; surface request shape, enum values, and graphics behavior remain
unchanged. Runtime validation remains green. unchanged. Runtime validation remains green.
The eighth bounded contract slice introduced `IInputHost` for modal fullwidth entry, ADV wait overloads and
callback servicing, input clock, cursor resources, and skip-state interaction. `IHost` inherits the focused
contract; all fourteen members, the required base wait, overload/default chains, and existing host classes
remain behaviorally unchanged. Input transport records remain in their prior locations pending a separate
cleanup. Runtime validation remains green.
4. **Make the build graph express source ownership.** Stop linking production `.cs` files from `godot/` and 4. **Make the build graph express source ownership.** Stop linking production `.cs` files from `godot/` and
`tools/movie-corpus-gate/` into `Age.Engine.Tests`. Extract the platform-neutral frontend/movie/diagnostic `tools/movie-corpus-gate/` into `Age.Engine.Tests`. Extract the platform-neutral frontend/movie/diagnostic
code into a small production project referenced by Godot, tests, and the corpus gate. Retain both existing code into a small production project referenced by Godot, tests, and the corpus gate. Retain both existing
@@ -1158,9 +1164,8 @@ layer's rendering diverges from ADV; save layout.
## 8. Immediate next step ## 8. Immediate next step
Continue step 3 of the **codebase consolidation** maintenance slice: clarify runtime contracts without changing Continue step 3 of the **codebase consolidation** maintenance slice: clarify runtime contracts without changing
behavior or the aggregate host accepted by the VM. With diagnostic, lifecycle, audio, and movie contracts behavior or the aggregate host accepted by the VM. With diagnostic, lifecycle, audio, and movie contracts
established beneath `IHost`, shared movie/image transport neutral, and the graphics contract now separated, move established beneath `IHost`, shared graphics transport neutral, and graphics/input contracts now separated, move
the input host contract next: modal text entry, ADV waits and callback servicing, input clock, cursor resources, the unchanged `FullwidthTextEditRequest`, `FullwidthTextEditResult`, and `AdvAutoWaitState` declarations from
and skip-state interaction. Preserve the existing overload/default chains and aggregate `IHost` entry point before `Hosting` to `Model` next. Preserve all consumers before extracting the remaining ADV text/presentation contract.
separating the remaining ADV text/presentation contract.
Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does
not replace Phase B gameplay validation or the open cross-platform gates. not replace Phase B gameplay validation or the open cross-platform gates.

View File

@@ -27,11 +27,8 @@ public readonly record struct DiagnosticMessage(string Caption, string Text);
public readonly record struct FullwidthTextEditRequest(string CurrentText, string InitialText); public readonly record struct FullwidthTextEditRequest(string CurrentText, string InitialText);
public readonly record struct FullwidthTextEditResult(bool Accepted, string Text); public readonly record struct FullwidthTextEditResult(bool Accepted, string Text);
public interface IHost : IDiagnosticHost, ILifecycleHost, IAudioHost, IMovieHost, IGraphicsHost public interface IHost : IDiagnosticHost, ILifecycleHost, IAudioHost, IMovieHost, IGraphicsHost, IInputHost
{ {
/// <summary>Present AGERc's modal full-width editor. Cancel preserves CurrentText.</summary>
FullwidthTextEditResult EditFullwidthString(FullwidthTextEditRequest request)
=> new(false, request.CurrentText);
void ShowText(int offset, string text); void ShowText(int offset, string text);
void ShowText(AdvLiveTextRun run, int glyphDelayMilliseconds) void ShowText(AdvLiveTextRun run, int glyphDelayMilliseconds)
=> ShowText(run.SourceOffset, run.Text); => ShowText(run.SourceOffset, run.Text);
@@ -89,33 +86,4 @@ public interface IHost : IDiagnosticHost, ILifecycleHost, IAudioHost, IMovieHost
void SetAdvPagePresentationSuspended(bool suspended) { } void SetAdvPagePresentationSuspended(bool suspended) { }
void SetAdvPagePresentationSuspended(GfxState gfx, bool suspended) void SetAdvPagePresentationSuspended(GfxState gfx, bool suspended)
=> SetAdvPagePresentationSuspended(suspended); => SetAdvPagePresentationSuspended(suspended);
void WaitForInput();
void WaitForInput(int layoutSlot) => WaitForInput();
// Interactive hosts service script callbacks on the VM thread while the enclosing ADV page remains
// parked. The callback returns true while another queued input callback is ready to run.
void WaitForInput(int layoutSlot, Func<bool> serviceInputCallback)
{
while (serviceInputCallback()) { }
WaitForInput(layoutSlot);
}
void WaitForInput(int layoutSlot, Func<bool> serviceInputCallback,
Func<AdvAutoWaitState> autoWaitState)
=> WaitForInput(layoutSlot, serviceInputCallback);
void WakeInputCallbackService() { }
void InputCallbackCompleted(GfxState gfx) { }
// Generic AGE input-callback services (ops 0xcc/0xcd, 0xfb/0xff/0x100, 0x108).
// Interactive hosts expose the same monotonic clock used by their frame scheduler.
long InputClockMilliseconds => Environment.TickCount64;
void SetCursorResource(long resourceId) { }
void ClearCursorResource() { }
// Native 0x1c7/0x1cc query two distinct ADV skip channels. Headless and non-interactive
// hosts default to normal playback; the Godot host supplies the live interactive values.
void SetMessageSkipActive(bool active) { }
// Logical action 6 is the native hold-to-fast-forward channel. Keep it separate from the
// persistent op-0x88 channel so releasing the key cannot turn off the user's Skip toggle.
void SetPhysicalMessageSkipActive(bool active) { }
bool IsMessageSkipActive => false;
// Optional diagnostic override. Native ReadTextDB state is VM/profile-owned; interactive hosts
// normally leave this false.
bool IsAdvReadSkipActive => false;
} }

View File

@@ -0,0 +1,49 @@
using Age.Engine.Model;
namespace Age.Engine.Hosting;
public interface IInputHost
{
/// <summary>Present AGERc's modal full-width editor. Cancel preserves CurrentText.</summary>
FullwidthTextEditResult EditFullwidthString(FullwidthTextEditRequest request)
=> new(false, request.CurrentText);
void WaitForInput();
void WaitForInput(int layoutSlot) => WaitForInput();
// Interactive hosts service script callbacks on the VM thread while the enclosing ADV page remains
// parked. The callback returns true while another queued input callback is ready to run.
void WaitForInput(int layoutSlot, Func<bool> serviceInputCallback)
{
while (serviceInputCallback()) { }
WaitForInput(layoutSlot);
}
void WaitForInput(int layoutSlot, Func<bool> serviceInputCallback,
Func<AdvAutoWaitState> autoWaitState)
=> WaitForInput(layoutSlot, serviceInputCallback);
void WakeInputCallbackService() { }
void InputCallbackCompleted(GfxState gfx) { }
// Generic AGE input-callback services (ops 0xcc/0xcd, 0xfb/0xff/0x100, 0x108).
// Interactive hosts expose the same monotonic clock used by their frame scheduler.
long InputClockMilliseconds => Environment.TickCount64;
void SetCursorResource(long resourceId) { }
void ClearCursorResource() { }
// Native 0x1c7/0x1cc query two distinct ADV skip channels. Headless and non-interactive
// hosts default to normal playback; the Godot host supplies the live interactive values.
void SetMessageSkipActive(bool active) { }
// Logical action 6 is the native hold-to-fast-forward channel. Keep it separate from the
// persistent op-0x88 channel so releasing the key cannot turn off the user's Skip toggle.
void SetPhysicalMessageSkipActive(bool active) { }
bool IsMessageSkipActive => false;
// Optional diagnostic override. Native ReadTextDB state is VM/profile-owned; interactive hosts
// normally leave this false.
bool IsAdvReadSkipActive => false;
}