From 09de7e5eb2bc6a0f82cde16fbc7b7bf33fac6a70 Mon Sep 17 00:00:00 2001 From: soul Date: Thu, 22 Oct 2026 20:53:30 +0200 Subject: [PATCH] ScenarioPicker: selected row in the menu accent, title is group over name, panes docked 128 apart; verify and capture run green in Unity; metas The prefab row tint is nearly invisible on the row's graphic, the long scenario name overflowed a 480-wide title, and the list scrolls to keep the selection in view. Co-Authored-By: Claude Sonnet 5.5 --- .../Scripts/Editor/ScenarioPickerCapture.cs | 11 ++++-- .../Editor/ScenarioPickerCapture.cs.meta | 2 ++ Assets/Scripts/Editor/ScenarioPickerVerify.cs | 25 +++++++------ .../Editor/ScenarioPickerVerify.cs.meta | 2 ++ Assets/Scripts/UI/ScenarioPicker.cs | 35 ++++++++++++++----- Assets/Scripts/UI/ScenarioPicker.cs.meta | 2 ++ 6 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 Assets/Scripts/Editor/ScenarioPickerCapture.cs.meta create mode 100644 Assets/Scripts/Editor/ScenarioPickerVerify.cs.meta create mode 100644 Assets/Scripts/UI/ScenarioPicker.cs.meta diff --git a/Assets/Scripts/Editor/ScenarioPickerCapture.cs b/Assets/Scripts/Editor/ScenarioPickerCapture.cs index a9b42a348..12ec94142 100644 --- a/Assets/Scripts/Editor/ScenarioPickerCapture.cs +++ b/Assets/Scripts/Editor/ScenarioPickerCapture.cs @@ -8,9 +8,9 @@ using UnityEngine.UI; // A render of the New Game screen as the game builds it: the real Main Menu scene's panel prototype, docked and filled // by ScenarioPicker.Dock and ScenarioPicker.Show with every scenario group, on a plain dark background (the cloud -// backdrop is a play-mode renderer). Writes /Temp/scenario-picker.png at 1920x1080. +// backdrop is a play-mode renderer). Writes /Temp/scenario-picker.png at 1920x1080, or the path after -pngOut (Unity empties Temp on exit). // -// Unity -batchmode -projectPath -executeMethod ScenarioPickerCapture.Run -logFile +// Unity -batchmode -projectPath -executeMethod ScenarioPickerCapture.Run [-pngOut ] -logFile // // Needs a GPU device; do not pass -nographics or -quit: Run exits the Editor itself, 0 on success and 1 on any failure. public static class ScenarioPickerCapture @@ -54,6 +54,8 @@ public static class ScenarioPickerCapture private static void Capture() { var (menu, list, detail) = Build(); + menu.Dialog.gameObject.SetActive(false); + list.Title.text = MainMenu.TitleSubtitle("new game", "scenarios"); ScenarioPicker.Show(list, detail, AllGroups(), _ => { }, () => { }); list.RefreshValues(); detail.RefreshValues(); @@ -75,6 +77,8 @@ public static class ScenarioPickerCapture Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform) list.transform); LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform) detail.transform); + foreach (var text in list.transform.GetComponentsInChildren()) + text.ForceMeshUpdate(); Canvas.ForceUpdateCanvases(); camera.Render(); @@ -93,6 +97,9 @@ public static class ScenarioPickerCapture throw new InvalidOperationException($"The capture is uniform: only {differing} pixels differ from the background."); var path = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "Temp", "scenario-picker.png")); + var args = Environment.GetCommandLineArgs(); + var outIndex = Array.IndexOf(args, "-pngOut"); + if (outIndex >= 0) path = Path.GetFullPath(args[outIndex + 1]); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllBytes(path, read.EncodeToPNG()); Debug.Log($"[ScenarioPickerCapture] {path} ({differing} of {Width * Height} pixels differ from the background)"); diff --git a/Assets/Scripts/Editor/ScenarioPickerCapture.cs.meta b/Assets/Scripts/Editor/ScenarioPickerCapture.cs.meta new file mode 100644 index 000000000..ebeb742e8 --- /dev/null +++ b/Assets/Scripts/Editor/ScenarioPickerCapture.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2e79f280179150e4080250c45e07cd69 \ No newline at end of file diff --git a/Assets/Scripts/Editor/ScenarioPickerVerify.cs b/Assets/Scripts/Editor/ScenarioPickerVerify.cs index 8190a3a3e..1a08b7aba 100644 --- a/Assets/Scripts/Editor/ScenarioPickerVerify.cs +++ b/Assets/Scripts/Editor/ScenarioPickerVerify.cs @@ -44,7 +44,6 @@ public static class ScenarioPickerVerify { try { - EventSystem.current = new GameObject("verify EventSystem").AddComponent(); SelectionFollowsClicksAndArrows(); ArrowsStopAtTheEnds(); LeftAndRightAreIgnored(); @@ -70,6 +69,10 @@ public static class ScenarioPickerVerify private static Screen Build(bool oneGroup = false) { var (_, list, detail) = ScenarioPickerCapture.Build(); + // Build opens the scene afresh, which destroys the previous EventSystem. + var events = new GameObject("verify EventSystem").AddComponent(); + // Edit mode never calls OnEnable, which is what registers an EventSystem as current. + typeof(EventSystem).GetMethod("OnEnable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(events, null); var screen = new Screen { List = list, Detail = detail, @@ -81,10 +84,10 @@ public static class ScenarioPickerVerify ? new List<(string label, Scenario[] scenarios)> { ("modes", screen.A) } : new List<(string label, Scenario[] scenarios)> { ("modes", screen.A), ("development", screen.B), ("test arenas", screen.C) }; screen.Picker = ScenarioPicker.Show(list, detail, groups, screen.Launched.Add, () => screen.Backs++); - var buttons = list.GetComponentsInChildren(true).Select(button => button.Button).ToArray(); + var buttons = list.GetComponentsInChildren(false).Where(button => !button.transform.IsChildOf(detail.transform)).Select(button => button.Button).ToArray(); screen.Rows = buttons.Take(buttons.Length - 1).ToArray(); screen.Back = buttons.Last(); - screen.Launch = detail.GetComponentsInChildren(true).Single().Button; + screen.Launch = detail.GetComponentsInChildren(false).Single().Button; return screen; } @@ -114,10 +117,10 @@ public static class ScenarioPickerVerify Require(EventSystem.current.currentSelectedGameObject == screen.Launch.gameObject, "A click on a name took focus off Launch."); Require(screen.Rows.All(row => row.navigation.mode == Navigation.Mode.None) && screen.Launch.navigation.mode == Navigation.Mode.None && screen.Back.navigation.mode == Navigation.Mode.None, "A picker button still takes Unity navigation."); - var selected = screen.Rows[3].colors; - var other = screen.Rows[0].colors; - Require(selected.normalColor == selected.highlightedColor && other.normalColor != other.highlightedColor, - "Only the selected row is drawn highlighted."); + var accent = screen.Rows[3].targetGraphic.color; + Require(screen.Rows.Where((row, i) => i != 3).All(row => row.targetGraphic.color != accent), "Only the selected row is drawn in the accent."); + Move(screen, MoveDirection.Up); + Require(screen.Rows[2].targetGraphic.color == accent && screen.Rows[3].targetGraphic.color != accent, "The accent did not follow the selection."); } private static void ArrowsStopAtTheEnds() @@ -163,7 +166,7 @@ public static class ScenarioPickerVerify private static string DetailText(Screen screen) { screen.Detail.RefreshValues(); - return string.Join("|", screen.Detail.GetComponentsInChildren(true).Select(text => text.text)); + return string.Join("|", screen.Detail.GetComponentsInChildren(false).Select(text => text.text)); } private static void DetailPaneFollowsSelection() @@ -171,13 +174,13 @@ public static class ScenarioPickerVerify var screen = Build(); var first = DetailText(screen); Require(first.Contains("brief of Alpha") && first.Contains("7") && first.Contains("on"), $"Detail does not describe Alpha: {first}"); - Require(screen.Detail.Title.text == MainMenu.TitleSubtitle("Alpha", "modes"), "Detail title is not the name and group."); + Require(screen.Detail.Title.text == MainMenu.TitleSubtitle("modes", "Alpha"), "Detail title is not the name and group."); Move(screen, MoveDirection.Down); Move(screen, MoveDirection.Down); var third = DetailText(screen); Require(third.Contains("brief of Gamma") && third.Contains("new each launch") && third.Contains("off"), $"Detail does not describe Gamma: {third}"); - Require(screen.Detail.Title.text == MainMenu.TitleSubtitle("Gamma", "development"), "Detail title did not follow the selection."); - Require(screen.Detail.GetComponentsInChildren(true).Single().Button == screen.Launch, "Selecting rebuilt the Launch button."); + Require(screen.Detail.Title.text == MainMenu.TitleSubtitle("development", "Gamma"), "Detail title did not follow the selection."); + Require(screen.Detail.GetComponentsInChildren(false).Single().Button == screen.Launch, "Selecting rebuilt the Launch button."); } private static void OneGroupHasNoSectionLabel() diff --git a/Assets/Scripts/Editor/ScenarioPickerVerify.cs.meta b/Assets/Scripts/Editor/ScenarioPickerVerify.cs.meta new file mode 100644 index 000000000..473330b96 --- /dev/null +++ b/Assets/Scripts/Editor/ScenarioPickerVerify.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7ca0b5db32f745a43a8fdc67dfac2996 \ No newline at end of file diff --git a/Assets/Scripts/UI/ScenarioPicker.cs b/Assets/Scripts/UI/ScenarioPicker.cs index 4d6ab393e..d5a71aa5a 100644 --- a/Assets/Scripts/UI/ScenarioPicker.cs +++ b/Assets/Scripts/UI/ScenarioPicker.cs @@ -16,14 +16,18 @@ public sealed class ScenarioPicker private readonly List _groupLabels = new List(); private readonly List