using System.Collections.Generic;
using Cthangover.Core.Bootstrap;
using Cthangover.Core.Factories.Impls;
using Cthangover.Core.Mods;
using Cthangover.Core.Scenes;
using Cthangover.Core.UI;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.Utils;
using Godot;
using Cthangover.Mods.Interface.Theming;
using Cthangover.Core.UI.Tool;
namespace Cthangover.Mods.Interface.Tool
{
///
/// Main toolbar/HUD container (the TopView shell node). It no longer
/// knows any concrete panel: buttons for mod-provided panels are handed to it
/// by from , and
/// pressing one calls . Tool buttons
/// (/) remain a separate,
/// self-registering mechanism and are added alongside the panel buttons.
///
public partial class ToolBox : Control, IToolbarHost, ISaveIconHost
{
/// Side of a toolbar button and its icon: the icons are 64 px pixel-art sprites (scaled x4), so a
/// 64 px slot shows every sprite pixel; at 60 px the nearest filter dropped rows of them.
private const int SlotSize = 64;
private HBoxContainer _buttons;
private TextureRect _saveIcon;
/// Wires the save icon visibility and appends the dev-tool buttons registered in .
public override void _Ready()
{
_buttons = GetNodeOrNull("Buttons");
_saveIcon = GetNodeOrNull("CenterTools/Save");
UpdateSaveIconVisibility();
AddToolButtons(_buttons);
}
///
/// Materializes a toolbar button for every entry. Called once per shell by
/// ; entries arrive pre-sorted by the registry
/// (button index, then mod load order, then id).
///
public void ApplyPanelButtons(IReadOnlyList entries)
{
if (_buttons == null || entries == null)
return;
foreach (var entry in entries)
_buttons.AddChild(CreatePanelButton(entry));
}
private static BaseButton CreatePanelButton(UiEntry entry)
{
var title = TranslationServer.Translate(entry.Button.Locale);
var icon = UIIconFactory.Instance.Get(entry.Button.Icon);
var button = CreateToolbarButton(title, icon);
var id = entry.Id;
button.Pressed += () => AppServices.Current.Ui.ToggleEntry(id);
return button;
}
private static BaseButton CreateToolbarButton(string title, Texture2D icon)
{
var button = new Button
{
CustomMinimumSize = new Vector2(SlotSize, SlotSize),
SizeFlagsVertical = SizeFlags.ShrinkCenter,
TooltipText = title,
};
if (icon != null)
{
var iconRect = UiKit.Icon(icon, SlotSize);
button.AddChild(iconRect);
iconRect.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect);
}
else
{
button.Text = title;
}
button.AddThemeStyleboxOverride("normal", UiKit.Frame(UiTokens.RadiusSm, UiTokens.Surface0, UiTokens.Line));
button.AddThemeStyleboxOverride("hover", UiKit.Frame(UiTokens.RadiusSm, UiTokens.Surface1, UiTokens.AccentLine));
button.AddThemeStyleboxOverride("pressed", UiKit.Frame(UiTokens.RadiusSm, UiTokens.Surface1, UiTokens.AccentLineStrong));
button.AddThemeStyleboxOverride("disabled", UiKit.Frame(UiTokens.RadiusSm, UiTokens.Surface0, UiTokens.LineDisabled));
button.AddThemeStyleboxOverride("focus", new StyleBoxEmpty());
return button;
}
///
/// Adds one "tools" toolbar button whose popup lists every visible
/// . Tools used to get a text button each,
/// which did not fit the square icon row and overlapped its icons; a
/// single icon keeps the HUD row uniform no matter how many tools are
/// installed. Nothing is added when no tool button is visible.
///
private void AddToolButtons(HBoxContainer container)
{
if (container == null)
return;
var visible = new List(ToolBoxButtonFactory.Instance.GetVisible());
if (visible.Count == 0)
return;
visible.Sort((a, b) => string.Compare(
TranslationServer.Translate(a.LocaleKey), TranslationServer.Translate(b.LocaleKey),
System.StringComparison.CurrentCulture));
var btn = CreateToolbarButton(TranslationServer.Translate("tools/menu_title"), UIIconFactory.Instance.Get("tools"));
var menu = new PopupMenu { Theme = ToolTheme.Get() };
foreach (var buttonDef in visible)
menu.AddItem(TranslationServer.Translate(buttonDef.LocaleKey));
menu.IndexPressed += index => OpenTool(visible[(int)index].ToolId);
btn.AddChild(menu);
btn.Pressed += () =>
{
var rect = btn.GetGlobalRect();
menu.Position = new Vector2I((int)rect.Position.X, (int)rect.End.Y + UiTokens.Space1);
menu.Popup();
};
container.AddChild(btn);
}
private static void OpenTool(string toolId)
{
var tool = ToolFactory.Instance.Get(toolId);
if (tool != null)
ToolWindow.ShowWindow(tool.CreateWindow());
}
///
/// Shows or hides the save icon based on .
/// Call after scene transitions to reflect the new scene's save policy.
///
public void UpdateSaveIconVisibility()
{
if (_saveIcon == null)
return;
_saveIcon.Visible = SceneManager.IsSaveAllowedForCurrentScene();
}
}
}