Menu: conditional buttons, OpenScene returns the opened node

- MenuBuilder skips a button whose MenuButtonEntry.Visible predicate is
  false (e.g. "Continue" only when a last session exists); a throwing
  predicate is logged and the button stays visible.
- MenuBuilder.OpenScene returns the overlay it opened (null when the
  scene failed to build), so callers can configure it.
- Text for mods left out of a game's mod set: mods/not_in_game_reason.
This commit is contained in:
cthangover committed 2026-10-17 14:27:29 +00:00
1 parent b2a0f1c10a
commit 563b42ea9f
3 files changed
+22 -2

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ mods/enabled = Enabled
mods/disabled = Disabled mods/disabled = Disabled
mods/disabled_reason = Disabled mods/disabled_reason = Disabled
mods/dep_disabled_reason = Dependency "{0}" is disabled mods/dep_disabled_reason = Dependency "{0}" is disabled
mods/not_in_game_reason = Not part of the game "{0}"
mods/dependency_disabled = Dependency disabled mods/dependency_disabled = Dependency disabled
mods/invalid_dep_format = Invalid dependency format: "{0}" mods/invalid_dep_format = Invalid dependency format: "{0}"
mods/required_mod_not_loaded = Required mod "{0}" is not loaded mods/required_mod_not_loaded = Required mod "{0}" is not loaded
+1
View File
@@ -24,6 +24,7 @@ mods/enabled = Включён
mods/disabled = Выключен mods/disabled = Выключен
mods/disabled_reason = Выключен mods/disabled_reason = Выключен
mods/dep_disabled_reason = Зависимость "{0}" выключена mods/dep_disabled_reason = Зависимость "{0}" выключена
mods/not_in_game_reason = Не входит в игру "{0}"
mods/dependency_disabled = Зависимость отключена mods/dependency_disabled = Зависимость отключена
mods/invalid_dep_format = Неверный формат зависимости: "{0}" mods/invalid_dep_format = Неверный формат зависимости: "{0}"
mods/required_mod_not_loaded = Требуемый мод "{0}" не загружен mods/required_mod_not_loaded = Требуемый мод "{0}" не загружен
+20 -2
View File
@@ -40,6 +40,9 @@ namespace Cthangover.Mods.Interface.Menu
foreach (var entry in AppServices.Current.Menus.Buttons) foreach (var entry in AppServices.Current.Menus.Buttons)
{ {
if (entry.Visible != null && !SafeVisible(entry))
continue;
if (!sections.TryGetValue(entry.Section ?? MenuButtonEntry.SectionMods, out var container) if (!sections.TryGetValue(entry.Section ?? MenuButtonEntry.SectionMods, out var container)
&& !sections.TryGetValue(MenuButtonEntry.SectionMods, out container)) && !sections.TryGetValue(MenuButtonEntry.SectionMods, out container))
{ {
@@ -62,6 +65,19 @@ namespace Cthangover.Mods.Interface.Menu
/// carry a locale meta key into the host's translation map, so the host /// carry a locale meta key into the host's translation map, so the host
/// keeps them localized across language switches. /// keeps them localized across language switches.
/// </summary> /// </summary>
private static bool SafeVisible(MenuButtonEntry entry)
{
try
{
return entry.Visible();
}
catch (System.Exception ex)
{
GameLogger.Log("MENU_BUILDER", $"Visibility check of button '{entry.Id}' failed: {ex.Message}", LogLevel.Warning);
return true;
}
}
public static void CollectLocaleKeys(Container container, Dictionary<Button, string> keys) public static void CollectLocaleKeys(Container container, Dictionary<Button, string> keys)
{ {
if (container == null || keys == null) if (container == null || keys == null)
@@ -116,13 +132,14 @@ namespace Cthangover.Mods.Interface.Menu
/// owns its lifetime and closes itself, or is replaced by another menu /// owns its lifetime and closes itself, or is replaced by another menu
/// scene opening over it. /// scene opening over it.
/// </summary> /// </summary>
public static void OpenScene(Control menuRoot, string scenePath, string label = null) /// <summary>Opens a mod scene as a full-rect overlay of the menu and returns it (null when it fails to build).</summary>
public static Node OpenScene(Control menuRoot, string scenePath, string label = null)
{ {
var node = new ModScenePrefab(scenePath).Instantiate(); var node = new ModScenePrefab(scenePath).Instantiate();
if (node == null) if (node == null)
{ {
GameLogger.Log("MENU_BUILDER", $"Open '{label ?? scenePath}': scene '{scenePath}' failed to build", LogLevel.Error); GameLogger.Log("MENU_BUILDER", $"Open '{label ?? scenePath}': scene '{scenePath}' failed to build", LogLevel.Error);
return; return null;
} }
menuRoot.AddChild(node); menuRoot.AddChild(node);
@@ -135,6 +152,7 @@ namespace Cthangover.Mods.Interface.Menu
modWidget.EnsureConstructed(); modWidget.EnsureConstructed();
GameLogger.Log("MENU_BUILDER", $"Opened '{label ?? scenePath}' → {scenePath}"); GameLogger.Log("MENU_BUILDER", $"Opened '{label ?? scenePath}' → {scenePath}");
return node;
} }
} }
} }