Remove the tool block from the main menu

Authoring tools open from the in-game toolbar only. Menu and test drivers quit
through ApplicationExit.
This commit is contained in:
cthangover committed 2026-10-29 13:21:43 +01:00
1 parent 364a0af3d1
commit 57450def43
9 files changed
+23 -53

No files matched your search

-8
View File
@@ -52,14 +52,6 @@ layout_mode = 2
layout_mode = 2
theme_override_constants/separation = 12
[node name="space2" type="Control" parent="MenuContainer" unique_id=1261364549]
custom_minimum_size = Vector2(0, 20)
layout_mode = 2
[node name="ToolMenuButtons" type="VBoxContainer" parent="MenuContainer" unique_id=43694906]
layout_mode = 2
theme_override_constants/separation = 12
[node name="CenterContainer" type="AspectRatioContainer" parent="." unique_id=1751426695]
layout_mode = 1
anchors_preset = -1
+2 -2
View File
@@ -140,10 +140,10 @@ namespace Cthangover.BaseMenu
host.GetNodeOrNull<SettingsMenu>("SettingsPanel")?.Open();
}
/// <summary>Quits the application immediately via <c>SceneTree.Quit</c>.</summary>
/// <summary>Quits the application after engine mods finish their registered cleanup.</summary>
public static void Exit(Control host)
{
host.GetTree().Quit();
Cthangover.Core.Bootstrap.ApplicationExit.Quit(host.GetTree());
}
}
}
+6 -32
View File
@@ -5,7 +5,6 @@ using Cthangover.Core.Settings;
using Cthangover.Core.UI;
using Cthangover.Core.UI.Menu;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.UI.Tool;
using Cthangover.Core.Utils;
using Godot;
@@ -14,11 +13,10 @@ namespace Cthangover.BaseMenu
{
/// <summary>
/// Title screen main menu, fully driven by <see cref="MenuRegistry"/>. The scene
/// only defines named section containers (game, mods, exit, tools); every button —
/// only defines named section containers (game, mods, exit); every button —
/// built-in or mod-provided — is created from registry entries, so mods can add,
/// replace or re-order entries without touching this scene. Below the sections,
/// every registered tool appends its own launcher button via
/// <see cref="IToolProvider.AddMenuButton"/>, so no tool list is hardcoded here.
/// replace or re-order entries without touching this scene. Authoring tools
/// are launched from the in-game toolbar.
/// If GameLogger reports mod compilation errors, a popup lists them. The
/// SettingsMenu and SaveLoadMenu panels are instantiated at ready time but stay
/// hidden; they are registered in <see cref="MenuRegistry"/> as panels "settings"
@@ -50,7 +48,7 @@ namespace Cthangover.BaseMenu
/// <summary>
/// Assembles the runtime UI: theme, hidden settings and save/load panels,
/// telegram link wiring, scene manager initialization and registry/tool
/// telegram link wiring, scene manager initialization and registry
/// driven buttons.
/// </summary>
private void BuildUi()
@@ -87,7 +85,6 @@ namespace Cthangover.BaseMenu
sceneManager.Initialize();
BuildRegistryButtons();
BuildToolButtons();
CheckModCompilationErrors();
RefreshButtons();
@@ -118,8 +115,8 @@ namespace Cthangover.BaseMenu
/// <summary>
/// Creates one button per <see cref="MenuRegistry"/> entry, routed to the
/// section container matching its <c>Section</c> ("game", "mods", "exit",
/// "tools"). Runs after <see cref="SceneManager.Initialize"/> because the
/// section container matching its <c>Section</c> ("game", "mods", "exit").
/// Runs after <see cref="SceneManager.Initialize"/> because the
/// registry is built during boot and filled by mod initializers; the
/// defensive Initialize call keeps direct scene launches working. Each
/// button's translation key is registered so <see cref="RefreshButtons"/>
@@ -132,7 +129,6 @@ namespace Cthangover.BaseMenu
{ "game", GetNode<Container>("MenuContainer/GameButtons") },
{ MenuButtonEntry.SectionMods, GetNode<Container>("MenuContainer/ModMenuButtons") },
{ "exit", GetNode<Container>("MenuContainer/ExitButtons") },
{ "tools", GetNode<Container>("MenuContainer/ToolMenuButtons") },
};
MenuBuilder.Build(this, sections);
@@ -140,28 +136,6 @@ namespace Cthangover.BaseMenu
MenuBuilder.CollectLocaleKeys(container, _btnKeys);
}
/// <summary>
/// Lets every registered tool append its launcher button to the tool block
/// below Exit (<c>MenuContainer/ToolMenuButtons</c>). Tools register
/// themselves in <see cref="ToolFactory"/>, so the block stays empty when no
/// tools are installed and needs no changes when a mod introduces a new tool.
/// Each button carries its translation key in metadata, keeping
/// <see cref="RefreshButtons"/> aware of it.
/// </summary>
private void BuildToolButtons()
{
var container = GetNodeOrNull<VBoxContainer>("MenuContainer/ToolMenuButtons");
if (container == null)
return;
foreach (var tool in ToolFactory.Instance.GetAll())
tool.AddMenuButton(container);
MenuBuilder.CollectLocaleKeys(container, _btnKeys);
GameLogger.Log("MAIN_MENU", $"Built {container.GetChildCount()} tool button(s)");
}
private void CheckModCompilationErrors()
{
if (GameLogger.CompilationErrors.Count == 0)
@@ -38,7 +38,11 @@ namespace Mods.CollectionEditTest
private const string GameId = "novel_template";
private const string AddedToolset = "dev_tools";
private const string AddedMod = "editor_tools";
private static readonly string[] AddedMods =
{
"scenario_editor", "scene_editor", "scene_builder", "map_editor",
"interactive_editor", "light_editor", "catalog_export"
};
private const string StudioMod = "scenario_studio";
private const string GameMenuId = "game_menu";
private const float TimeoutSeconds = 240f;
@@ -97,7 +101,7 @@ namespace Mods.CollectionEditTest
private static bool Busy => GameSession.IsSwitching || ModManager.Instance.IsReloading || ModHotReloadService.IsReloadRunning;
private static bool EditorsLoaded => ModRegistry.Instance.Mods.ContainsKey(AddedMod);
private static bool EditorsLoaded => AddedMods.All(ModRegistry.Instance.Mods.ContainsKey);
/// <summary>Scenes of the game entered since the last clear; the main menu does not count.</summary>
private void OnSceneEntered(SceneEnteredEvent e)
@@ -123,7 +127,7 @@ namespace Mods.CollectionEditTest
if (startedOnPlayerPackage)
GameLogger.Log("TEST", "CollectionEditTest: the game started on the player's own package; the before/switch checks are skipped");
else
Check($"'{AddedMod}' is not loaded before the edit", !EditorsLoaded);
Check("individual editors are not loaded before the edit", !AddedMods.Any(ModRegistry.Instance.Mods.ContainsKey));
AddEditorsToCollection();
Check("the edited collection makes the running game outdated", GameCatalog.IsActiveOutdated());
@@ -168,8 +172,8 @@ namespace Mods.CollectionEditTest
return;
var reload = ModManager.Instance.LastReload;
if (!startedOnPlayerPackage)
Check("New game after the edit switched the mod set", reload?.Applied == true && reload.Plan?.Load.Contains(AddedMod) == true);
Check($"'{AddedMod}' is loaded after the edit", EditorsLoaded);
Check("New game after the edit switched the mod set", reload?.Applied == true && AddedMods.All(id => reload.Plan?.Load.Contains(id) == true));
Check("all seven individual editors are loaded after the edit", EditorsLoaded);
Check($"'{StudioMod}' is loaded after the edit", ModRegistry.Instance.Mods.ContainsKey(StudioMod));
Check("the studio's button is on the game's toolbar", HasToolbarButton(StudioButtonTooltip()));
Check("the game matches its edited collection", !GameCatalog.IsActiveOutdated());
@@ -309,7 +313,7 @@ namespace Mods.CollectionEditTest
foreach (var failure in failures)
GameLogger.Log("TEST", $"CollectionEditTest: failed: {failure}");
GameLogger.Log("TEST", $"[TEST_RESULT] name=collection_edit passed={passed} failed={failures.Count}");
GetTree().Quit(failures.Count == 0 ? 0 : 1);
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
}
}
}
@@ -262,7 +262,7 @@ namespace Mods.DisplaySettingsTest
foreach (var failure in failures)
GameLogger.Log("TEST", $"DisplaySettingsTest: failed: {failure}");
GameLogger.Log("TEST", $"[TEST_RESULT] name=display_settings passed={passed} failed={failures.Count}");
GetTree().Quit(failures.Count == 0 ? 0 : 1);
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
}
}
}
@@ -313,7 +313,7 @@ namespace HotReloadProbeApp
foreach (var failure in failures)
GameLogger.Log("TEST", $"HotReloadTest: failed: {failure}");
GameLogger.Log("TEST", $"[TEST_RESULT] name=hot_reload passed={passed} failed={failures.Count}");
GetTree().Quit(failures.Count == 0 ? 0 : 1);
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
}
}
}
@@ -274,7 +274,7 @@ namespace Mods.MenuFlowTest
foreach (var failure in failures)
GameLogger.Log("TEST", $"MenuFlowTest: failed: {failure}");
GameLogger.Log("TEST", $"[TEST_RESULT] name=menu_flow passed={passed} failed={failures.Count}");
GetTree().Quit(failures.Count == 0 ? 0 : 1);
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
}
}
}
@@ -356,7 +356,7 @@ namespace Mods.NewGameTest
foreach (var failure in failures)
GameLogger.Log("TEST", $"NewGameTest: failed: {failure}");
GameLogger.Log("TEST", $"[TEST_RESULT] name=new_game passed={passed} failed={failures.Count}");
GetTree().Quit(failures.Count == 0 ? 0 : 1);
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
}
}
}
@@ -129,7 +129,7 @@ namespace Mods.SaveDormancyTest
foreach (var failure in failures)
GameLogger.Log("TEST", $"SaveDormancyTest: failed: {failure}");
GameLogger.Log("TEST", $"[TEST_RESULT] name=save_dormancy passed={passed} failed={failures.Count}");
GetTree().Quit(failures.Count == 0 ? 0 : 1);
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
}
}
}