fix(ui): commit FramebufferResize + ResetPanelLayout — orphaned during earlier cwd/sed shenanigans
These changes were referenced by commitsfc1e193/6273255/2818fcc/df9f2fdin their messages but the actual edits sat uncommitted in the working tree — caught by the pre-merge code review pass. Without this commit the merge to main would lose all the panel-layout fixes the user already live-verified. What was orphaned: · _window.FramebufferResize += OnFramebufferResize (Run() wiring) · OnFramebufferResize handler — updates GL viewport + camera aspect on window resize; force-resets panel layout via ResetPanelLayout. · ResetPanelLayout(ImGuiCond) — positions Vitals / Chat / Debug / Settings panels at sensible defaults relative to current window size. Called at startup with FirstUseEver (imgui.ini wins on later launches) and on FramebufferResize / View menu item with Always (force reset). · View → "Reset window layout" menu item. · OnLoad seeding ResetPanelLayout(FirstUseEver) after panel registration so first-launch users don't see all panels stacked at (0,0). · DisplaySettings.Default.Resolution: "1920x1080" → "1280x720" so the default matches the WindowOptions startup size — opening Display + Save without edits is a complete visual no-op (the alternative would have triggered an immediate resize on every first-time Save). dotnet build green; tests unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
df9f2fd3da
commit
944a0364c5
2 changed files with 102 additions and 4 deletions
|
|
@ -572,6 +572,12 @@ public sealed class GameWindow : IDisposable
|
||||||
_window.Update += OnUpdate;
|
_window.Update += OnUpdate;
|
||||||
_window.Render += OnRender;
|
_window.Render += OnRender;
|
||||||
_window.Closing += OnClosing;
|
_window.Closing += OnClosing;
|
||||||
|
// L.0 Display tab: keep the GL viewport + camera aspect in sync
|
||||||
|
// with the window framebuffer. Without this handler, resizing
|
||||||
|
// the window (or applying a Display-tab Resolution change at
|
||||||
|
// startup) leaves the viewport pinned to the original size —
|
||||||
|
// user sees a small render in the corner of a big window.
|
||||||
|
_window.FramebufferResize += OnFramebufferResize;
|
||||||
|
|
||||||
_window.Run();
|
_window.Run();
|
||||||
}
|
}
|
||||||
|
|
@ -1058,6 +1064,14 @@ public sealed class GameWindow : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("devtools: ImGui panel host ready (VitalsPanel + ChatPanel + DebugPanel + SettingsPanel registered)");
|
Console.WriteLine("devtools: ImGui panel host ready (VitalsPanel + ChatPanel + DebugPanel + SettingsPanel registered)");
|
||||||
|
|
||||||
|
// L.0 Display tab: seed sensible default positions for
|
||||||
|
// every registered panel. cond=FirstUseEver means imgui.ini
|
||||||
|
// takes precedence on subsequent launches — the user's
|
||||||
|
// dragged positions persist. Without this, the first-run
|
||||||
|
// experience stacks every panel at (0,0) which looks
|
||||||
|
// broken.
|
||||||
|
ResetPanelLayout(ImGuiNET.ImGuiCond.FirstUseEver);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -4515,6 +4529,15 @@ public sealed class GameWindow : IDisposable
|
||||||
if (_debugPanel is not null
|
if (_debugPanel is not null
|
||||||
&& ImGuiNET.ImGui.MenuItem("Debug", "Ctrl+F1"))
|
&& ImGuiNET.ImGui.MenuItem("Debug", "Ctrl+F1"))
|
||||||
_debugPanel.IsVisible = !_debugPanel.IsVisible;
|
_debugPanel.IsVisible = !_debugPanel.IsVisible;
|
||||||
|
ImGuiNET.ImGui.Separator();
|
||||||
|
// L.0 Display tab: a manual reset for users whose
|
||||||
|
// imgui.ini has saved a panel position that's now
|
||||||
|
// off-screen (after a window shrink, monitor swap,
|
||||||
|
// or a malformed save). Force-resets every panel
|
||||||
|
// to its default landing position. The same code
|
||||||
|
// path runs automatically on FramebufferResize.
|
||||||
|
if (ImGuiNET.ImGui.MenuItem("Reset window layout"))
|
||||||
|
ResetPanelLayout(ImGuiNET.ImGuiCond.Always);
|
||||||
ImGuiNET.ImGui.EndMenu();
|
ImGuiNET.ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
// K-fix2 (2026-04-26): Camera submenu — discoverable
|
// K-fix2 (2026-04-26): Camera submenu — discoverable
|
||||||
|
|
@ -5408,6 +5431,78 @@ public sealed class GameWindow : IDisposable
|
||||||
private AcDream.UI.Abstractions.Panels.Settings.SettingsStore? _settingsStore;
|
private AcDream.UI.Abstractions.Panels.Settings.SettingsStore? _settingsStore;
|
||||||
private string _activeToonKey = "default";
|
private string _activeToonKey = "default";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// L.0 Display tab: framebuffer-resize handler — update GL viewport
|
||||||
|
/// + camera aspect when the window is resized (by the user dragging
|
||||||
|
/// the corner OR by ApplyDisplayWindowState applying a saved
|
||||||
|
/// Resolution). Without this, the viewport stays pinned at the
|
||||||
|
/// startup size, producing a small render inside a big window.
|
||||||
|
/// Also force-resets ImGui panel layout so panels that were
|
||||||
|
/// previously off the new viewport snap back to default positions.
|
||||||
|
/// </summary>
|
||||||
|
private void OnFramebufferResize(Silk.NET.Maths.Vector2D<int> newSize)
|
||||||
|
{
|
||||||
|
if (newSize.X <= 0 || newSize.Y <= 0) return;
|
||||||
|
_gl?.Viewport(0, 0, (uint)newSize.X, (uint)newSize.Y);
|
||||||
|
_cameraController?.SetAspect(newSize.X / (float)newSize.Y);
|
||||||
|
// Resize is always a force-reset — the alternative ("clamp
|
||||||
|
// existing positions") would require tracking each panel's
|
||||||
|
// current pos+size, which ImGuiNET doesn't expose by name.
|
||||||
|
// Force-reset is acceptable UX because resizing happens rarely
|
||||||
|
// and the user can always drag panels back where they want.
|
||||||
|
if (DevToolsEnabled && _imguiBootstrap is not null)
|
||||||
|
ResetPanelLayout(ImGuiNET.ImGuiCond.Always);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// L.0 Display tab: position every registered panel to its default
|
||||||
|
/// landing spot, computed relative to the current window size so
|
||||||
|
/// the layout adapts to any resolution. Called from:
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item>OnFramebufferResize (cond=Always — force-reset on resize).</item>
|
||||||
|
/// <item>The View → "Reset window layout" menu item (cond=Always).</item>
|
||||||
|
/// <item>OnLoad after panel registration (cond=FirstUseEver — only
|
||||||
|
/// applies when imgui.ini has no saved position for that
|
||||||
|
/// panel; on subsequent launches the saved positions win).</item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
private void ResetPanelLayout(ImGuiNET.ImGuiCond cond)
|
||||||
|
{
|
||||||
|
if (_window is null) return;
|
||||||
|
float w = _window.Size.X;
|
||||||
|
float h = _window.Size.Y;
|
||||||
|
// Sane minimums so the math doesn't blow up on a tiny window.
|
||||||
|
if (w < 480) w = 480;
|
||||||
|
if (h < 320) h = 320;
|
||||||
|
|
||||||
|
// Panel positions chosen to be classic-MMO discoverable on a
|
||||||
|
// 1280x720 window: vitals top-left under the menu bar, chat
|
||||||
|
// bottom-left, debug top-right, settings centered. All sizes
|
||||||
|
// are reasonable defaults the user can resize from.
|
||||||
|
SetPanelLayout(_vitalsPanel?.Title, new System.Numerics.Vector2(10f, 30f),
|
||||||
|
new System.Numerics.Vector2(220f, 110f), cond);
|
||||||
|
SetPanelLayout(_chatPanel?.Title, new System.Numerics.Vector2(10f, h - 320f),
|
||||||
|
new System.Numerics.Vector2(450f, 300f), cond);
|
||||||
|
SetPanelLayout(_debugPanel?.Title, new System.Numerics.Vector2(w - 380f, 30f),
|
||||||
|
new System.Numerics.Vector2(370f, 520f), cond);
|
||||||
|
SetPanelLayout(_settingsPanel?.Title, new System.Numerics.Vector2((w - 700f) * 0.5f, (h - 500f) * 0.5f),
|
||||||
|
new System.Numerics.Vector2(700f, 500f), cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetPanelLayout(
|
||||||
|
string? title,
|
||||||
|
System.Numerics.Vector2 pos,
|
||||||
|
System.Numerics.Vector2 size,
|
||||||
|
ImGuiNET.ImGuiCond cond)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(title)) return;
|
||||||
|
// SetWindowPos/SetWindowSize by name work even when the window
|
||||||
|
// has never been Begin'd — ImGui stores the value for next
|
||||||
|
// appearance.
|
||||||
|
ImGuiNET.ImGui.SetWindowPos(title, pos, cond);
|
||||||
|
ImGuiNET.ImGui.SetWindowSize(title, size, cond);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// L.0 Display tab: apply the window-state-dependent settings
|
/// L.0 Display tab: apply the window-state-dependent settings
|
||||||
/// (Resolution + Fullscreen) from a <see cref="AcDream.UI.Abstractions.Panels.Settings.DisplaySettings"/>
|
/// (Resolution + Fullscreen) from a <see cref="AcDream.UI.Abstractions.Panels.Settings.DisplaySettings"/>
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,14 @@ public sealed record DisplaySettings(
|
||||||
bool ShowFps)
|
bool ShowFps)
|
||||||
{
|
{
|
||||||
/// <summary>Values used on first launch / when settings.json is absent.
|
/// <summary>Values used on first launch / when settings.json is absent.
|
||||||
/// FieldOfView (60°) and VSync (false) match the camera + window
|
/// All defaults pinned to the pre-L.0 runtime state — Resolution
|
||||||
/// defaults that shipped before L.0, so opening Display + Save
|
/// matches the WindowOptions startup size (1280×720), FieldOfView
|
||||||
/// without touching anything is a visual no-op.</summary>
|
/// matches camera FovY (60°), VSync matches WindowOptions (false),
|
||||||
|
/// ShowFps preserves the perf string in the title bar. Net effect:
|
||||||
|
/// opening Display + Save without touching anything is a complete
|
||||||
|
/// visual no-op.</summary>
|
||||||
public static DisplaySettings Default { get; } = new(
|
public static DisplaySettings Default { get; } = new(
|
||||||
Resolution: "1920x1080",
|
Resolution: "1280x720",
|
||||||
Fullscreen: false,
|
Fullscreen: false,
|
||||||
VSync: false,
|
VSync: false,
|
||||||
FieldOfView: 60f,
|
FieldOfView: 60f,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue