feat(render): Campaign V slice V11 commit 1 - delete ImGui, Studio, and the DevTools frontend
The ImGui developer-tools stack (AcDream.UI.ImGui), UI Studio (src/AcDream.App/Studio), and the DevToolsFramePresenter/ SettingsDevToolsCompositionPhase ImGui composition machinery are removed. Vulkan never composed a DevTools frontend (DevToolsEnabled already forced false whenever the backend was Vulkan); this commit makes that permanent by deleting the only implementation rather than leaving a dead branch behind. What moved: Studio/SampleData.cs is a live production dependency (InteractionRetainedUiComposition's character-sheet fallback, plus three UI.Layout test files) - git mv'd to src/AcDream.App/UI/Layout/SampleData.cs, namespace AcDream.App.UI.Layout, and trimmed to the SampleCharacter API that is actually still called (BuildObjectTable/AddItem/AddEquipped/the item-guid and icon constants had zero callers left once the Studio fixture provider that used them was deleted). What survives as backend-neutral seams, per the tests that still exercise them: IDevToolsFrameLifecycle (moved into RenderFramePreparationController.cs, now always bound to null), IFramebufferDevToolsTarget/FramebufferDevToolsBinding in FramebufferResizeController.cs (its concrete DevToolsFramebufferTarget adapter is deleted), and IDevToolsGameplayCommands in GameplayInputCommandController.cs (DevToolsGameplayCommands becomes a documented no-op instead of forwarding to the deleted presenter). A follow-up re-homes Settings/Debug onto the retained UI through IPanelRenderer; until then keybind remapping falls back to editing keybinds.json. DevToolsEnabled is now `private const bool DevToolsEnabled = false`. RuntimeOptions.DevTools is unchanged and still reaches VulkanGraphicsContext for the optional debug-utils extensions; Program.cs now logs one line when ACDREAM_DEVTOOLS=1 explaining that the ImGui UI is gone and the flag is Vulkan-only now. Removed: AcDream.UI.ImGui (project + ImGui.NET/Silk.NET.OpenGL.Extensions.ImGui package refs), src/AcDream.App/Studio (minus SampleData.cs), DevToolsFramePresenter.cs and everything only it constructed (ISettingsDevToolsCompositionFactory, RetailSettingsDevToolsCompositionFactory, DevToolsCompositionOwner, IGameWindowSettingsDevToolsPublication, SettingsDevToolsOptionalDependencies, the "developer tools" shutdown-ledger stage and its DevTools-typed fields on IngressShutdownRoots/ RenderShutdownRoots), the ui-studio Program.cs verb, and the cimgui native manifest entries in GraphicalHostPlatformServices. GameWindow.cs's DevTools composition branch, its _vitalsVm/_debugVm/_devToolsComposition/ _devToolsFramePresenter/_devToolsCommandBus fields, and every settingsDevTools .DevTools?.* access across FrameRootComposition.cs/SessionPlayerComposition.cs are gone with it. Build green; complete Release solution suite 8,830 / 5 skips (App Tests 4,097/3 skips run standalone - one #250-family zero-allocation test flakes under the full parallel `dotnet test AcDream.slnx` run, a pre-existing, documented class unrelated to this change). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
db4426d5ef
commit
844cf092a1
48 changed files with 227 additions and 6201 deletions
|
|
@ -1,491 +0,0 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Input;
|
||||
using AcDream.App.Net;
|
||||
using AcDream.UI.Abstractions;
|
||||
using AcDream.UI.Abstractions.Panels.Chat;
|
||||
using AcDream.UI.Abstractions.Panels.Debug;
|
||||
using AcDream.UI.Abstractions.Panels.Settings;
|
||||
using AcDream.UI.Abstractions.Panels.Vitals;
|
||||
using AcDream.UI.ImGui;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
internal enum DevToolsPanelLayoutCondition
|
||||
{
|
||||
FirstUseEver,
|
||||
Always,
|
||||
}
|
||||
|
||||
internal enum DevToolsPanelKind
|
||||
{
|
||||
Vitals,
|
||||
Chat,
|
||||
Debug,
|
||||
Settings,
|
||||
}
|
||||
|
||||
internal interface IDevToolsFrameLifecycle : IRenderFrameFailureRecovery
|
||||
{
|
||||
void BeginFrame(float deltaSeconds);
|
||||
|
||||
void Render(double deltaSeconds, int viewportWidth, int viewportHeight);
|
||||
}
|
||||
|
||||
internal interface IDevToolsFrameBackend : IDisposable
|
||||
{
|
||||
void BeginFrame(float deltaSeconds);
|
||||
|
||||
void AbortFrame();
|
||||
|
||||
bool BeginMainMenuBar();
|
||||
|
||||
void EndMainMenuBar();
|
||||
|
||||
bool BeginMenu(string label);
|
||||
|
||||
void EndMenu();
|
||||
|
||||
bool MenuItem(string label, string? shortcut = null, bool selected = false);
|
||||
|
||||
void Separator();
|
||||
|
||||
void RenderPanels(PanelContext context);
|
||||
|
||||
void RenderDrawData();
|
||||
|
||||
void SetWindowLayout(
|
||||
string title,
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
DevToolsPanelLayoutCondition condition);
|
||||
}
|
||||
|
||||
internal interface IDevToolsCameraMenuOperations
|
||||
{
|
||||
bool IsFlyMode { get; }
|
||||
|
||||
bool CollideCamera { get; set; }
|
||||
|
||||
void ToggleFlyOrChase();
|
||||
}
|
||||
|
||||
internal interface IDevToolsCommandBusSource
|
||||
{
|
||||
ICommandBus Current { get; }
|
||||
}
|
||||
|
||||
internal interface IDevToolsPanelSet
|
||||
{
|
||||
bool Contains(DevToolsPanelKind kind);
|
||||
|
||||
string? GetTitle(DevToolsPanelKind kind);
|
||||
|
||||
bool IsVisible(DevToolsPanelKind kind);
|
||||
|
||||
void Toggle(DevToolsPanelKind kind);
|
||||
|
||||
void FocusChatInput();
|
||||
|
||||
void AddDebugToast(string message);
|
||||
}
|
||||
|
||||
/// <summary>Concrete ImGui backend for the developer presentation owner.</summary>
|
||||
internal sealed class ImGuiDevToolsFrameBackend : IDevToolsFrameBackend, IDisposable
|
||||
{
|
||||
private readonly IImGuiBootstrapper _bootstrap;
|
||||
private readonly ImGuiPanelHost _panels;
|
||||
private bool _disposed;
|
||||
|
||||
public ImGuiDevToolsFrameBackend(
|
||||
IImGuiBootstrapper bootstrap,
|
||||
ImGuiPanelHost panels)
|
||||
{
|
||||
_bootstrap = bootstrap ?? throw new ArgumentNullException(nameof(bootstrap));
|
||||
_panels = panels ?? throw new ArgumentNullException(nameof(panels));
|
||||
}
|
||||
|
||||
public void BeginFrame(float deltaSeconds) => _bootstrap.BeginFrame(deltaSeconds);
|
||||
|
||||
public void AbortFrame() => _bootstrap.AbortFrame();
|
||||
|
||||
public bool BeginMainMenuBar() => ImGuiNET.ImGui.BeginMainMenuBar();
|
||||
|
||||
public void EndMainMenuBar() => ImGuiNET.ImGui.EndMainMenuBar();
|
||||
|
||||
public bool BeginMenu(string label) => ImGuiNET.ImGui.BeginMenu(label);
|
||||
|
||||
public void EndMenu() => ImGuiNET.ImGui.EndMenu();
|
||||
|
||||
public bool MenuItem(string label, string? shortcut = null, bool selected = false) =>
|
||||
ImGuiNET.ImGui.MenuItem(label, shortcut ?? string.Empty, selected);
|
||||
|
||||
public void Separator() => ImGuiNET.ImGui.Separator();
|
||||
|
||||
public void RenderPanels(PanelContext context) => _panels.RenderAll(context);
|
||||
|
||||
public void RenderDrawData() => _bootstrap.Render();
|
||||
|
||||
public void SetWindowLayout(
|
||||
string title,
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
DevToolsPanelLayoutCondition condition)
|
||||
{
|
||||
ImGuiCond imguiCondition = condition switch
|
||||
{
|
||||
DevToolsPanelLayoutCondition.FirstUseEver => ImGuiCond.FirstUseEver,
|
||||
DevToolsPanelLayoutCondition.Always => ImGuiCond.Always,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(condition)),
|
||||
};
|
||||
ImGuiNET.ImGui.SetWindowPos(title, position, imguiCondition);
|
||||
ImGuiNET.ImGui.SetWindowSize(title, size, imguiCondition);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_bootstrap.Dispose();
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Mutable late-composition seam for player-mode menu operations.</summary>
|
||||
internal sealed class DevToolsCameraMenuOperations : IDevToolsCameraMenuOperations
|
||||
{
|
||||
private readonly CameraController _camera;
|
||||
private readonly IDevToolsPlayerModeCommands _playerMode;
|
||||
|
||||
public DevToolsCameraMenuOperations(
|
||||
CameraController camera,
|
||||
IDevToolsPlayerModeCommands playerMode)
|
||||
{
|
||||
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
|
||||
_playerMode = playerMode ?? throw new ArgumentNullException(nameof(playerMode));
|
||||
}
|
||||
|
||||
public bool IsFlyMode => _camera.IsFlyMode;
|
||||
|
||||
public bool CollideCamera
|
||||
{
|
||||
get => AcDream.Core.Rendering.CameraDiagnostics.CollideCamera;
|
||||
set => AcDream.Core.Rendering.CameraDiagnostics.CollideCamera = value;
|
||||
}
|
||||
|
||||
public void ToggleFlyOrChase() => _playerMode.ToggleFlyOrChase();
|
||||
}
|
||||
|
||||
/// <summary>Resolves the reconnect-safe command bus at draw time.</summary>
|
||||
internal sealed class DevToolsCommandBusSource : IDevToolsCommandBusSource
|
||||
{
|
||||
private ILiveUiSessionTarget? _session;
|
||||
private bool _deactivated;
|
||||
|
||||
public ICommandBus Current =>
|
||||
!_deactivated && _session is { } session
|
||||
? session.Commands
|
||||
: NullCommandBus.Instance;
|
||||
|
||||
public void Bind(ILiveUiSessionTarget session)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
ObjectDisposedException.ThrowIf(_deactivated, this);
|
||||
if (_session is not null && !ReferenceEquals(_session, session))
|
||||
throw new InvalidOperationException(
|
||||
"Developer command-bus authority is already bound.");
|
||||
_session = session;
|
||||
}
|
||||
|
||||
public IDisposable BindOwned(ILiveUiSessionTarget session)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
ObjectDisposedException.ThrowIf(_deactivated, this);
|
||||
if (_session is not null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Developer command-bus authority is already bound.");
|
||||
}
|
||||
|
||||
_session = session;
|
||||
return new Binding(this, session);
|
||||
}
|
||||
|
||||
public void Unbind(ILiveUiSessionTarget session)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
if (ReferenceEquals(_session, session))
|
||||
_session = null;
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
_deactivated = true;
|
||||
_session = null;
|
||||
}
|
||||
|
||||
private sealed class Binding : IDisposable
|
||||
{
|
||||
private DevToolsCommandBusSource? _owner;
|
||||
private readonly ILiveUiSessionTarget _expected;
|
||||
|
||||
public Binding(
|
||||
DevToolsCommandBusSource owner,
|
||||
ILiveUiSessionTarget expected)
|
||||
{
|
||||
_owner = owner;
|
||||
_expected = expected;
|
||||
}
|
||||
|
||||
public void Dispose() =>
|
||||
Interlocked.Exchange(ref _owner, null)?.Unbind(_expected);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Typed panel operations used by menu and input presentation.</summary>
|
||||
internal sealed class DevToolsPanelSet : IDevToolsPanelSet
|
||||
{
|
||||
private readonly VitalsPanel _vitals;
|
||||
private readonly ChatPanel _chat;
|
||||
private readonly DebugPanel _debug;
|
||||
private readonly DebugVM _debugViewModel;
|
||||
private readonly SettingsPanel? _settings;
|
||||
|
||||
public DevToolsPanelSet(
|
||||
VitalsPanel vitals,
|
||||
ChatPanel chat,
|
||||
DebugPanel debug,
|
||||
DebugVM debugViewModel,
|
||||
SettingsPanel? settings)
|
||||
{
|
||||
_vitals = vitals ?? throw new ArgumentNullException(nameof(vitals));
|
||||
_chat = chat ?? throw new ArgumentNullException(nameof(chat));
|
||||
_debug = debug ?? throw new ArgumentNullException(nameof(debug));
|
||||
_debugViewModel = debugViewModel
|
||||
?? throw new ArgumentNullException(nameof(debugViewModel));
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public bool Contains(DevToolsPanelKind kind) =>
|
||||
kind != DevToolsPanelKind.Settings || _settings is not null;
|
||||
|
||||
public string? GetTitle(DevToolsPanelKind kind) => GetPanel(kind)?.Title;
|
||||
|
||||
public bool IsVisible(DevToolsPanelKind kind) => GetPanel(kind)?.IsVisible == true;
|
||||
|
||||
public void Toggle(DevToolsPanelKind kind)
|
||||
{
|
||||
if (GetPanel(kind) is { } panel)
|
||||
panel.IsVisible = !panel.IsVisible;
|
||||
}
|
||||
|
||||
public void FocusChatInput() => _chat.FocusInput();
|
||||
|
||||
public void AddDebugToast(string message) => _debugViewModel.AddToast(message);
|
||||
|
||||
private IPanel? GetPanel(DevToolsPanelKind kind) => kind switch
|
||||
{
|
||||
DevToolsPanelKind.Vitals => _vitals,
|
||||
DevToolsPanelKind.Chat => _chat,
|
||||
DevToolsPanelKind.Debug => _debug,
|
||||
DevToolsPanelKind.Settings => _settings,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(kind)),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Owns the optional ImGui developer frame, menu policy, panel actions, and
|
||||
/// reusable default layout. Retained gameplay UI remains a separate earlier
|
||||
/// presentation phase.
|
||||
/// </summary>
|
||||
internal sealed class DevToolsFramePresenter : IDevToolsFrameLifecycle
|
||||
{
|
||||
private readonly IDevToolsFrameBackend _backend;
|
||||
private readonly IDevToolsCameraMenuOperations _camera;
|
||||
private readonly IDevToolsCommandBusSource _commands;
|
||||
private readonly IDevToolsPanelSet _panels;
|
||||
private readonly AcDream.App.Diagnostics.FrameProfiler _profiler;
|
||||
private bool _frameOpen;
|
||||
|
||||
public DevToolsFramePresenter(
|
||||
IDevToolsFrameBackend backend,
|
||||
IDevToolsCameraMenuOperations camera,
|
||||
IDevToolsCommandBusSource commands,
|
||||
AcDream.App.Diagnostics.FrameProfiler profiler,
|
||||
IDevToolsPanelSet panels)
|
||||
{
|
||||
_backend = backend ?? throw new ArgumentNullException(nameof(backend));
|
||||
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
|
||||
_commands = commands ?? throw new ArgumentNullException(nameof(commands));
|
||||
_profiler = profiler ?? throw new ArgumentNullException(nameof(profiler));
|
||||
_panels = panels ?? throw new ArgumentNullException(nameof(panels));
|
||||
}
|
||||
|
||||
public void BeginFrame(float deltaSeconds)
|
||||
{
|
||||
if (_frameOpen)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"The previous developer-tools frame must render or abort before a new frame begins.");
|
||||
}
|
||||
|
||||
_frameOpen = true;
|
||||
_backend.BeginFrame(deltaSeconds);
|
||||
}
|
||||
|
||||
public void Render(double deltaSeconds, int viewportWidth, int viewportHeight)
|
||||
{
|
||||
if (!_frameOpen)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"BeginFrame must open the developer-tools frame before Render.");
|
||||
}
|
||||
|
||||
var context = new PanelContext((float)deltaSeconds, _commands.Current);
|
||||
DrawMenu(viewportWidth, viewportHeight);
|
||||
_backend.RenderPanels(context);
|
||||
using var stage = _profiler.BeginStage(AcDream.App.Diagnostics.FrameStage.ImGui);
|
||||
_backend.RenderDrawData();
|
||||
_frameOpen = false;
|
||||
}
|
||||
|
||||
public void AbortFrame()
|
||||
{
|
||||
if (!_frameOpen)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_backend.AbortFrame();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_frameOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleDebugPanel()
|
||||
{
|
||||
_panels.Toggle(DevToolsPanelKind.Debug);
|
||||
_panels.AddDebugToast(
|
||||
$"Debug panel {(_panels.IsVisible(DevToolsPanelKind.Debug) ? "ON" : "OFF")}");
|
||||
}
|
||||
|
||||
public void FocusChatInput() => _panels.FocusChatInput();
|
||||
|
||||
public void ToggleSettingsPanel()
|
||||
{
|
||||
_panels.Toggle(DevToolsPanelKind.Settings);
|
||||
}
|
||||
|
||||
public void ResetLayout(
|
||||
int viewportWidth,
|
||||
int viewportHeight,
|
||||
DevToolsPanelLayoutCondition condition)
|
||||
{
|
||||
float width = Math.Max(viewportWidth, 480);
|
||||
float height = Math.Max(viewportHeight, 320);
|
||||
|
||||
SetLayout(
|
||||
DevToolsPanelKind.Vitals,
|
||||
new Vector2(10f, 30f),
|
||||
new Vector2(220f, 110f),
|
||||
condition);
|
||||
SetLayout(
|
||||
DevToolsPanelKind.Chat,
|
||||
new Vector2(10f, height - 320f),
|
||||
new Vector2(450f, 300f),
|
||||
condition);
|
||||
SetLayout(
|
||||
DevToolsPanelKind.Debug,
|
||||
new Vector2(width - 380f, 30f),
|
||||
new Vector2(370f, 520f),
|
||||
condition);
|
||||
if (_panels.Contains(DevToolsPanelKind.Settings))
|
||||
{
|
||||
SetLayout(
|
||||
DevToolsPanelKind.Settings,
|
||||
new Vector2((width - 700f) * 0.5f, (height - 500f) * 0.5f),
|
||||
new Vector2(700f, 500f),
|
||||
condition);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMenu(int viewportWidth, int viewportHeight)
|
||||
{
|
||||
if (!_backend.BeginMainMenuBar())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_backend.BeginMenu("View"))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_panels.Contains(DevToolsPanelKind.Settings)
|
||||
&& _backend.MenuItem("Settings", "F11"))
|
||||
{
|
||||
_panels.Toggle(DevToolsPanelKind.Settings);
|
||||
}
|
||||
if (_backend.MenuItem("Vitals"))
|
||||
_panels.Toggle(DevToolsPanelKind.Vitals);
|
||||
if (_backend.MenuItem("Chat"))
|
||||
_panels.Toggle(DevToolsPanelKind.Chat);
|
||||
if (_backend.MenuItem("Debug", "Ctrl+F1"))
|
||||
_panels.Toggle(DevToolsPanelKind.Debug);
|
||||
_backend.Separator();
|
||||
if (_backend.MenuItem("Reset window layout"))
|
||||
ResetLayout(
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
DevToolsPanelLayoutCondition.Always);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_backend.EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
if (_backend.BeginMenu("Camera"))
|
||||
{
|
||||
try
|
||||
{
|
||||
string flyLabel = _camera.IsFlyMode
|
||||
? "Exit Free-Fly Mode"
|
||||
: "Enter Free-Fly Mode";
|
||||
if (_backend.MenuItem(flyLabel, "Ctrl+Shift+F"))
|
||||
_camera.ToggleFlyOrChase();
|
||||
|
||||
bool collide = _camera.CollideCamera;
|
||||
if (_backend.MenuItem(
|
||||
"Collide Camera (spring arm)",
|
||||
selected: collide))
|
||||
{
|
||||
_camera.CollideCamera = !collide;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_backend.EndMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_backend.EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetLayout(
|
||||
DevToolsPanelKind panel,
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
DevToolsPanelLayoutCondition condition)
|
||||
{
|
||||
string? title = _panels.GetTitle(panel);
|
||||
if (!string.IsNullOrEmpty(title))
|
||||
_backend.SetWindowLayout(title, position, size, condition);
|
||||
}
|
||||
}
|
||||
|
|
@ -37,19 +37,6 @@ internal interface IFramebufferDevToolsTarget
|
|||
void ResetLayout(int width, int height);
|
||||
}
|
||||
|
||||
internal sealed class DevToolsFramebufferTarget(DevToolsFramePresenter presenter)
|
||||
: IFramebufferDevToolsTarget
|
||||
{
|
||||
private readonly DevToolsFramePresenter _presenter = presenter
|
||||
?? throw new ArgumentNullException(nameof(presenter));
|
||||
|
||||
public void ResetLayout(int width, int height) =>
|
||||
_presenter.ResetLayout(
|
||||
width,
|
||||
height,
|
||||
DevToolsPanelLayoutCondition.Always);
|
||||
}
|
||||
|
||||
/// <summary>Expected-owner lease for the optional Phase-3 resize edge.</summary>
|
||||
internal sealed class FramebufferDevToolsBinding : IDisposable
|
||||
{
|
||||
|
|
@ -124,8 +111,9 @@ internal sealed class FramebufferResizeController
|
|||
return;
|
||||
|
||||
// Frozen order: GL viewport, shared aspect publication, camera, then
|
||||
// optional ImGui layout reset. Late binding never replays an earlier
|
||||
// resize transition.
|
||||
// the optional developer-tools layout reset (unbound since Campaign V
|
||||
// slice V11 removed the ImGui frontend). Late binding never replays an
|
||||
// earlier resize transition.
|
||||
_viewport?.ResizeViewport(width, height);
|
||||
_viewportAspect.Update(width, height);
|
||||
_camera?.SetAspect(width / (float)height);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ public sealed class GameWindow :
|
|||
IGameWindowPlatformPublication<GameWindowGraphics, IInputContext>,
|
||||
IGameWindowHostInputCameraPublication,
|
||||
IGameWindowContentEffectsAudioPublication,
|
||||
IGameWindowSettingsDevToolsPublication,
|
||||
IGameWindowWorldRenderPublication,
|
||||
IGameWindowInteractionRetainedUiPublication,
|
||||
IGameWindowLivePresentationPublication,
|
||||
|
|
@ -91,11 +90,11 @@ public sealed class GameWindow :
|
|||
private readonly AcDream.App.Rendering.WorldSceneDebugState
|
||||
_worldSceneDebugState = new();
|
||||
|
||||
// Phase I.2: the old StbTrueTypeSharp DebugOverlay was deleted in
|
||||
// favor of the ImGui-backed DebugPanel (see _debugVm below). The
|
||||
// TextRenderer + BitmapFont fields stay alive because they're shared
|
||||
// Phase I.2: the old StbTrueTypeSharp DebugOverlay was deleted in favor of
|
||||
// the ImGui-backed DebugPanel, which Campaign V slice V11 removed in turn.
|
||||
// The TextRenderer + BitmapFont fields stay alive because they're shared
|
||||
// with UiHost and reserved for the future world-space HUD (D.6 —
|
||||
// damage floaters, name plates) where ImGui can't reach into the 3D
|
||||
// damage floaters, name plates) where ImGui couldn't reach into the 3D
|
||||
// scene. They are no longer used for any debug overlay.
|
||||
private TextRenderer? _textRenderer;
|
||||
private BitmapFont? _debugFont;
|
||||
|
|
@ -379,12 +378,9 @@ public sealed class GameWindow :
|
|||
public AcDream.Core.Player.LocalPlayerState LocalPlayer =>
|
||||
_runtimeCharacter.LocalPlayer;
|
||||
|
||||
// Phase D.2a — ImGui devtools UI overlay. Null unless ACDREAM_DEVTOOLS=1.
|
||||
// See docs/plans/2026-04-24-ui-framework.md for the staged UI strategy.
|
||||
private AcDream.App.Rendering.DevToolsFramePresenter? _devToolsFramePresenter;
|
||||
private AcDream.App.Rendering.DevToolsCommandBusSource? _devToolsCommandBus;
|
||||
private DevToolsCompositionOwner? _devToolsComposition;
|
||||
private AcDream.UI.Abstractions.Panels.Vitals.VitalsVM? _vitalsVm;
|
||||
// Phase D.2a — ImGui devtools UI overlay. Removed at Campaign V slice V11;
|
||||
// see docs/plans/2026-04-24-ui-framework.md for the staged UI strategy and
|
||||
// docs/plans/2026-07-27-vulkan-campaign.md for the removal.
|
||||
private AcDream.UI.Abstractions.Panels.Chat.ChatVM? _retailChatVm;
|
||||
// Phase D.2b — retained host + composition runtime. Null unless ACDREAM_RETAIL_UI=1.
|
||||
private AcDream.App.UI.UiHost? _uiHost;
|
||||
|
|
@ -418,19 +414,13 @@ public sealed class GameWindow :
|
|||
_creatureAppraisalFramePresenter;
|
||||
// Phase D.2b Task 9 — plugin UI registrations buffered before OnLoad; drained in OnLoad.
|
||||
private readonly AcDream.App.Plugins.BufferedUiRegistry? _uiRegistry;
|
||||
// Phase I.2: ImGui debug panel ViewModel. The devtools presenter owns
|
||||
// its panel; the VM remains here because runtime feedback producers bind
|
||||
// directly to it during composition.
|
||||
private AcDream.UI.Abstractions.Panels.Debug.DebugVM? _debugVm;
|
||||
// DevToolsEnabled reads through typed RuntimeOptions.
|
||||
//
|
||||
// Campaign V slice V6h: the developer frontend is ImGui, which is not ported
|
||||
// to Vulkan and which slice V11 deletes outright, so a Vulkan host composes
|
||||
// none regardless of ACDREAM_DEVTOOLS. The flag still reaches
|
||||
// VulkanInstanceFactory, where it selects the optional debug-utils
|
||||
// instance extensions.
|
||||
private bool DevToolsEnabled =>
|
||||
_options.DevTools && _options.RenderBackend != RenderBackendKind.Vulkan;
|
||||
// Campaign V slice V11 deleted the ImGui developer-tools frontend along
|
||||
// with the OpenGL backend it required, so no host ever composes a
|
||||
// developer UI regardless of ACDREAM_DEVTOOLS. The flag still reaches
|
||||
// VulkanGraphicsContext, where it selects the optional debug-utils
|
||||
// instance/device extensions — see the ACDREAM_DEVTOOLS log line in
|
||||
// Run() below, which is the one remaining observable effect of the flag.
|
||||
private const bool DevToolsEnabled = false;
|
||||
|
||||
// Phase G.1-G.2 world lighting/time state. The environment owner keeps
|
||||
// the clock, selected day group, and weather transitions coherent.
|
||||
|
|
@ -922,26 +912,6 @@ public sealed class GameWindow :
|
|||
_audioSink = value.HookSink;
|
||||
}
|
||||
|
||||
void IGameWindowSettingsDevToolsPublication.PublishDevTools(
|
||||
DevToolsCompositionOwner value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
if (_devToolsComposition is not null
|
||||
|| _devToolsFramePresenter is not null
|
||||
|| _devToolsCommandBus is not null
|
||||
|| _debugVm is not null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"The GameWindow composition shell already owns developer tools.");
|
||||
}
|
||||
|
||||
_devToolsComposition = value;
|
||||
_devToolsFramePresenter = value.Presenter;
|
||||
_devToolsCommandBus = value.CommandBus;
|
||||
_vitalsVm = value.Vitals;
|
||||
_debugVm = value.Debug;
|
||||
}
|
||||
|
||||
void IGameWindowWorldRenderPublication.PublishBindlessSupport(
|
||||
BindlessSupport value) =>
|
||||
PublishCompositionOwner(
|
||||
|
|
@ -1048,7 +1018,6 @@ public sealed class GameWindow :
|
|||
{
|
||||
_uiHost = retained.Host;
|
||||
_retailUiRuntime = retained.Runtime;
|
||||
_vitalsVm ??= retained.Vitals;
|
||||
_retailChatVm = retained.Chat;
|
||||
_characterSheetProvider = retained.CharacterSheet;
|
||||
_frameScreenshots = retained.Screenshots;
|
||||
|
|
@ -1347,65 +1316,15 @@ public sealed class GameWindow :
|
|||
Console.Error.WriteLine),
|
||||
this).Compose(platformResult, hostInputCamera),
|
||||
(platformResult, hostInputCamera, contentEffectsAudio) =>
|
||||
{
|
||||
SettingsDevToolsOptionalDependencies? optionalDevTools = null;
|
||||
if (DevToolsEnabled)
|
||||
{
|
||||
var devToolsWorldEntities =
|
||||
new DeferredCanonicalWorldEntityCountSource();
|
||||
var devToolsFrameDiagnostics =
|
||||
new DeferredRenderFrameDiagnosticsSource();
|
||||
var devToolsPlayerModeCommands =
|
||||
new DeferredDevToolsPlayerModeCommands();
|
||||
var devToolsFacts = new DevToolsRuntimeFacts(
|
||||
_localPlayerMode,
|
||||
_playerControllerSlot,
|
||||
hostInputCamera.CameraController,
|
||||
devToolsWorldEntities,
|
||||
_animatedEntities,
|
||||
_debugVmRenderFacts,
|
||||
_physicsEngine,
|
||||
_worldSceneDebugState,
|
||||
_renderRange,
|
||||
hostInputCamera.CameraPointerInput,
|
||||
_worldEnvironment,
|
||||
Lighting,
|
||||
contentEffectsAudio.ParticleSystem,
|
||||
devToolsFrameDiagnostics);
|
||||
IRuntimeKeyBindingTarget? keyBindingTarget =
|
||||
hostInputCamera.InputDispatcher is { } settingsDispatcher
|
||||
? new RuntimeKeyBindingTarget(
|
||||
settingsDispatcher,
|
||||
_applicationPaths.KeyBindingsFile)
|
||||
: null;
|
||||
optionalDevTools = new SettingsDevToolsOptionalDependencies(
|
||||
devToolsFacts,
|
||||
keyBindingTarget,
|
||||
devToolsWorldEntities,
|
||||
devToolsFrameDiagnostics,
|
||||
devToolsPlayerModeCommands);
|
||||
}
|
||||
|
||||
return new SettingsDevToolsCompositionPhase(
|
||||
new SettingsDevToolsCompositionPhase(
|
||||
new SettingsDevToolsDependencies(
|
||||
_window!,
|
||||
_runtimeSettings,
|
||||
new RuntimeSettingsStartupTargets(
|
||||
new SilkRuntimeDisplayWindowTarget(_window!),
|
||||
_displayFramePacing,
|
||||
hostInputCamera.CameraController,
|
||||
contentEffectsAudio.Audio?.Engine),
|
||||
_hostQuiescence,
|
||||
_runtime,
|
||||
optionalDevTools,
|
||||
_runtimeDiagnosticCommands,
|
||||
_combatFeedback,
|
||||
_keyBindings,
|
||||
_frameProfiler,
|
||||
_framebufferResize,
|
||||
Console.WriteLine),
|
||||
this).Compose(platformResult, hostInputCamera, contentEffectsAudio);
|
||||
},
|
||||
contentEffectsAudio.Audio?.Engine)))
|
||||
.Compose(platformResult, hostInputCamera, contentEffectsAudio),
|
||||
(platformResult, contentEffectsAudio, settingsDevTools) =>
|
||||
{
|
||||
const uint initialCenterLandblockId = 0xA9B4FFFFu;
|
||||
|
|
@ -1433,9 +1352,10 @@ public sealed class GameWindow :
|
|||
},
|
||||
(platformResult, hostInputCamera, contentEffectsAudio, settingsDevTools, worldRender) =>
|
||||
{
|
||||
Action<string>? compositionToast = settingsDevTools.DevTools is { } devTools
|
||||
? text => devTools.Debug.AddToast(text)
|
||||
: null;
|
||||
// The ImGui developer-tools debug toast sink was removed at
|
||||
// Campaign V slice V11 along with the rest of the ImGui
|
||||
// frontend; there is no replacement toast surface yet.
|
||||
Action<string>? compositionToast = null;
|
||||
return new InteractionRetainedUiCompositionPhase(
|
||||
new InteractionRetainedUiDependencies(
|
||||
_options,
|
||||
|
|
@ -1469,7 +1389,7 @@ public sealed class GameWindow :
|
|||
_window!,
|
||||
viewPlane),
|
||||
_uiFrameDiagnostics,
|
||||
settingsDevTools.DevTools?.Vitals,
|
||||
ExistingVitals: null,
|
||||
compositionToast,
|
||||
ClientTimerNow,
|
||||
Console.WriteLine,
|
||||
|
|
@ -1490,9 +1410,10 @@ public sealed class GameWindow :
|
|||
worldRender,
|
||||
interactionUi) =>
|
||||
{
|
||||
Action<string>? compositionToast = settingsDevTools.DevTools is { } devTools
|
||||
? text => devTools.Debug.AddToast(text)
|
||||
: null;
|
||||
// The ImGui developer-tools debug toast sink was removed at
|
||||
// Campaign V slice V11 along with the rest of the ImGui
|
||||
// frontend; there is no replacement toast surface yet.
|
||||
Action<string>? compositionToast = null;
|
||||
return new LivePresentationCompositionPhase(
|
||||
new LivePresentationDependencies(
|
||||
_options,
|
||||
|
|
@ -1527,8 +1448,8 @@ public sealed class GameWindow :
|
|||
_hookRouter,
|
||||
_renderDiagnosticLog,
|
||||
WorldTime,
|
||||
settingsDevTools.DevTools?.LateBindings.WorldEntities,
|
||||
settingsDevTools.DevTools?.LateBindings.FrameDiagnostics,
|
||||
DevWorldEntities: null,
|
||||
DevFrameDiagnostics: null,
|
||||
_uiFrameDiagnostics,
|
||||
Console.WriteLine,
|
||||
compositionToast),
|
||||
|
|
@ -1761,7 +1682,6 @@ public sealed class GameWindow :
|
|||
_kbSource,
|
||||
_retailUiLease,
|
||||
_uiHost,
|
||||
_devToolsComposition,
|
||||
_runtime,
|
||||
_runtimeSettings,
|
||||
_movementInput,
|
||||
|
|
@ -1797,7 +1717,6 @@ public sealed class GameWindow :
|
|||
new RenderShutdownRoots(
|
||||
_gpuFrameFlights,
|
||||
_gpuDevice,
|
||||
_devToolsComposition,
|
||||
_localPlayerTeleport,
|
||||
_portalTunnelFallback,
|
||||
_paperdollViewportRenderer,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ internal sealed record IngressShutdownRoots(
|
|||
RetailUiRuntimeLease RetailUi,
|
||||
// Keeps failed physical UI bindings alive through native-window release.
|
||||
UiHost? RetainedUiHost,
|
||||
DevToolsCompositionOwner? DevTools,
|
||||
GameRuntime Runtime,
|
||||
RuntimeSettingsController Settings,
|
||||
DispatcherMovementInputSource MovementInput,
|
||||
|
|
@ -102,7 +101,6 @@ internal sealed record LiveShutdownRoots(
|
|||
internal sealed record RenderShutdownRoots(
|
||||
GpuFrameFlightController? FrameFlights,
|
||||
IGpuDevice? GpuDevice,
|
||||
DevToolsCompositionOwner? DevTools,
|
||||
LocalPlayerTeleportController? LocalTeleport,
|
||||
TransferableResourceSlot<PortalTunnelPresentation> PortalTunnelFallback,
|
||||
PaperdollViewportRenderer? Paperdoll,
|
||||
|
|
@ -350,7 +348,6 @@ internal static class GameWindowShutdownManifest
|
|||
Hard("mouse source", () => ingress.MouseSource?.Deactivate()),
|
||||
Hard("keyboard source", () => ingress.KeyboardSource?.Deactivate()),
|
||||
Hard("retained UI input", ingress.RetailUi.QuiesceInput),
|
||||
Hard("developer tools input", () => ingress.DevTools?.DeactivateInput()),
|
||||
Hard("game runtime session", ingress.Runtime.StopSession),
|
||||
]),
|
||||
new ResourceShutdownStage("physical ingress cleanup",
|
||||
|
|
@ -359,7 +356,6 @@ internal static class GameWindowShutdownManifest
|
|||
Soft("retained gameplay", () => DisposeRetainedGameplay(ingress.RetainedGameplay)),
|
||||
Soft("gameplay actions", () => DisposeGameplayActions(ingress.GameplayActions)),
|
||||
Soft("retained UI input", ingress.RetailUi.DeactivateInput),
|
||||
Soft("developer tools input", () => ingress.DevTools?.DetachInput()),
|
||||
Soft("camera pointer", () => DisposeCameraPointer(ingress.CameraPointer)),
|
||||
Soft("dispatcher", () => DisposeDispatcher(ingress)),
|
||||
Soft("mouse source", () => DisposeMouseSource(ingress.MouseSource)),
|
||||
|
|
@ -420,7 +416,6 @@ internal static class GameWindowShutdownManifest
|
|||
]),
|
||||
new ResourceShutdownStage("render frontends",
|
||||
[
|
||||
Hard("developer tools", () => DisposeDevToolsFrontend(render.DevTools)),
|
||||
Hard("portal tunnel", () =>
|
||||
{
|
||||
render.LocalTeleport?.Dispose();
|
||||
|
|
@ -600,12 +595,4 @@ internal static class GameWindowShutdownManifest
|
|||
throw new InvalidOperationException("OpenAL native-resource cleanup remains pending.");
|
||||
}
|
||||
|
||||
private static void DisposeDevToolsFrontend(DevToolsCompositionOwner? owner)
|
||||
{
|
||||
if (owner is null)
|
||||
return;
|
||||
owner.DisposeFrontend();
|
||||
if (!owner.IsFrontendDisposalComplete)
|
||||
throw new InvalidOperationException("Developer-tools frontend cleanup remains incomplete.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,20 @@ internal interface IRenderWeatherFramePhase
|
|||
void Tick(double deltaSeconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional per-frame developer-presentation hook. Its one production
|
||||
/// implementation (the ImGui developer-tools frontend) was removed at
|
||||
/// Campaign V slice V11; the interface survives as the seam a follow-up
|
||||
/// re-homing Settings/Debug onto the retained UI will implement, and every
|
||||
/// current caller already treats it as optional (<c>null</c>-conditional).
|
||||
/// </summary>
|
||||
internal interface IDevToolsFrameLifecycle : IRenderFrameFailureRecovery
|
||||
{
|
||||
void BeginFrame(float deltaSeconds);
|
||||
|
||||
void Render(double deltaSeconds, int viewportWidth, int viewportHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preserves the accepted pre-world order after the GPU/resource transaction:
|
||||
/// begin optional developer UI, advance render-time weather, then hand the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue