ui stule update

This commit is contained in:
cthangover committed 2026-09-26 08:05:13 +03:00
1 parent 6af7a03808
commit 7521959cc0
17 files changed
+588 -48

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
# Catalog export tool — extra keys
mods/catalog_select_mod = Select a mod:
+2
View File
@@ -0,0 +1,2 @@
# Catalog export tool — дополнительные ключи
mods/catalog_select_mod = Выберите мод:
+2
View File
@@ -86,6 +86,8 @@ tools/scenario_editor/unsaved_switch_text = You have unsaved changes. Switch fil
tools/unsaved_title = Unsaved changes tools/unsaved_title = Unsaved changes
tools/unsaved_text = You have unsaved changes. Close without saving? tools/unsaved_text = You have unsaved changes. Close without saving?
mods/catalog_select_mod = Select a mod:
tools/scenario_editor/play = ▶ Play tools/scenario_editor/play = ▶ Play
tools/scenario_editor/play_tooltip = Run scenario in test mode tools/scenario_editor/play_tooltip = Run scenario in test mode
tools/scenario_editor/stop = ⏹ Stop tools/scenario_editor/stop = ⏹ Stop
+2 -2
View File
@@ -4,9 +4,9 @@
"version": "1.0.0", "version": "1.0.0",
"author": "ct", "author": "ct",
"description": "Development tools", "description": "Development tools",
"category": "tools", "category": "tools, editor",
"sources": [ "sources": [
"src/**/*.cs" "src/**/*.cs"
], ],
"depends": ["core>=1"] "depends": ["visual_novel_core>=1"]
} }
@@ -0,0 +1,23 @@
using Cthangover.Core.UI.Tool;
using Godot;
namespace Cthangover.Core.UI.Tool.CatalogExport
{
/// <summary>
/// Registers the catalog export window as a developer tool. Moved here from
/// the old mods menu when mod management UI was delegated to the
/// <c>mod_manager</c> mod — exporting a catalog entry is an authoring task,
/// not part of day-to-day mod management.
/// </summary>
public class CatalogExportToolProvider : IToolProvider
{
/// <summary>Unique tool identifier.</summary>
public string Id => "catalog_export";
/// <summary>Translation key for the tool's display name.</summary>
public string LocaleKey => "mods/catalog_title";
/// <summary>Creates the export window instance.</summary>
public Window CreateWindow() => new CatalogExportWindow();
}
}
+499
View File
@@ -0,0 +1,499 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Cthangover.Core.Mods;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.UI.Tool;
using Cthangover.Core.Utils;
using Godot;
namespace Cthangover.Core.UI.Tool.CatalogExport
{
/// <summary>
/// Developer tool that builds a catalog entry (JSON for the online mod
/// catalog) from a locally installed mod's manifest. Ported out of the old
/// mods menu so that mod-management UI can live in the <c>mod_manager</c>
/// mod while this authoring utility stays a tool.
/// <para/>
/// The window lets the author pick any discovered mod, fill in the
/// catalog-only metadata (download URL, category, tags, changelog, status,
/// minimum game version, icon URL, localized names/descriptions), preview
/// the resulting JSON, copy it to the clipboard, or export it next to the
/// mod's zip via <see cref="ModCatalogExporter"/>.
/// </summary>
public partial class CatalogExportWindow : ToolWindow
{
private static readonly string[] Statuses = { "stable", "beta", "deprecated", "archived" };
private static readonly CategoryType[] Categories = Enum.GetValues<CategoryType>();
private OptionButton _modSelect;
private VBoxContainer _formHost;
private ModInfo _modInfo;
private ModManifest _manifest;
private LineEdit _urlEdit;
private ItemList _categoryList;
private LineEdit _tagsEdit;
private TextEdit _changelogEdit;
private OptionButton _statusOpt;
private LineEdit _minGameVerEdit;
private LineEdit _iconUrlEdit;
private VBoxContainer _localeContainer;
private TextEdit _previewEdit;
public CatalogExportWindow() : base("mods/catalog_title")
{
Size = new Vector2I(620, 720);
CthangoverTheme.Apply(this);
var vbox = CreateFillContainer();
vbox.AddThemeConstantOverride("separation", 8);
AddChild(vbox);
var selectRow = new HBoxContainer();
selectRow.AddThemeConstantOverride("separation", 8);
var selectLabel = new Label { Text = TranslationServer.Translate("mods/catalog_select_mod") };
selectLabel.AddThemeColorOverride("font_color", UiTokens.Muted);
selectRow.AddChild(selectLabel);
_modSelect = new OptionButton
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
_modSelect.ItemSelected += OnModSelected;
selectRow.AddChild(_modSelect);
vbox.AddChild(selectRow);
var scroll = new ScrollContainer
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
SizeFlagsVertical = Control.SizeFlags.ExpandFill,
HorizontalScrollMode = ScrollContainer.ScrollMode.Disabled,
};
vbox.AddChild(scroll);
_formHost = new VBoxContainer
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
_formHost.AddThemeConstantOverride("separation", 8);
scroll.AddChild(_formHost);
PopulateModList();
}
private void PopulateModList()
{
var ordered = ModRegistry.Instance.GetOrderedModIds(filterDisabled: false);
foreach (var id in ordered)
{
var info = ModRegistry.Instance.GetMod(id);
if (info == null)
continue;
_modSelect.AddItem(info.DisplayTitle);
_modSelect.SetItemMetadata(_modSelect.ItemCount - 1, id);
}
if (_modSelect.ItemCount > 0)
{
_modSelect.Selected = 0;
BuildForm(_modSelect.GetItemMetadata(0).AsString());
}
}
private void OnModSelected(long index)
{
BuildForm(_modSelect.GetItemMetadata((int)index).AsString());
}
private void BuildForm(string modId)
{
foreach (var child in _formHost.GetChildren())
child.QueueFree();
_modInfo = ModRegistry.Instance.GetMod(modId) as ModInfo;
_manifest = _modInfo?.Manifest;
if (_modInfo == null || _manifest == null)
return;
AddSectionLabel(_formHost, "Mod Info");
AddReadOnlyField(_formHost, "mods/id", _modInfo.Id);
AddReadOnlyField(_formHost, "mods/name", _modInfo.DisplayTitle);
AddReadOnlyField(_formHost, "mods/version", _modInfo.Version ?? "—");
AddReadOnlyField(_formHost, "mods/author", _modInfo.Author ?? "—");
AddSectionLabel(_formHost, "Catalog Metadata");
_urlEdit = AddLineEdit(_formHost, "mods/catalog_download_url");
_categoryList = new ItemList
{
CustomMinimumSize = new Vector2(0, 130),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
SelectMode = ItemList.SelectModeEnum.Toggle,
};
var preselected = _manifest.Category ?? CategoryType.Other;
for (var i = 0; i < Categories.Length; i++)
{
_categoryList.AddItem(GetCategoryDisplayName(Categories[i]));
if ((preselected & Categories[i]) != 0)
_categoryList.Select(i, false);
}
AddLabeledControl(_formHost, "mods/catalog_category", _categoryList);
_tagsEdit = AddLineEdit(_formHost, "mods/catalog_tags");
_changelogEdit = new TextEdit
{
CustomMinimumSize = new Vector2(0, 60),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
WrapMode = TextEdit.LineWrappingMode.Boundary,
};
AddLabeledControl(_formHost, "mods/catalog_changelog", _changelogEdit);
_statusOpt = AddOptionButton(_formHost, "mods/catalog_status", Statuses);
_minGameVerEdit = AddLineEdit(_formHost, "mods/catalog_min_game_version");
_iconUrlEdit = AddLineEdit(_formHost, "mods/catalog_icon_url");
AddSectionLabel(_formHost, "JSON Preview");
_previewEdit = new TextEdit
{
CustomMinimumSize = new Vector2(0, 160),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
Editable = false,
WrapMode = TextEdit.LineWrappingMode.None,
};
_previewEdit.AddThemeFontSizeOverride("font_size", UiTokens.FontSmall);
_formHost.AddChild(_previewEdit);
var btnRow = new HBoxContainer
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
btnRow.AddThemeConstantOverride("separation", 8);
var copyBtn = new Button
{
Text = TranslationServer.Translate("mods/catalog_copy"),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
copyBtn.Pressed += OnCopyPressed;
btnRow.AddChild(copyBtn);
var exportBtn = new Button
{
Text = TranslationServer.Translate("mods/catalog_export_file"),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
exportBtn.Pressed += OnExportPressed;
btnRow.AddChild(exportBtn);
var closeBtn = new Button
{
Text = TranslationServer.Translate("mods/catalog_close"),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
closeBtn.Pressed += () => QueueFree();
btnRow.AddChild(closeBtn);
_formHost.AddChild(btnRow);
AddSectionLabel(_formHost, "Locales");
_localeContainer = new VBoxContainer
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
_localeContainer.AddThemeConstantOverride("separation", 4);
_formHost.AddChild(_localeContainer);
var addLocaleBtn = new Button
{
Text = TranslationServer.Translate("mods/catalog_add_locale"),
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
addLocaleBtn.Pressed += () => AddLocaleRow(string.Empty, string.Empty, string.Empty);
_formHost.AddChild(addLocaleBtn);
_urlEdit.TextChanged += _ => UpdatePreview();
_categoryList.ItemSelected += _ => UpdatePreview();
_categoryList.MultiSelected += (_, _) => UpdatePreview();
_tagsEdit.TextChanged += _ => UpdatePreview();
_changelogEdit.TextChanged += UpdatePreview;
_statusOpt.ItemSelected += _ => UpdatePreview();
_minGameVerEdit.TextChanged += _ => UpdatePreview();
_iconUrlEdit.TextChanged += _ => UpdatePreview();
UpdatePreview();
}
private static string GetCategoryDisplayName(CategoryType cat) => cat switch
{
CategoryType.Story => TranslationServer.Translate("mods/category_story"),
CategoryType.Characters => TranslationServer.Translate("mods/category_characters"),
CategoryType.Gameplay => TranslationServer.Translate("mods/category_gameplay"),
CategoryType.Visual => TranslationServer.Translate("mods/category_visual"),
CategoryType.Audio => TranslationServer.Translate("mods/category_audio"),
CategoryType.UI => TranslationServer.Translate("mods/category_ui"),
CategoryType.Locale => TranslationServer.Translate("mods/category_locale"),
CategoryType.Library => TranslationServer.Translate("mods/category_library"),
CategoryType.Engine => TranslationServer.Translate("mods/category_engine"),
CategoryType.Overhaul => TranslationServer.Translate("mods/category_overhaul"),
CategoryType.Tools => TranslationServer.Translate("mods/category_tools"),
CategoryType.Editor => TranslationServer.Translate("mods/category_editor"),
CategoryType.Debug => TranslationServer.Translate("mods/category_debug"),
CategoryType.Other => TranslationServer.Translate("mods/category_other"),
_ => cat.ToString(),
};
private void AddLocaleRow(string lang, string name, string description)
{
var row = new HBoxContainer
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
};
row.AddThemeConstantOverride("separation", 4);
var langEdit = new LineEdit
{
CustomMinimumSize = new Vector2(44, 0),
PlaceholderText = "en",
MaxLength = 5,
Text = lang,
};
row.AddChild(langEdit);
var nameEdit = new LineEdit
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
PlaceholderText = TranslationServer.Translate("mods/catalog_locale_name"),
Text = name,
};
row.AddChild(nameEdit);
var descEdit = new LineEdit
{
SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
PlaceholderText = TranslationServer.Translate("mods/catalog_locale_desc"),
Text = description,
};
row.AddChild(descEdit);
var removeBtn = new Button { Text = "×", CustomMinimumSize = new Vector2(28, 0) };
removeBtn.Pressed += () => RemoveLocaleRow(row);
row.AddChild(removeBtn);
langEdit.TextChanged += _ => UpdatePreview();
nameEdit.TextChanged += _ => UpdatePreview();
descEdit.TextChanged += _ => UpdatePreview();
_localeContainer.AddChild(row);
}
private void RemoveLocaleRow(HBoxContainer row)
{
_localeContainer.RemoveChild(row);
row.QueueFree();
UpdatePreview();
}
private void UpdatePreview()
{
if (_previewEdit == null || _modInfo == null || _manifest == null)
return;
var entry = BuildEntryFromManifest(_manifest);
entry.Downloads = new List<CatalogEntryDownload>
{
new()
{
Version = entry.Version,
Urls = new List<string> { _urlEdit.Text.Trim() },
SizeBytes = 0,
ArchiveSha256 = "—",
InstallSha256 = "—",
},
};
entry.Category = CollectSelectedCategories(_categoryList, Categories);
entry.Tags = ParseTags(_tagsEdit.Text);
entry.Downloads[0].Changelog = NullIfEmpty(_changelogEdit.Text);
entry.Status = Statuses[_statusOpt.Selected];
entry.MinGameVersion = NullIfEmpty(_minGameVerEdit.Text);
entry.IconUrl = NullIfEmpty(_iconUrlEdit.Text);
entry.Locale = CollectLocales();
_previewEdit.Text = JsonSerializer.Serialize(entry, JsonOptionsProvider.WriteIndentedIgnoreNullOptions);
}
private List<CatalogLocaleEntry> CollectLocales()
{
var list = new List<CatalogLocaleEntry>();
foreach (var child in _localeContainer.GetChildren())
{
if (child is not HBoxContainer row || row.GetChildCount() < 3)
continue;
var lang = ((LineEdit)row.GetChild(0)).Text.Trim();
var name = ((LineEdit)row.GetChild(1)).Text.Trim();
var description = ((LineEdit)row.GetChild(2)).Text.Trim();
if (lang.Length == 0)
continue;
list.Add(new CatalogLocaleEntry
{
Lang = lang,
Name = NullIfEmpty(name),
Description = NullIfEmpty(description),
});
}
if (list.Count == 0 && _manifest != null)
{
list.Add(new CatalogLocaleEntry
{
Lang = "en",
Name = _manifest.Name,
Description = _manifest.Description,
});
}
return list;
}
private CatalogExportEntry BuildExportEntry()
{
var entry = BuildEntryFromManifest(_manifest);
entry.Downloads = new List<CatalogEntryDownload>
{
new()
{
Version = entry.Version,
Urls = new List<string> { _urlEdit.Text.Trim() },
SizeBytes = 0,
},
};
entry.Category = CollectSelectedCategories(_categoryList, Categories);
entry.Tags = ParseTags(_tagsEdit.Text);
entry.Downloads[0].Changelog = NullIfEmpty(_changelogEdit.Text);
entry.Status = Statuses[_statusOpt.Selected];
entry.MinGameVersion = NullIfEmpty(_minGameVerEdit.Text);
entry.IconUrl = NullIfEmpty(_iconUrlEdit.Text);
entry.Locale = CollectLocales();
return entry;
}
private void OnCopyPressed()
{
DisplayServer.ClipboardSet(_previewEdit.Text);
GameLogger.Log("CATALOG_EXPORT", $"Copied catalog JSON for '{_modInfo?.Id}' to clipboard");
}
private void OnExportPressed()
{
if (_modInfo == null)
return;
var entry = BuildExportEntry();
var modsRoot = ModRegistry.ModsPath;
var isZip = _modInfo.FileProvider.RootPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase);
if (isZip)
ModCatalogExporter.ExportFromZip(_modInfo, entry, modsRoot);
else
ModCatalogExporter.ExportFromFolder(_modInfo, entry, modsRoot);
QueueFree();
}
private static List<string> ParseTags(string text)
{
if (string.IsNullOrWhiteSpace(text))
return null;
return text.Split(',').Select(t => t.Trim()).Where(t => t.Length > 0).ToList();
}
private static string NullIfEmpty(string text)
{
var trimmed = text?.Trim();
return string.IsNullOrEmpty(trimmed) ? null : trimmed;
}
private static CatalogExportEntry BuildEntryFromManifest(ModManifest manifest)
{
var depends = manifest.Depends?.Select(d => d.ToString()).Where(s => s.Length > 0).ToList();
return new CatalogExportEntry
{
Id = manifest.Id,
Name = manifest.Name,
Author = manifest.Author,
Version = manifest.Version,
Description = manifest.Description,
Category = manifest.Category ?? CategoryType.Other,
Depends = depends,
ConflictsWith = manifest.ConflictsWith,
};
}
private static CategoryType CollectSelectedCategories(ItemList list, CategoryType[] categories)
{
var selected = (CategoryType)0;
for (var i = 0; i < categories.Length && i < list.ItemCount; i++)
{
if (list.IsSelected(i))
selected |= categories[i];
}
return selected != 0 ? selected : CategoryType.Other;
}
private static void AddLabeledControl(Container parent, string labelKey, Control control)
{
var box = new VBoxContainer { SizeFlagsHorizontal = Control.SizeFlags.ExpandFill };
var label = new Label
{
Text = TranslationServer.Translate(labelKey),
};
label.AddThemeFontSizeOverride("font_size", UiTokens.FontBodySmall);
label.AddThemeColorOverride("font_color", UiTokens.Muted);
box.AddChild(label);
box.AddChild(control);
parent.AddChild(box);
}
private static void AddReadOnlyField(Container parent, string labelKey, string value)
{
var label = new Label
{
Text = $"{TranslationServer.Translate(labelKey)}: {value}",
};
label.AddThemeFontSizeOverride("font_size", UiTokens.FontBody);
label.AddThemeColorOverride("font_color", UiTokens.Body);
parent.AddChild(label);
}
private static LineEdit AddLineEdit(Container parent, string labelKey)
{
var edit = new LineEdit { SizeFlagsHorizontal = Control.SizeFlags.ExpandFill };
AddLabeledControl(parent, labelKey, edit);
return edit;
}
private static OptionButton AddOptionButton(Container parent, string labelKey, string[] items)
{
var opt = new OptionButton { SizeFlagsHorizontal = Control.SizeFlags.ExpandFill };
foreach (var item in items)
opt.AddItem(item);
AddLabeledControl(parent, labelKey, opt);
return opt;
}
private static void AddSectionLabel(Container parent, string text)
{
var sep = new HSeparator();
parent.AddChild(sep);
var label = new Label { Text = text };
label.AddThemeFontSizeOverride("font_size", UiTokens.FontBodyLarge);
label.AddThemeColorOverride("font_color", UiTokens.Ink);
parent.AddChild(label);
}
}
}
@@ -1,9 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Cthangover.Core.Interactive; using Cthangover.Core.Interactive;
using Cthangover.Core.Mods; using Cthangover.Core.Mods;
using Cthangover.Core.Mods.Resolvers; using Cthangover.Core.Mods.Resolvers;
using Cthangover.Core.Factories.Impls; using Cthangover.Core.Factories.Impls;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.UI.Tool; using Cthangover.Core.UI.Tool;
using Cthangover.Core.Utils; using Cthangover.Core.Utils;
using Cthangover.Tools.Services; using Cthangover.Tools.Services;
@@ -13,13 +14,13 @@ namespace Cthangover.Tools.InteractiveEditor
{ {
public partial class InteractiveEditorWindow : ToolWindow public partial class InteractiveEditorWindow : ToolWindow
{ {
private static readonly Color _rectColor = new(0f, 1f, 0f, 0.6f); private static readonly Color _rectColor = UiTokens.Alpha(UiTokens.Success, 0.6f);
private static readonly Color _circleColor = new(0f, 0.5f, 1f, 0.6f); private static readonly Color _circleColor = UiTokens.Alpha(UiTokens.Info, 0.6f);
private static readonly Color _vertexColor = new(1f, 0.8f, 0f, 0.8f); private static readonly Color _vertexColor = UiTokens.Alpha(UiTokens.AccentBright, 0.8f);
private static readonly Color _colliderOverlayColor = new(0f, 1f, 0f, 0.15f); private static readonly Color _colliderOverlayColor = UiTokens.Alpha(UiTokens.Success, 0.15f);
private static readonly Color _colliderCircleOverlayColor = new(0f, 0.5f, 1f, 0.15f); private static readonly Color _colliderCircleOverlayColor = UiTokens.Alpha(UiTokens.Info, 0.15f);
private static readonly Color _colliderPolyOverlayColor = new(1f, 0.5f, 0f, 0.15f); private static readonly Color _colliderPolyOverlayColor = UiTokens.Alpha(UiTokens.Accent, 0.15f);
private static readonly Color _colliderPolyOutlineColor = new(1f, 0.5f, 0f, 0.6f); private static readonly Color _colliderPolyOutlineColor = UiTokens.Alpha(UiTokens.Accent, 0.6f);
private InteractiveEditorController _controller = new(); private InteractiveEditorController _controller = new();
@@ -56,6 +57,7 @@ namespace Cthangover.Tools.InteractiveEditor
public InteractiveEditorWindow() : base("tools/interactive_editor/title") public InteractiveEditorWindow() : base("tools/interactive_editor/title")
{ {
Size = new Vector2I(1280, 820); Size = new Vector2I(1280, 820);
CthangoverTheme.Apply(this);
var outer = CreateFillContainer(); var outer = CreateFillContainer();
AddChild(outer); AddChild(outer);
@@ -215,7 +217,7 @@ namespace Cthangover.Tools.InteractiveEditor
AddLabel(parent, "tools/interactive_editor/label_highlight_color"); AddLabel(parent, "tools/interactive_editor/label_highlight_color");
_highlightColorBtn = new ColorPickerButton _highlightColorBtn = new ColorPickerButton
{ {
Color = new Color(1f, 1f, 0f, 0.2f), Color = UiTokens.Alpha(UiTokens.Accent, 0.2f),
CustomMinimumSize = new Vector2(40, 30) CustomMinimumSize = new Vector2(40, 30)
}; };
_highlightColorBtn.ColorChanged += _ => OnParamChanged(); _highlightColorBtn.ColorChanged += _ => OnParamChanged();
@@ -262,7 +264,7 @@ namespace Cthangover.Tools.InteractiveEditor
private void AddLabel(Control parent, string locKey) private void AddLabel(Control parent, string locKey)
{ {
var label = new Label { Text = Tr(locKey) }; var label = new Label { Text = Tr(locKey) };
label.AddThemeColorOverride("font_color", new Color(0.7f, 0.7f, 0.7f)); label.AddThemeColorOverride("font_color", UiTokens.Muted);
parent.AddChild(label); parent.AddChild(label);
} }
@@ -850,3 +852,4 @@ namespace Cthangover.Tools.InteractiveEditor
} }
} }
} }
+3 -2
View File
@@ -3,6 +3,7 @@ using System.Text.Json;
using Cthangover.Core.Mods; using Cthangover.Core.Mods;
using Cthangover.Core.Mods.Resolvers; using Cthangover.Core.Mods.Resolvers;
using Cthangover.Core.UI.Lights; using Cthangover.Core.UI.Lights;
using Cthangover.Core.UI.Theming;
using Godot; using Godot;
namespace Cthangover.Core.UI.Tool.LightEditor namespace Cthangover.Core.UI.Tool.LightEditor
@@ -36,7 +37,7 @@ namespace Cthangover.Core.UI.Tool.LightEditor
previewPositions[i] = new Vector2(-1000f, -1000f); previewPositions[i] = new Vector2(-1000f, -1000f);
previewRadii[i] = 0f; previewRadii[i] = 0f;
previewInfluence[i] = 0f; previewInfluence[i] = 0f;
previewColors[i] = Colors.White; previewColors[i] = UiTokens.White;
} }
} }
@@ -122,7 +123,7 @@ namespace Cthangover.Core.UI.Tool.LightEditor
previewPositions[i] = new Vector2(-1000f, -1000f); previewPositions[i] = new Vector2(-1000f, -1000f);
previewRadii[i] = 0f; previewRadii[i] = 0f;
previewInfluence[i] = 0f; previewInfluence[i] = 0f;
previewColors[i] = Colors.White; previewColors[i] = UiTokens.White;
} }
int count = Mathf.Min(Lights.Count, 10); int count = Mathf.Min(Lights.Count, 10);
+2
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text.Json; using System.Text.Json;
using Cthangover.Core.Factories.Impls; using Cthangover.Core.Factories.Impls;
using Cthangover.Core.UI.Lights; using Cthangover.Core.UI.Lights;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.Utils; using Cthangover.Core.Utils;
using Cthangover.Tools.Services; using Cthangover.Tools.Services;
using Godot; using Godot;
@@ -40,6 +41,7 @@ namespace Cthangover.Core.UI.Tool.LightEditor
public LightEditorWindow() : base("tools/light_editor/title") public LightEditorWindow() : base("tools/light_editor/title")
{ {
controller = new LightEditorController(); controller = new LightEditorController();
CthangoverTheme.Apply(this);
BuildUI(); BuildUI();
LoadBackgroundList(); LoadBackgroundList();
} }
@@ -1,5 +1,6 @@
using System; using System;
using Cthangover.Core.Scenes; using Cthangover.Core.Scenes;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.Utils; using Cthangover.Core.Utils;
using Cthangover.Tools.Services; using Cthangover.Tools.Services;
using Godot; using Godot;
@@ -27,6 +28,7 @@ namespace Cthangover.Core.UI.Tool.ScenarioEditor
public ScenarioEditorWindow() : base("tools/scenario_editor/title") public ScenarioEditorWindow() : base("tools/scenario_editor/title")
{ {
CthangoverTheme.Apply(this);
BuildUI(); BuildUI();
} }
+2 -1
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Cthangover.Core.UI.Theming;
using Cthangover.Tools.Services; using Cthangover.Tools.Services;
using Godot; using Godot;
@@ -36,7 +37,7 @@ namespace Cthangover.Core.UI.Tool.ScenarioEditor
var modItem = _fileTree.CreateItem(root); var modItem = _fileTree.CreateItem(root);
modItem.SetText(0, $"[{mod.ModId}]"); modItem.SetText(0, $"[{mod.ModId}]");
modItem.SetSelectable(0, false); modItem.SetSelectable(0, false);
modItem.SetCustomColor(0, new Color(0.5f, 0.75f, 1f)); modItem.SetCustomColor(0, UiTokens.Info);
foreach (var group in mod.Groups) foreach (var group in mod.Groups)
{ {
+11 -14
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Cthangover.Core.UI.Theming;
using Cthangover.Tools.Services; using Cthangover.Tools.Services;
using Godot; using Godot;
@@ -102,18 +103,18 @@ namespace Cthangover.Core.UI.Tool.ScenarioEditor
(bgCount > 1 ? $" +{bgCount - 1}" : "") : "") (bgCount > 1 ? $" +{bgCount - 1}" : "") : "")
}); });
var color = Colors.White; var color = UiTokens.White;
if (nodeData.IsStartScene) if (nodeData.IsStartScene)
{ {
color = new Color(0.3f, 1f, 0.3f); color = UiTokens.Success;
gn.AddThemeStyleboxOverride("titlebar", CreateTitlebarStyle(new Color(0.2f, 0.5f, 0.15f))); gn.AddThemeStyleboxOverride("titlebar", CreateTitlebarStyle(UiTokens.Alpha(UiTokens.Success, 0.3f)));
} }
else if (nodeData.HasErrors) else if (nodeData.HasErrors)
{ {
color = new Color(1f, 0.3f, 0.3f); color = UiTokens.DangerText;
gn.AddThemeStyleboxOverride("titlebar", CreateTitlebarStyle(new Color(0.5f, 0.1f, 0.1f))); gn.AddThemeStyleboxOverride("titlebar", CreateTitlebarStyle(UiTokens.Alpha(UiTokens.Danger, 0.5f)));
} }
gn.SetSlot(0, true, 0, Colors.White, true, 0, color); gn.SetSlot(0, true, 0, UiTokens.White, true, 0, color);
_graph.AddChild(gn); _graph.AddChild(gn);
_nodes[key] = gn; _nodes[key] = gn;
@@ -148,14 +149,10 @@ namespace Cthangover.Core.UI.Tool.ScenarioEditor
private static StyleBoxFlat CreateTitlebarStyle(Color bgColor) private static StyleBoxFlat CreateTitlebarStyle(Color bgColor)
{ {
return new StyleBoxFlat var style = UiKit.Frame(UiTokens.RadiusMd, bgColor);
{ style.CornerRadiusBottomLeft = 0;
BgColor = bgColor, style.CornerRadiusBottomRight = 0;
CornerRadiusTopLeft = 6, return style;
CornerRadiusTopRight = 6,
CornerRadiusBottomLeft = 0,
CornerRadiusBottomRight = 0
};
} }
private void ClearGraph() private void ClearGraph()
+4 -3
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Cthangover.Core.UI; using Cthangover.Core.UI;
using Cthangover.Core.UI.Theming;
using Godot; using Godot;
namespace Cthangover.Core.UI.Tool.SceneBuilder namespace Cthangover.Core.UI.Tool.SceneBuilder
@@ -65,7 +66,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
_banner = new Label(); _banner = new Label();
_banner.AutowrapMode = TextServer.AutowrapMode.WordSmart; _banner.AutowrapMode = TextServer.AutowrapMode.WordSmart;
_banner.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill; _banner.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
_banner.Modulate = new Color(1f, 0.75f, 0.3f); _banner.Modulate = UiTokens.Warning;
_banner.Visible = false; _banner.Visible = false;
root.AddChild(_banner); root.AddChild(_banner);
@@ -125,7 +126,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
foreach (var entry in InspectorPropertyCatalog.Build(node, insideContainer)) foreach (var entry in InspectorPropertyCatalog.Build(node, insideContainer))
{ {
var categoryLabel = new Label { Text = TranslationServer.Translate(entry.CategoryKey) }; var categoryLabel = new Label { Text = TranslationServer.Translate(entry.CategoryKey) };
categoryLabel.Modulate = new Color(1f, 0.85f, 0.4f); categoryLabel.Modulate = UiTokens.AccentBright;
_rows.AddChild(categoryLabel); _rows.AddChild(categoryLabel);
foreach (var property in entry.Properties) foreach (var property in entry.Properties)
@@ -367,7 +368,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
private Color ReadColor(string key) private Color ReadColor(string key)
{ {
var v = _node.Get(key); var v = _node.Get(key);
return v.VariantType == Variant.Type.Nil ? Colors.White : v.AsColor(); return v.VariantType == Variant.Type.Nil ? UiTokens.White : v.AsColor();
} }
private Vector2 ReadVector2(string key) private Vector2 ReadVector2(string key)
+4 -3
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using Cthangover.Core.Mods; using Cthangover.Core.Mods;
using Cthangover.Core.Scenes; using Cthangover.Core.Scenes;
using Cthangover.Core.UI.Theming;
using Godot; using Godot;
namespace Cthangover.Core.UI.Tool.SceneBuilder namespace Cthangover.Core.UI.Tool.SceneBuilder
@@ -240,7 +241,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
private void AttachHighlight(Node root) private void AttachHighlight(Node root)
{ {
_highlight = new ColorRect(); _highlight = new ColorRect();
_highlight.Color = new Color(1f, 0.7f, 0f, 0.35f); _highlight.Color = UiTokens.Alpha(UiTokens.Accent, 0.35f);
_highlight.Visible = false; _highlight.Visible = false;
_highlight.MouseFilter = Control.MouseFilterEnum.Ignore; _highlight.MouseFilter = Control.MouseFilterEnum.Ignore;
_highlight.ZIndex = 4096; _highlight.ZIndex = 4096;
@@ -335,7 +336,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
_highlight.Position = pos; _highlight.Position = pos;
_highlight.Size = new Vector2(20, 20); _highlight.Size = new Vector2(20, 20);
_highlight.Color = new Color(1f, 0.3f, 0.3f, 0.5f); _highlight.Color = UiTokens.Alpha(UiTokens.Danger, 0.5f);
_highlight.Visible = true; _highlight.Visible = true;
} }
} }
@@ -424,7 +425,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
{ {
if (_highlight != null) if (_highlight != null)
_highlight.Visible = false; _highlight.Visible = false;
_highlight.Color = new Color(1f, 0.7f, 0f, 0.35f); _highlight.Color = UiTokens.Alpha(UiTokens.Accent, 0.35f);
} }
} }
} }
+2
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Cthangover.Core.UI.Theming;
using Cthangover.Core.Utils; using Cthangover.Core.Utils;
using Godot; using Godot;
@@ -56,6 +57,7 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
/// <summary>Constructs the window, creates the controller, builds UI, and populates selectors.</summary> /// <summary>Constructs the window, creates the controller, builds UI, and populates selectors.</summary>
public SceneBuilderWindow() : base("tools/scene_builder/title") public SceneBuilderWindow() : base("tools/scene_builder/title")
{ {
CthangoverTheme.Apply(this);
_controller = new SceneBuilderController(); _controller = new SceneBuilderController();
BuildUI(); BuildUI();
PopulateBaseList(); PopulateBaseList();
+5 -4
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Cthangover.Core.UI; using Cthangover.Core.UI;
using Cthangover.Core.UI.Theming;
using Godot; using Godot;
namespace Cthangover.Core.UI.Tool.SceneBuilder namespace Cthangover.Core.UI.Tool.SceneBuilder
@@ -87,13 +88,13 @@ namespace Cthangover.Core.UI.Tool.SceneBuilder
Resized += Refresh; Resized += Refresh;
for (var i = 0; i < 4; i++) for (var i = 0; i < 4; i++)
_borderRects.Add(CreateMarker(new Color(1f, 0.85f, 0.35f, 0.95f))); _borderRects.Add(CreateMarker(UiTokens.Alpha(UiTokens.AccentBright, 0.95f)));
for (var i = 0; i < ResizeMarkerCount; i++) for (var i = 0; i < ResizeMarkerCount; i++)
_handleRects.Add(CreateMarker(new Color(1f, 0.62f, 0.1f, 1f))); _handleRects.Add(CreateMarker(UiTokens.Accent));
for (var i = 0; i < AnchorDotCount * 2; i++) for (var i = 0; i < AnchorDotCount * 2; i++)
_anchorLines.Add(CreateMarker(new Color(0.35f, 0.75f, 1f, 0.55f))); _anchorLines.Add(CreateMarker(UiTokens.Alpha(UiTokens.Info, 0.55f)));
for (var i = 0; i < AnchorDotCount; i++) for (var i = 0; i < AnchorDotCount; i++)
_anchorDots.Add(CreateMarker(new Color(0.45f, 0.85f, 1f, 1f))); _anchorDots.Add(CreateMarker(UiTokens.Info));
GuiInput += OnOverlayGui; GuiInput += OnOverlayGui;
} }
+10 -9
View File
@@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Cthangover.Core.Scenarios; using Cthangover.Core.Scenarios;
using Cthangover.Core.Factories.Impls; using Cthangover.Core.Factories.Impls;
using Cthangover.Core.UI.Theming;
using Godot; using Godot;
namespace Cthangover.Tools.Services namespace Cthangover.Tools.Services
@@ -18,19 +19,19 @@ namespace Cthangover.Tools.Services
{ {
/// <summary> /// <summary>
/// Builds a <see cref="CodeHighlighter"/> for scenario DSL syntax. /// Builds a <see cref="CodeHighlighter"/> for scenario DSL syntax.
/// Comments (lines starting with <c>#</c>) are green, strings are orange, /// Comments (lines starting with <c>#</c>) are green, strings are bright
/// command names are blue, and argument keywords (e.g. <c>key</c>, /// gold, command names are blue, and argument keywords (e.g. <c>key</c>,
/// <c>wait</c>, <c>quest_id</c>) are amber. /// <c>wait</c>, <c>quest_id</c>) are amber — all from <see cref="UiTokens"/>.
/// </summary> /// </summary>
public static CodeHighlighter CreateHighlighter() public static CodeHighlighter CreateHighlighter()
{ {
var hl = new CodeHighlighter(); var hl = new CodeHighlighter();
hl.AddColorRegion("#", null, new Color(0.45f, 0.75f, 0.45f), true); hl.AddColorRegion("#", null, UiTokens.Success, true);
hl.AddColorRegion("\"", "\"", new Color(1f, 0.6f, 0.4f), false); hl.AddColorRegion("\"", "\"", UiTokens.AccentBright, false);
hl.NumberColor = new Color(0.7f, 0.7f, 1f); hl.NumberColor = UiTokens.Info;
hl.SymbolColor = new Color(0.8f, 0.8f, 0.8f); hl.SymbolColor = UiTokens.Muted;
var cmdColor = new Color(0.4f, 0.7f, 1f); var cmdColor = UiTokens.Info;
hl.KeywordColors = new Godot.Collections.Dictionary(); hl.KeywordColors = new Godot.Collections.Dictionary();
foreach (var cmd in ScenarioCommandStrategyFactory.GetAllCommandNames()) foreach (var cmd in ScenarioCommandStrategyFactory.GetAllCommandNames())
@@ -40,7 +41,7 @@ namespace Cthangover.Tools.Services
"option", "select" "option", "select"
}) hl.KeywordColors[cmd] = cmdColor; }) hl.KeywordColors[cmd] = cmdColor;
var argColor = new Color(0.8f, 0.6f, 0.3f); var argColor = UiTokens.Accent;
foreach (var kw in new[] { foreach (var kw in new[] {
"key", "first", "second", "hide_color", "wait", "speed", "hidden", "key", "first", "second", "hide_color", "wait", "speed", "hidden",
"sprites", "loop", "target", "quest_id", "show", "hide", "duration" "sprites", "loop", "target", "quest_id", "show", "hide", "duration"