From 1995aae77dab086a5f333559fceb0ebdb71d319d Mon Sep 17 00:00:00 2001 From: iisaev Date: Fri, 13 Nov 2026 17:52:27 +0100 Subject: [PATCH] feat: use authored category names for mods Store categories as authored strings. Trim and deduplicate without changing case, compare without case sensitivity, and keep all observed categories available to filters and editors. --- locale/ui_en.properties | 48 ++++-- locale/ui_es.properties | 28 ++-- locale/ui_ja.properties | 28 ++-- locale/ui_ko.properties | 28 ++-- locale/ui_ru.properties | 48 ++++-- locale/ui_vi.properties | 28 ++-- locale/ui_zh.properties | 28 ++-- manifest.json | 2 +- scenes/components/mod_category_editor.tscn | 57 +++++++ src/View/ModCategoryEditor.cs | 165 +++++++++++++++++++++ src/View/ModCategoryNames.cs | 45 ++++++ 11 files changed, 406 insertions(+), 99 deletions(-) create mode 100644 scenes/components/mod_category_editor.tscn create mode 100644 src/View/ModCategoryEditor.cs create mode 100644 src/View/ModCategoryNames.cs diff --git a/locale/ui_en.properties b/locale/ui_en.properties index b5f3de2..7d1bed4 100644 --- a/locale/ui_en.properties +++ b/locale/ui_en.properties @@ -57,20 +57,20 @@ mods/catalog_export = Export to Catalog mods/catalog_title = Export Catalog Entry mods/catalog_download_url = Download URL mods/catalog_category = Category -mods/category_story = Story -mods/category_characters = Characters -mods/category_gameplay = Gameplay -mods/category_visual = Visual -mods/category_audio = Audio -mods/category_ui = UI -mods/category_locale = Locale -mods/category_library = Library -mods/category_engine = Engine -mods/category_overhaul = Overhaul -mods/category_tools = Tools -mods/category_editor = Editor -mods/category_debug = Debug -mods/category_other = Other +mod_category/story = Story +mod_category/characters = Characters +mod_category/gameplay = Gameplay +mod_category/visual = Visual +mod_category/audio = Audio +mod_category/ui = UI +mod_category/locale = Locale +mod_category/library = Library +mod_category/engine = Engine +mod_category/overhaul = Overhaul +mod_category/tools = Tools +mod_category/editor = Editor +mod_category/debug = Debug +mod_category/other = Other mods/catalog_tags = Tags (comma-separated) mods/catalog_changelog = Changelog mods/catalog_status = Status @@ -269,3 +269,23 @@ tools/menu_title = Tools # --- Development cover --- ui/cover/in_development = In development + +mod_categories/title = Categories +mod_categories/code = Category, e.g. RPG — Gear +mod_categories/add = Add +mod_categories/primary = Primary category +mod_categories/suggestions = Choose a category… +mod_categories/save = Save categories +mod_categories/saved = Categories saved to manifest.json. +mod_categories/development = Saved in the development mod before packaging. +mod_categories/readonly = Categories of installed packages and catalog entries are read-only. Edit the development folder. +mod_categories/pending = Add the typed category or clear the input before continuing. + +mod_categories/hint_code = Enter any category name; spelling is preserved. +mod_categories/hint_suggestions = Choose a category from installed mods, catalogs or the base suggestions. +mod_categories/hint_primary = The primary category appears on the card and determines its group. It is saved first. +mod_categories/hint_add = Add the entered category. +mod_categories/hint_base = Include or remove this category. +mod_categories/hint_remove = Remove this custom category. + +mod_categories/hint_filter = Show mods with this category: diff --git a/locale/ui_es.properties b/locale/ui_es.properties index d123637..5072726 100644 --- a/locale/ui_es.properties +++ b/locale/ui_es.properties @@ -57,20 +57,20 @@ mods/catalog_export = Exportar al catálogo mods/catalog_title = Exportar entrada del catálogo mods/catalog_download_url = URL de descarga mods/catalog_category = Categoría -mods/category_story = Historia -mods/category_characters = Personajes -mods/category_gameplay = Jugabilidad -mods/category_visual = Visual -mods/category_audio = Audio -mods/category_ui = Interfaz -mods/category_locale = Idioma -mods/category_library = Biblioteca -mods/category_engine = Motor -mods/category_overhaul = Conversión total -mods/category_tools = Herramientas -mods/category_editor = Editor -mods/category_debug = Depuración -mods/category_other = Otros +mod_category/story = Historia +mod_category/characters = Personajes +mod_category/gameplay = Jugabilidad +mod_category/visual = Visual +mod_category/audio = Audio +mod_category/ui = Interfaz +mod_category/locale = Idioma +mod_category/library = Biblioteca +mod_category/engine = Motor +mod_category/overhaul = Conversión total +mod_category/tools = Herramientas +mod_category/editor = Editor +mod_category/debug = Depuración +mod_category/other = Otros mods/catalog_tags = Etiquetas (separadas por comas) mods/catalog_changelog = Cambios mods/catalog_status = Estado diff --git a/locale/ui_ja.properties b/locale/ui_ja.properties index 833281f..9f7c4f9 100644 --- a/locale/ui_ja.properties +++ b/locale/ui_ja.properties @@ -57,20 +57,20 @@ mods/catalog_export = カタログに書き出す mods/catalog_title = カタログ項目を書き出す mods/catalog_download_url = ダウンロード URL mods/catalog_category = カテゴリー -mods/category_story = ストーリー -mods/category_characters = キャラクター -mods/category_gameplay = ゲームプレイ -mods/category_visual = ビジュアル -mods/category_audio = オーディオ -mods/category_ui = UI -mods/category_locale = 言語 -mods/category_library = ライブラリ -mods/category_engine = エンジン -mods/category_overhaul = 大型改造 -mods/category_tools = ツール -mods/category_editor = エディター -mods/category_debug = デバッグ -mods/category_other = その他 +mod_category/story = ストーリー +mod_category/characters = キャラクター +mod_category/gameplay = ゲームプレイ +mod_category/visual = ビジュアル +mod_category/audio = オーディオ +mod_category/ui = UI +mod_category/locale = 言語 +mod_category/library = ライブラリ +mod_category/engine = エンジン +mod_category/overhaul = 大型改造 +mod_category/tools = ツール +mod_category/editor = エディター +mod_category/debug = デバッグ +mod_category/other = その他 mods/catalog_tags = タグ(カンマ区切り) mods/catalog_changelog = 変更履歴 mods/catalog_status = 状態 diff --git a/locale/ui_ko.properties b/locale/ui_ko.properties index 7c4a6d6..aac262a 100644 --- a/locale/ui_ko.properties +++ b/locale/ui_ko.properties @@ -57,20 +57,20 @@ mods/catalog_export = 카탈로그로 내보내기 mods/catalog_title = 카탈로그 항목 내보내기 mods/catalog_download_url = 다운로드 URL mods/catalog_category = 분류 -mods/category_story = 스토리 -mods/category_characters = 캐릭터 -mods/category_gameplay = 게임플레이 -mods/category_visual = 비주얼 -mods/category_audio = 오디오 -mods/category_ui = UI -mods/category_locale = 언어 -mods/category_library = 라이브러리 -mods/category_engine = 엔진 -mods/category_overhaul = 대규모 개편 -mods/category_tools = 도구 -mods/category_editor = 에디터 -mods/category_debug = 디버그 -mods/category_other = 기타 +mod_category/story = 스토리 +mod_category/characters = 캐릭터 +mod_category/gameplay = 게임플레이 +mod_category/visual = 비주얼 +mod_category/audio = 오디오 +mod_category/ui = UI +mod_category/locale = 언어 +mod_category/library = 라이브러리 +mod_category/engine = 엔진 +mod_category/overhaul = 대규모 개편 +mod_category/tools = 도구 +mod_category/editor = 에디터 +mod_category/debug = 디버그 +mod_category/other = 기타 mods/catalog_tags = 태그 (쉼표로 구분) mods/catalog_changelog = 변경 기록 mods/catalog_status = 상태 diff --git a/locale/ui_ru.properties b/locale/ui_ru.properties index f985478..cb9e450 100644 --- a/locale/ui_ru.properties +++ b/locale/ui_ru.properties @@ -57,20 +57,20 @@ mods/catalog_export = Экспорт в каталог mods/catalog_title = Экспорт записи каталога mods/catalog_download_url = URL скачивания mods/catalog_category = Категория -mods/category_story = Сюжет -mods/category_characters = Персонажи -mods/category_gameplay = Геймплей -mods/category_visual = Визуал -mods/category_audio = Аудио -mods/category_ui = Интерфейс -mods/category_locale = Перевод -mods/category_library = Библиотека -mods/category_engine = Движок -mods/category_overhaul = Тотальная конверсия -mods/category_tools = Инструменты -mods/category_editor = Редактор -mods/category_debug = Отладка -mods/category_other = Прочее +mod_category/story = Сюжет +mod_category/characters = Персонажи +mod_category/gameplay = Геймплей +mod_category/visual = Визуал +mod_category/audio = Аудио +mod_category/ui = Интерфейс +mod_category/locale = Перевод +mod_category/library = Библиотека +mod_category/engine = Движок +mod_category/overhaul = Тотальная конверсия +mod_category/tools = Инструменты +mod_category/editor = Редактор +mod_category/debug = Отладка +mod_category/other = Прочее mods/catalog_tags = Теги (через запятую) mods/catalog_changelog = Список изменений mods/catalog_status = Статус @@ -269,3 +269,23 @@ tools/menu_title = Инструменты # --- Development cover --- ui/cover/in_development = В разработке + +mod_categories/title = Категории +mod_categories/code = Категория, например RPG — оружие +mod_categories/add = Добавить +mod_categories/primary = Основная категория +mod_categories/suggestions = Выбрать категорию… +mod_categories/save = Сохранить категории +mod_categories/saved = Категории сохранены в manifest.json. +mod_categories/development = Сохраняются в папке разработки мода до упаковки. +mod_categories/readonly = Категории установленных пакетов и записей каталога доступны для чтения. Правьте папку разработки. +mod_categories/pending = Добавьте набранную категорию или очистите поле перед продолжением. + +mod_categories/hint_code = Введите любое название категории; написание сохраняется. +mod_categories/hint_suggestions = Выберите категорию из установленных модов, каталогов или базовых подсказок. +mod_categories/hint_primary = Основная категория показывается в карточке и определяет её группу. Сохраняется первой. +mod_categories/hint_add = Добавить введённую категорию. +mod_categories/hint_base = Добавить или убрать эту категорию. +mod_categories/hint_remove = Убрать эту свою категорию. + +mod_categories/hint_filter = Показать моды с этой категорией: diff --git a/locale/ui_vi.properties b/locale/ui_vi.properties index 13fb7ca..ae9d053 100644 --- a/locale/ui_vi.properties +++ b/locale/ui_vi.properties @@ -57,20 +57,20 @@ mods/catalog_export = Xuất sang danh mục mods/catalog_title = Xuất mục danh mục mods/catalog_download_url = URL tải xuống mods/catalog_category = Thể loại -mods/category_story = Cốt truyện -mods/category_characters = Nhân vật -mods/category_gameplay = Lối chơi -mods/category_visual = Hình ảnh -mods/category_audio = Âm thanh -mods/category_ui = Giao diện -mods/category_locale = Ngôn ngữ -mods/category_library = Thư viện -mods/category_engine = Engine -mods/category_overhaul = Đại tu -mods/category_tools = Công cụ -mods/category_editor = Trình sửa -mods/category_debug = Gỡ lỗi -mods/category_other = Khác +mod_category/story = Cốt truyện +mod_category/characters = Nhân vật +mod_category/gameplay = Lối chơi +mod_category/visual = Hình ảnh +mod_category/audio = Âm thanh +mod_category/ui = Giao diện +mod_category/locale = Ngôn ngữ +mod_category/library = Thư viện +mod_category/engine = Bộ máy +mod_category/overhaul = Đại tu +mod_category/tools = Công cụ +mod_category/editor = Trình sửa +mod_category/debug = Gỡ lỗi +mod_category/other = Khác mods/catalog_tags = Thẻ (cách nhau bằng dấu phẩy) mods/catalog_changelog = Nhật ký thay đổi mods/catalog_status = Trạng thái diff --git a/locale/ui_zh.properties b/locale/ui_zh.properties index abcd2df..d22fe8c 100644 --- a/locale/ui_zh.properties +++ b/locale/ui_zh.properties @@ -57,20 +57,20 @@ mods/catalog_export = 导出到目录 mods/catalog_title = 导出目录条目 mods/catalog_download_url = 下载 URL mods/catalog_category = 分类 -mods/category_story = 剧情 -mods/category_characters = 角色 -mods/category_gameplay = 玩法 -mods/category_visual = 视觉 -mods/category_audio = 音频 -mods/category_ui = 界面 -mods/category_locale = 语言 -mods/category_library = 库 -mods/category_engine = 引擎 -mods/category_overhaul = 大型改动 -mods/category_tools = 工具 -mods/category_editor = 编辑器 -mods/category_debug = 调试 -mods/category_other = 其他 +mod_category/story = 剧情 +mod_category/characters = 角色 +mod_category/gameplay = 玩法 +mod_category/visual = 视觉 +mod_category/audio = 音频 +mod_category/ui = 界面 +mod_category/locale = 语言 +mod_category/library = 库 +mod_category/engine = 引擎 +mod_category/overhaul = 大型改动 +mod_category/tools = 工具 +mod_category/editor = 编辑器 +mod_category/debug = 调试 +mod_category/other = 其他 mods/catalog_tags = 标签(逗号分隔) mods/catalog_changelog = 更新日志 mods/catalog_status = 状态 diff --git a/manifest.json b/manifest.json index edff27e..846b807 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "version": "0.1.0", "author": "ct", "description": "The interface layer every game shares: the toolbar, the in-game menu, the save indicator, notifications and the common look of panels, buttons and lists.", - "category": "ui", + "categories": ["ui"], "depends": [], "sources": [ "src/**/*.cs" diff --git a/scenes/components/mod_category_editor.tscn b/scenes/components/mod_category_editor.tscn new file mode 100644 index 0000000..0375509 --- /dev/null +++ b/scenes/components/mod_category_editor.tscn @@ -0,0 +1,57 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/View/ModCategoryEditor.cs" id="1"] + +[node name="ModCategoryEditor" type="Control"] +custom_minimum_size = Vector2(440, 260) +size_flags_horizontal = 3 +script = ExtResource("1") + +[node name="Layout" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Layout"] +layout_mode = 2 +text = "mod_categories/title" + +[node name="Base" type="GridContainer" parent="Layout"] +layout_mode = 2 +columns = 4 + +[node name="Custom" type="HFlowContainer" parent="Layout"] +layout_mode = 2 + +[node name="Input" type="HBoxContainer" parent="Layout"] +layout_mode = 2 + +[node name="Code" type="LineEdit" parent="Layout/Input"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "mod_categories/code" + +[node name="Add" type="Button" parent="Layout/Input"] +layout_mode = 2 +text = "mod_categories/add" + +[node name="Suggestions" type="OptionButton" parent="Layout"] +layout_mode = 2 +fit_to_longest_item = false + +[node name="PrimaryRow" type="HBoxContainer" parent="Layout"] +layout_mode = 2 + +[node name="Caption" type="Label" parent="Layout/PrimaryRow"] +layout_mode = 2 +text = "mod_categories/primary" + +[node name="Primary" type="OptionButton" parent="Layout/PrimaryRow"] +layout_mode = 2 +fit_to_longest_item = false +text_overrun_behavior = 3 +size_flags_horizontal = 3 diff --git a/src/View/ModCategoryEditor.cs b/src/View/ModCategoryEditor.cs new file mode 100644 index 0000000..2624748 --- /dev/null +++ b/src/View/ModCategoryEditor.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Cthangover.Core.Mods; +using Cthangover.Core.Scenes; +using Cthangover.Core.Utils; +using Cthangover.Mods.Interface.Base.Lists; +using Godot; + +namespace Cthangover.Mods.Interface.View +{ + +/// Shared ordered category editor. Base checkboxes, custom chips, code completion and primary choice edit the same list. +public partial class ModCategoryEditor : ModWidget +{ + private readonly List selected = new(); + private readonly List known = new(); + private readonly Dictionary checks = new(ModCategories.Comparer); + private LineEdit input; + private OptionButton suggestions; + private OptionButton primary; + private bool refreshing; + private bool editable = true; + + public event Action Changed; + /// Snapshot in publishing order; choosing the primary moves it to the first position. + public List Categories => new(selected); + public bool HasPendingInput => !string.IsNullOrWhiteSpace(input?.Text); + + public static ModCategoryEditor Create(IEnumerable categories) + { + var editor = TscnScenes.LoadAndBuild("scenes/components/mod_category_editor.tscn") as ModCategoryEditor + ?? throw new InvalidOperationException("Category editor scene unavailable"); + editor.SetCategories(categories); + return editor; + } + + public static string ProjectRoot => GameEnvironment.IsRuntime ? GamePaths.Globalize("res://") : System.IO.Directory.GetCurrentDirectory(); + + public void SetCategories(IEnumerable categories) + { + EnsureConstructed(); + selected.Clear(); + selected.AddRange(ModCategories.Effective(categories)); + known.Clear(); + known.AddRange(ModCategories.Normalize(ModCategoryNames.Known().Concat(selected))); + Refresh(); + } + + public void SetEditable(bool value) + { + editable = value; + EnsureConstructed(); + Refresh(); + } + + protected override void Construct() + { + input = GetNode("Layout/Input/Code"); + suggestions = GetNode("Layout/Suggestions"); + primary = GetNode("Layout/PrimaryRow/Primary"); + input.TooltipText = Tr("mod_categories/hint_code"); + suggestions.TooltipText = Tr("mod_categories/hint_suggestions"); + primary.TooltipText = Tr("mod_categories/hint_primary"); + GetNode