commit e8e0c5159de6099e49f2c2cb3a16abe75e66a5e9 Author: iisaev Date: Sun Oct 18 12:41:39 2026 +0300 init mod diff --git a/locale/en.properties b/locale/en.properties new file mode 100644 index 0000000..09de939 --- /dev/null +++ b/locale/en.properties @@ -0,0 +1,221 @@ +# mod_manager — mod manager localization + +mod_mod_manager_name = Mod Manager +mod_mod_manager_desc = Nexus-style mod manager: catalog browsing, category filters, install, update and remove. + +mod_manager/menu_title = Mods & Collections +mod_manager/title = Mod Manager +mod_manager/back = Close +mod_manager/back_to_list = Back +mod_manager/search_placeholder = Search mods... +mod_manager/sort_name = By name +mod_manager/sort_author = By author +mod_manager/sort_status = By status +mod_manager/refresh = Refresh catalog +mod_manager/loading = Loading catalog... +mod_manager/results = Mods: {0} + +mod_manager/filters = Filters +mod_manager/reset_filters = Reset +mod_manager/filter_status = Status +mod_manager/filter_categories = Categories +mod_manager/group_by_category = Group by category + +mod_manager/status_installed = Installed +mod_manager/status_not_installed = Not installed +mod_manager/status_update = Update available +mod_manager/status_downgrade = Older version available +mod_manager/status_modified = Modified locally +mod_manager/status_disabled = Disabled +mod_manager/status_conflict = Catalog conflict +mod_manager/conflict_title = Warning +mod_manager/conflict_warning = The same mod with the same version and title is published by different catalogs with different content. One variant may be counterfeit: install only from a trusted source. +mod_manager/source_catalog = Catalog: {0} +mod_manager/source_local = Local mod + +mod_manager/category_story = Story +mod_manager/category_characters = Characters +mod_manager/category_gameplay = Gameplay +mod_manager/category_visual = Visual +mod_manager/category_audio = Audio +mod_manager/category_ui = UI +mod_manager/category_locale = Locale +mod_manager/category_library = Library +mod_manager/category_engine = Engine +mod_manager/category_overhaul = Overhaul +mod_manager/category_tools = Tools +mod_manager/category_editor = Editor +mod_manager/category_debug = Debug +mod_manager/category_other = Other + +mod_manager/action_install = Install +mod_manager/action_update = Update +mod_manager/action_downgrade = Downgrade +mod_manager/action_reinstall = Reinstall +mod_manager/action_delete = Delete +mod_manager/action_enable = Enable +mod_manager/action_disable = Disable + +mod_manager/restart_required = Changes will take effect after restarting the game +mod_manager/progress_installing = Installing "{0}"... +mod_manager/install_failed = Install failed. Check your connection and try again. +mod_manager/delete_title = Delete mod +mod_manager/delete_text = Delete mod "{0}"? This is irreversible and takes effect after restart. +mod_manager/delete_confirm = Delete +mod_manager/delete_failed = Failed to delete the mod. See the log. +mod_manager/cancel = Cancel + +mod_manager/installed_version = Installed: {0} +mod_manager/not_installed_hint = Not installed +mod_manager/latest = latest +mod_manager/installed_marker = installed +mod_manager/no_results = Nothing found +mod_manager/description = Description +mod_manager/depends = Depends on +mod_manager/used_by = Used by +mod_manager/conflicts = Conflicts +mod_manager/changelog = Changelog +mod_manager/version = Version: +mod_manager/self_hint = System mod: cannot be deleted or disabled + +mod_manager/collections_menu_title = Collections +mod_manager/collections_title = Collections +mod_manager/collections_empty = No collections found +mod_manager/collection_result = Mods: {0}/{1} +mod_manager/collection_mechanics = Mechanics +mod_manager/collection_node = Mod +mod_manager/collection_plan = Install plan +mod_manager/collection_apply = Apply collection +mod_manager/collection_plan_ready = Everything is ready +mod_manager/collection_install_count = To install: {0} +mod_manager/collection_enable_count = To enable: {0} +mod_manager/collection_missing = Missing from the catalog: {0} +mod_manager/collection_mismatch = Version mismatch: {0} +mod_manager/collection_optional = optional +mod_manager/collection_externals = Dependencies +mod_manager/collection_external = dependency +mod_manager/collection_node_hint = Select a mod on the graph +mod_manager/collection_requires = Requires: {0} +mod_manager/collection_origin_builtin = built-in +mod_manager/collection_origin_user = local +mod_manager/collection_origin_catalog = catalog +mod_manager/collection_progress = Applying "{0}"... +mod_manager/collection_apply_failed = Failed to apply the collection. See the log. +mod_manager/collection_state_installed = Installed +mod_manager/collection_state_disabled = Disabled +mod_manager/collection_state_catalog = Available in catalog +mod_manager/collection_state_missing = Not found +mod_manager/collection_state_mismatch = Version mismatch + +# Scheme editor (collections pyramid) +mod_manager/collection_add_mechanic = + Mechanic +mod_manager/collection_new_game = + Game +mod_manager/collection_new_game_name = New game +mod_manager/collection_new_game_desc = Assemble a game from mechanics: add blocks and mods. +mod_manager/collection_new_mechanic_name = New mechanic +mod_manager/collection_group_ready = ready +mod_manager/collection_group_empty = empty +mod_manager/collection_group_off = off +mod_manager/collection_links = Links +mod_manager/collection_problems = Problems +mod_manager/collection_tab_inspector = Inspector +mod_manager/collection_tab_problems = Check +mod_manager/collection_tab_plan = Plan +mod_manager/collection_plan_install = to install +mod_manager/collection_plan_enable = to enable +mod_manager/collection_save = Save +mod_manager/collection_reset = Reset +mod_manager/collection_json = JSON +mod_manager/collection_save_ok = Saved to user://collections.json +mod_manager/collection_no_changes = Nothing to save +mod_manager/collection_reset_confirm = Discard unsaved changes? +mod_manager/collection_rename_title = Name and description +mod_manager/collection_field_name = Name +mod_manager/collection_field_note = Description +mod_manager/collection_add_mod = Add mod +mod_manager/collection_empty_mechanic = Empty mechanic +mod_manager/collection_empty_mechanic_desc = Create a contour from scratch: add the name, description and mods manually. +mod_manager/collection_pick_mechanic = Add mechanic +mod_manager/collection_pick_replace = Replace mechanic +mod_manager/collection_choose = Add +mod_manager/collection_replace = Replace +mod_manager/collection_remove = Remove +mod_manager/collection_rename = Rename +mod_manager/collection_create = Create +mod_manager/collection_where = Add to +mod_manager/collection_new_extra = + new "Extra" mechanic +mod_manager/collection_extra_name = Extra +mod_manager/collection_extra_note = Manually added mods. +mod_manager/collection_search_mechanic = Search mechanics... +mod_manager/collection_search_mod = Search mods... +mod_manager/collection_problems_none = No problems - the assembly is consistent. +mod_manager/collection_problem_missing = Block "{0}" not found +mod_manager/collection_problem_cycle = Cycle: "{0}" -> "{1}" +mod_manager/collection_problem_role = Slot "{0}" is claimed twice +mod_manager/collection_problem_require = "{0}": requirement "{1}" is not met +mod_manager/collection_show = Show +mod_manager/collection_hint = Select a contour or a mod. Drag frames by the header, resize by the corner, move mods freely. Drag the empty canvas with the left button to pan. +mod_manager/collection_mechanic = mechanic +mod_manager/collection_group = group +mod_manager/collection_mods = mods +mod_manager/collection_in_group = In group +mod_manager/collection_remove_mod = Remove from mechanic +mod_manager/collection_turn_on = Turn on +mod_manager/collection_turn_off = Turn off +mod_manager/collection_unsaved = unsaved changes + +# ─── Mods & collections hub ─── +mod_manager/hub_tab_mods = Mods +mod_manager/hub_tab_collections = Collections +mod_manager/hub_back_to_menu = ← Menu +mod_manager/hub_back_to_gallery = ← Games +mod_manager/hub_in_one_collection = in {0} collection +mod_manager/hub_in_many_collections = in {0} collections + +# Gallery of ready games +mod_manager/gallery_crumb = Ready-made games +mod_manager/gallery_title = Games +mod_manager/gallery_hint = ready-made mod sets: one button installs everything +mod_manager/gallery_search_placeholder = Search collections... +mod_manager/gallery_new_game = + Build your own game +mod_manager/gallery_new_game_blank = + Build your own game from scratch +mod_manager/gallery_empty_hint = Add a collections/ folder with JSON files to your mod — the collections will appear here. +mod_manager/gallery_edit_scheme = Edit scheme +mod_manager/gallery_ready = Ready to play +mod_manager/gallery_ready_done = Ready ✓ +mod_manager/gallery_missing_n = Missing {0} +mod_manager/gallery_problems_n = Problems: {0} +mod_manager/gallery_enable_badge_n = Enable {0} +mod_manager/gallery_install_btn_n = Install ({0}) +mod_manager/gallery_enable_btn_n = Enable ({0}) +mod_manager/gallery_draft = Draft +mod_manager/gallery_continue = Continue building + +# Bottom build bar (scheme editor) +mod_manager/build_caption = Build +mod_manager/build_stat_install = Install +mod_manager/build_stat_enable = Enable +mod_manager/build_stat_problems = Problems +mod_manager/build_hint_problems = Fix the problems to apply the collection +mod_manager/build_open_manager = Open mod manager +mod_manager/collection_crumb_scheme = Scheme +mod_manager/collection_find_in_catalog = Find in catalog + + +mod_manager/collection_duplicate = Duplicate +mod_manager/collection_revert = Revert to built-in +mod_manager/collection_saves = Saves: {0} +mod_manager/collection_next_launch = Changes apply the next time the game starts. +mod_manager/collection_json_apply = Apply +mod_manager/collection_json_invalid = Invalid JSON: {0} +mod_manager/collection_json_id_changed = The collection id cannot change — use Duplicate for a new game. +mod_manager/collection_copy_name = {0} (copy) +mod_manager/collection_copy_saves = The original game has saves ({0}). Copy them to the new game? +mod_manager/collection_copy_saves_ok = Copy +mod_manager/collection_revert_confirm = Discard your changes and restore the built-in version of the game? Saves stay. +mod_manager/collection_revert_done = Built-in version restored. +mod_manager/collection_delete = Delete collection +mod_manager/collection_delete_confirm = The collection «{0}» will be deleted. Its mods stay installed in the system, and its saves ({1}) stay on disk. +mod_manager/collection_delete_done = Collection deleted. Its mods stay in the system. +mod_manager/collection_nested_readonly = This block is nested deeper — open it on its own to change it. +mod_manager/collection_forked = Block “{0}” copied for this game — other games stay unchanged. diff --git a/locale/ru.properties b/locale/ru.properties new file mode 100644 index 0000000..1a7737f --- /dev/null +++ b/locale/ru.properties @@ -0,0 +1,221 @@ +# mod_manager — локализация менеджера модов + +mod_mod_manager_name = Менеджер модов +mod_mod_manager_desc = Менеджер модов в стиле Nexus: каталог, фильтры по категориям, установка, обновление и удаление. + +mod_manager/menu_title = Моды и коллекции +mod_manager/title = Менеджер модов +mod_manager/back = Закрыть +mod_manager/back_to_list = Назад +mod_manager/search_placeholder = Поиск модов... +mod_manager/sort_name = По имени +mod_manager/sort_author = По автору +mod_manager/sort_status = По статусу +mod_manager/refresh = Обновить каталог +mod_manager/loading = Загрузка каталога... +mod_manager/results = Модов: {0} + +mod_manager/filters = Фильтры +mod_manager/reset_filters = Сбросить +mod_manager/filter_status = Статус +mod_manager/filter_categories = Категории +mod_manager/group_by_category = Группировать по категориям + +mod_manager/status_installed = Установлен +mod_manager/status_not_installed = Не установлен +mod_manager/status_update = Есть обновление +mod_manager/status_downgrade = Доступна старая версия +mod_manager/status_modified = Изменён локально +mod_manager/status_disabled = Выключен +mod_manager/status_conflict = Конфликт каталогов +mod_manager/conflict_title = Предупреждение +mod_manager/conflict_warning = Один и тот же мод с одинаковой версией и названием опубликован в разных каталогах с разным содержимым. Один из вариантов может быть подделкой: устанавливайте только из доверенного источника. +mod_manager/source_catalog = Каталог: {0} +mod_manager/source_local = Локальный мод + +mod_manager/category_story = Сюжет +mod_manager/category_characters = Персонажи +mod_manager/category_gameplay = Геймплей +mod_manager/category_visual = Визуал +mod_manager/category_audio = Аудио +mod_manager/category_ui = Интерфейс +mod_manager/category_locale = Перевод +mod_manager/category_library = Библиотека +mod_manager/category_engine = Движок +mod_manager/category_overhaul = Оверхаул +mod_manager/category_tools = Инструменты +mod_manager/category_editor = Редактор +mod_manager/category_debug = Отладка +mod_manager/category_other = Прочее + +mod_manager/action_install = Установить +mod_manager/action_update = Обновить +mod_manager/action_downgrade = Понизить +mod_manager/action_reinstall = Переустановить +mod_manager/action_delete = Удалить +mod_manager/action_enable = Включить +mod_manager/action_disable = Выключить + +mod_manager/restart_required = Изменения вступят в силу после перезапуска игры +mod_manager/progress_installing = Установка "{0}"... +mod_manager/install_failed = Не удалось установить мод. Проверьте подключение и повторите. +mod_manager/delete_title = Удаление мода +mod_manager/delete_text = Удалить мод "{0}"? Действие необратимо и вступит в силу после перезапуска. +mod_manager/delete_confirm = Удалить +mod_manager/delete_failed = Не удалось удалить мод. Смотрите лог. +mod_manager/cancel = Отмена + +mod_manager/installed_version = Установлено: {0} +mod_manager/not_installed_hint = Не установлен +mod_manager/latest = последняя +mod_manager/installed_marker = установлена +mod_manager/no_results = Ничего не найдено +mod_manager/description = Описание +mod_manager/depends = Зависимости +mod_manager/used_by = Используется +mod_manager/conflicts = Конфликты +mod_manager/changelog = Изменения +mod_manager/version = Версия: +mod_manager/self_hint = Системный мод: удаление и выключение недоступны + +mod_manager/collections_menu_title = Коллекции +mod_manager/collections_title = Коллекции +mod_manager/collections_empty = Коллекции не найдены +mod_manager/collection_result = Модов: {0}/{1} +mod_manager/collection_mechanics = Механики +mod_manager/collection_node = Мод +mod_manager/collection_plan = План установки +mod_manager/collection_apply = Применить коллекцию +mod_manager/collection_plan_ready = Всё готово +mod_manager/collection_install_count = Установить: {0} +mod_manager/collection_enable_count = Включить: {0} +mod_manager/collection_missing = Нет в каталоге: {0} +mod_manager/collection_mismatch = Несовпадение версий: {0} +mod_manager/collection_optional = необязательная +mod_manager/collection_externals = Зависимости +mod_manager/collection_external = зависимость +mod_manager/collection_node_hint = Выберите мод на графе +mod_manager/collection_requires = Требуется: {0} +mod_manager/collection_origin_builtin = встроенная +mod_manager/collection_origin_user = локальная +mod_manager/collection_origin_catalog = из каталога +mod_manager/collection_progress = Применение "{0}"... +mod_manager/collection_apply_failed = Не удалось применить коллекцию. Смотрите лог. +mod_manager/collection_state_installed = Установлен +mod_manager/collection_state_disabled = Выключен +mod_manager/collection_state_catalog = Доступен в каталоге +mod_manager/collection_state_missing = Не найден +mod_manager/collection_state_mismatch = Версия не подходит + +# Схема коллекции (пирамида) +mod_manager/collection_add_mechanic = + Механика +mod_manager/collection_new_game = + Игра +mod_manager/collection_new_game_name = Новая игра +mod_manager/collection_new_game_desc = Соберите игру из механик: добавляйте блоки и моды. +mod_manager/collection_new_mechanic_name = Новая механика +mod_manager/collection_group_ready = готово +mod_manager/collection_group_empty = пусто +mod_manager/collection_group_off = выключена +mod_manager/collection_links = Связи +mod_manager/collection_problems = Проблемы +mod_manager/collection_tab_inspector = Инспектор +mod_manager/collection_tab_problems = Проверка +mod_manager/collection_tab_plan = План +mod_manager/collection_plan_install = установить +mod_manager/collection_plan_enable = включить +mod_manager/collection_save = Сохранить +mod_manager/collection_reset = Сбросить +mod_manager/collection_json = JSON +mod_manager/collection_save_ok = Сохранено в user://collections.json +mod_manager/collection_no_changes = Нет изменений для сохранения +mod_manager/collection_reset_confirm = Сбросить несохранённые правки? +mod_manager/collection_rename_title = Название и описание +mod_manager/collection_field_name = Название +mod_manager/collection_field_note = Описание +mod_manager/collection_add_mod = Добавить мод +mod_manager/collection_empty_mechanic = Пустая механика +mod_manager/collection_empty_mechanic_desc = Создать контур с нуля: название, описание и моды добавите вручную. +mod_manager/collection_pick_mechanic = Добавить механику +mod_manager/collection_pick_replace = Заменить механику +mod_manager/collection_choose = Добавить +mod_manager/collection_replace = Заменить +mod_manager/collection_remove = Убрать +mod_manager/collection_rename = Переименовать +mod_manager/collection_create = Создать +mod_manager/collection_where = Куда добавить +mod_manager/collection_new_extra = + новая механика «Дополнительно» +mod_manager/collection_extra_name = Дополнительно +mod_manager/collection_extra_note = Добавленные вручную моды. +mod_manager/collection_search_mechanic = Поиск механики... +mod_manager/collection_search_mod = Поиск мода... +mod_manager/collection_problems_none = Проблем нет — сборка согласована. +mod_manager/collection_problem_missing = Блок «{0}» не найден +mod_manager/collection_problem_cycle = Цикл: «{0}» → «{1}» +mod_manager/collection_problem_role = Слот «{0}» занят дважды +mod_manager/collection_problem_require = «{0}»: не выполнено требование «{1}» +mod_manager/collection_show = Показать +mod_manager/collection_hint = Выберите контур или мод. Контуры двигаются за заголовок, тянутся за угол, моды внутри двигаются свободно. Пустое поле схемы перемещается перетаскиванием ЛКМ. +mod_manager/collection_mechanic = механика +mod_manager/collection_group = группа +mod_manager/collection_mods = модов +mod_manager/collection_in_group = В механике +mod_manager/collection_remove_mod = Убрать из механики +mod_manager/collection_turn_on = Включить +mod_manager/collection_turn_off = Выключить +mod_manager/collection_unsaved = ● несохранённые правки + +# ─── Хаб «Моды и коллекции» ─── +mod_manager/hub_tab_mods = Моды +mod_manager/hub_tab_collections = Коллекции +mod_manager/hub_back_to_menu = ← Меню +mod_manager/hub_back_to_gallery = ← К играм +mod_manager/hub_in_one_collection = в {0} коллекции +mod_manager/hub_in_many_collections = в {0} коллекциях + +# Галерея готовых игр +mod_manager/gallery_crumb = Готовые игры +mod_manager/gallery_title = Игры +mod_manager/gallery_hint = готовые наборы модов: одна кнопка — и всё установлено +mod_manager/gallery_search_placeholder = Поиск коллекций... +mod_manager/gallery_new_game = + Собрать свою игру +mod_manager/gallery_new_game_blank = + Собрать свою игру с нуля +mod_manager/gallery_empty_hint = Добавьте в свой мод папку collections/ с JSON-файлами — коллекции появятся здесь. +mod_manager/gallery_edit_scheme = Изменить схему +mod_manager/gallery_ready = Готова к игре +mod_manager/gallery_ready_done = Готова ✓ +mod_manager/gallery_missing_n = Не хватает {0} +mod_manager/gallery_problems_n = Проблемы: {0} +mod_manager/gallery_enable_badge_n = Включить {0} +mod_manager/gallery_install_btn_n = Установить ({0}) +mod_manager/gallery_enable_btn_n = Включить ({0}) +mod_manager/gallery_draft = Черновик +mod_manager/gallery_continue = Продолжить сборку + +# Нижняя панель сборки (редактор схемы) +mod_manager/build_caption = Сборка +mod_manager/build_stat_install = Установить +mod_manager/build_stat_enable = Включить +mod_manager/build_stat_problems = Проблемы +mod_manager/build_hint_problems = Устраните проблемы, чтобы применить коллекцию +mod_manager/build_open_manager = Открыть менеджер модов +mod_manager/collection_crumb_scheme = Схема +mod_manager/collection_find_in_catalog = Найти в каталоге + + +mod_manager/collection_duplicate = Дублировать +mod_manager/collection_revert = Вернуть встроенную +mod_manager/collection_saves = Сохранений: {0} +mod_manager/collection_next_launch = Изменения вступят в силу при следующем запуске игры. +mod_manager/collection_json_apply = Применить +mod_manager/collection_json_invalid = JSON не разобран: {0} +mod_manager/collection_json_id_changed = Id коллекции менять нельзя — для новой игры используйте «Дублировать». +mod_manager/collection_copy_name = {0} (копия) +mod_manager/collection_copy_saves = У исходной игры есть сохранения ({0}). Скопировать их в новую игру? +mod_manager/collection_copy_saves_ok = Скопировать +mod_manager/collection_revert_confirm = Удалить ваши изменения и вернуть встроенную версию игры? Сохранения останутся. +mod_manager/collection_revert_done = Возвращена встроенная версия. +mod_manager/collection_delete = Удалить коллекцию +mod_manager/collection_delete_confirm = Коллекция «{0}» будет удалена. Моды из неё останутся установленными в системе, сохранения ({1}) — на диске. +mod_manager/collection_delete_done = Коллекция удалена. Моды остались в системе. +mod_manager/collection_nested_readonly = Этот блок вложен глубже — откройте его отдельно, чтобы изменить. +mod_manager/collection_forked = Блок «{0}» скопирован для этой игры — другие игры не изменятся. diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..19cd23b --- /dev/null +++ b/manifest.json @@ -0,0 +1,19 @@ +{ + "id": "mod_manager", + "name": "Mod Manager", + "version": "1.0.0", + "author": "ct", + "description": "Nexus-style mod manager: browse the catalog, filter by category and status, install, update and remove mods.", + "category": "tools, ui", + "sources": [ + "src/**/*.cs" + ], + "depends": ["interface>=1"], + "main_menu": [ + { + "id": "mods_hub", + "scene_path": "scenes/mods_hub_screen.tscn", + "button": { "icon": "mod_manager", "locale": "mod_manager/menu_title", "index": 100 } + } + ] +} diff --git a/mod.png b/mod.png new file mode 100644 index 0000000..7ec3767 Binary files /dev/null and b/mod.png differ diff --git a/scenes/components/mod_card.tscn b/scenes/components/mod_card.tscn new file mode 100644 index 0000000..6fd286b --- /dev/null +++ b/scenes/components/mod_card.tscn @@ -0,0 +1,145 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/UI/ModCard.cs" id="1_card"] + +[node name="ModCard" type="PanelContainer"] +custom_minimum_size = Vector2(236, 0) +size_flags_horizontal = 0 +mouse_filter = 0 +script = ExtResource("1_card") + +[node name="VBox" type="VBoxContainer" parent="."] +layout_mode = 2 +theme_override_constants/separation = 0 + +[node name="Cover" type="Control" parent="VBox"] +custom_minimum_size = Vector2(0, 132) +layout_mode = 2 +clip_contents = true +mouse_filter = 2 + +[node name="Placeholder" type="ColorRect" parent="VBox/Cover"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.054902, 0.058824, 0.082353, 1) + +[node name="Image" type="TextureRect" parent="VBox/Cover"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +expand_mode = 1 +stretch_mode = 6 + +[node name="Body" type="MarginContainer" parent="VBox"] +layout_mode = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="Box" type="VBoxContainer" parent="VBox/Body"] +layout_mode = 2 +theme_override_constants/separation = 5 + +[node name="Title" type="Label" parent="VBox/Body/Box"] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 +mouse_filter = 2 +clip_text = true +autowrap_mode = 3 +max_lines_visible = 2 +text_overrun_behavior = 3 + +[node name="Author" type="Label" parent="VBox/Body/Box"] +custom_minimum_size = Vector2(0, 16) +layout_mode = 2 +mouse_filter = 2 +clip_text = true +text_overrun_behavior = 3 +theme_override_font_sizes/font_size = 11 + +[node name="Source" type="Label" parent="VBox/Body/Box"] +custom_minimum_size = Vector2(0, 16) +layout_mode = 2 +mouse_filter = 2 +clip_text = true +text_overrun_behavior = 3 +theme_override_font_sizes/font_size = 11 + +[node name="MetaRow" type="HBoxContainer" parent="VBox/Body/Box"] +custom_minimum_size = Vector2(0, 28) +layout_mode = 2 +theme_override_constants/separation = 6 + +[node name="Status" type="Label" parent="VBox/Body/Box/MetaRow"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 4 +mouse_filter = 2 +clip_text = true +text_overrun_behavior = 3 +theme_override_font_sizes/font_size = 11 +vertical_alignment = 1 + +[node name="VersionHost" type="Control" parent="VBox/Body/Box/MetaRow"] +custom_minimum_size = Vector2(102, 28) +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 +mouse_filter = 2 +clip_contents = true + +[node name="Versions" type="OptionButton" parent="VBox/Body/Box/MetaRow/VersionHost"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/font_size = 11 + +[node name="ActionRow" type="HBoxContainer" parent="VBox/Body/Box"] +custom_minimum_size = Vector2(0, 32) +layout_mode = 2 +theme_override_constants/separation = 6 + +[node name="ActionHost" type="Control" parent="VBox/Body/Box/ActionRow"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 4 +mouse_filter = 2 + +[node name="Action" type="Button" parent="VBox/Body/Box/ActionRow/ActionHost"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +clip_text = true +text_overrun_behavior = 3 + +[node name="EnabledHost" type="Control" parent="VBox/Body/Box/ActionRow"] +custom_minimum_size = Vector2(40, 32) +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 +mouse_filter = 2 +clip_contents = true + +[node name="Enabled" type="CheckButton" parent="VBox/Body/Box/ActionRow/EnabledHost"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/scenes/components/mod_detail_view.tscn b/scenes/components/mod_detail_view.tscn new file mode 100644 index 0000000..a8e990d --- /dev/null +++ b/scenes/components/mod_detail_view.tscn @@ -0,0 +1,180 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/UI/ModDetailView.cs" id="1_detail"] + +[node name="ModDetailView" type="VBoxContainer"] +theme_override_constants/separation = 8 +script = ExtResource("1_detail") + +[node name="Scroll" type="ScrollContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +horizontal_scroll_mode = 0 + +[node name="Content" type="VBoxContainer" parent="Scroll"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/separation = 14 + +[node name="Hero" type="PanelContainer" parent="Scroll/Content"] +layout_mode = 2 + +[node name="HeroMargin" type="MarginContainer" parent="Scroll/Content/Hero"] +layout_mode = 2 +theme_override_constants/margin_left = 14 +theme_override_constants/margin_top = 14 +theme_override_constants/margin_right = 14 +theme_override_constants/margin_bottom = 14 + +[node name="HeroRow" type="HBoxContainer" parent="Scroll/Content/Hero/HeroMargin"] +layout_mode = 2 +theme_override_constants/separation = 16 + +[node name="Cover" type="Control" parent="Scroll/Content/Hero/HeroMargin/HeroRow"] +custom_minimum_size = Vector2(270, 180) +layout_mode = 2 +clip_contents = true +mouse_filter = 2 + +[node name="Placeholder" type="ColorRect" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Cover"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.054902, 0.058824, 0.082353, 1) + +[node name="Image" type="TextureRect" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Cover"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +expand_mode = 1 +stretch_mode = 6 + +[node name="Info" type="VBoxContainer" parent="Scroll/Content/Hero/HeroMargin/HeroRow"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/separation = 6 + +[node name="Back" type="Button" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"] +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="Title" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"] +layout_mode = 2 +autowrap_mode = 3 +theme_override_font_sizes/font_size = 22 + +[node name="Author" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"] +layout_mode = 2 + +[node name="Meta" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"] +layout_mode = 2 + +[node name="VersionRow" type="HBoxContainer" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="Caption" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info/VersionRow"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Versions" type="OptionButton" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info/VersionRow"] +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="Installed" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info/VersionRow"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Size" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info/VersionRow"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="ActionsRow" type="HBoxContainer" parent="Scroll/Content"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="ConflictBox" type="VBoxContainer" parent="Scroll/Content"] +visible = false +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Scroll/Content/ConflictBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="Text" type="Label" parent="Scroll/Content/ConflictBox"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="DescriptionBox" type="VBoxContainer" parent="Scroll/Content"] +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Scroll/Content/DescriptionBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="Text" type="Label" parent="Scroll/Content/DescriptionBox"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="ChangelogBox" type="VBoxContainer" parent="Scroll/Content"] +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Scroll/Content/ChangelogBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="Text" type="Label" parent="Scroll/Content/ChangelogBox"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="DependsBox" type="VBoxContainer" parent="Scroll/Content"] +visible = false +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Scroll/Content/DependsBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="Text" type="Label" parent="Scroll/Content/DependsBox"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="UsedByBox" type="VBoxContainer" parent="Scroll/Content"] +visible = false +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Scroll/Content/UsedByBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="Text" type="Label" parent="Scroll/Content/UsedByBox"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="ConflictsBox" type="VBoxContainer" parent="Scroll/Content"] +visible = false +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="Caption" type="Label" parent="Scroll/Content/ConflictsBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="Text" type="Label" parent="Scroll/Content/ConflictsBox"] +layout_mode = 2 +autowrap_mode = 3 diff --git a/scenes/components/mod_filter_panel.tscn b/scenes/components/mod_filter_panel.tscn new file mode 100644 index 0000000..33265ee --- /dev/null +++ b/scenes/components/mod_filter_panel.tscn @@ -0,0 +1,43 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/UI/ModFilterPanel.cs" id="1_filter"] + +[node name="ModFilterPanel" type="VBoxContainer"] +theme_override_constants/separation = 8 +script = ExtResource("1_filter") + +[node name="Title" type="Label" parent="."] +layout_mode = 2 +theme_override_font_sizes/font_size = 16 + +[node name="Reset" type="Button" parent="."] +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="Sep1" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="StatusCaption" type="Label" parent="."] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="StatusList" type="VBoxContainer" parent="."] +layout_mode = 2 +theme_override_constants/separation = 2 + +[node name="Sep2" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="CategoryCaption" type="Label" parent="."] +layout_mode = 2 +theme_override_font_sizes/font_size = 12 + +[node name="CategoryList" type="VBoxContainer" parent="."] +layout_mode = 2 +theme_override_constants/separation = 2 + +[node name="Sep3" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="GroupToggle" type="CheckButton" parent="."] +layout_mode = 2 diff --git a/scenes/components/mod_grid_group.tscn b/scenes/components/mod_grid_group.tscn new file mode 100644 index 0000000..0dbef99 --- /dev/null +++ b/scenes/components/mod_grid_group.tscn @@ -0,0 +1,16 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/UI/ModGridGroup.cs" id="1_group"] + +[node name="ModGridGroup" type="VBoxContainer"] +theme_override_constants/separation = 8 +script = ExtResource("1_group") + +[node name="Header" type="Label" parent="."] +layout_mode = 2 +theme_override_font_sizes/font_size = 15 + +[node name="Flow" type="HFlowContainer" parent="."] +layout_mode = 2 +theme_override_constants/h_separation = 12 +theme_override_constants/v_separation = 12 diff --git a/scenes/components/mod_grid_view.tscn b/scenes/components/mod_grid_view.tscn new file mode 100644 index 0000000..5150bce --- /dev/null +++ b/scenes/components/mod_grid_view.tscn @@ -0,0 +1,12 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/UI/ModGridView.cs" id="1_grid"] + +[node name="ModGridView" type="ScrollContainer"] +horizontal_scroll_mode = 0 +script = ExtResource("1_grid") + +[node name="Host" type="VBoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/separation = 18 diff --git a/scenes/mod_collections_screen.tscn b/scenes/mod_collections_screen.tscn new file mode 100644 index 0000000..7865a7d --- /dev/null +++ b/scenes/mod_collections_screen.tscn @@ -0,0 +1,198 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/ModCollectionsScreen.cs" id="1_screen"] +[ext_resource type="Script" path="src/UI/CollectionSchemeCanvas.cs" id="2_canvas"] + +[node name="ModCollectionsScreen" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 0 +script = ExtResource("1_screen") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.054902, 0.058824, 0.082353, 1) + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 12 + +[node name="Root" type="VBoxContainer" parent="Margin"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="Header" type="HBoxContainer" parent="Margin/Root"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="Close" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 + +[node name="Title" type="Label" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 +theme_override_font_sizes/font_size = 24 +uppercase = true + +[node name="GameSelect" type="OptionButton" parent="Margin/Root/Header"] +custom_minimum_size = Vector2(220, 0) +layout_mode = 2 +size_flags_vertical = 4 + +[node name="AddMechanic" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="NewGame" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Spacer" type="Control" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_horizontal = 3 +mouse_filter = 2 + +[node name="EdgesToggle" type="CheckBox" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 +button_pressed = true + +[node name="Problems" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Plan" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="ModsCount" type="Label" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Dirty" type="Label" parent="Margin/Root/Header"] +visible = false +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Json" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Reset" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Save" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Refresh" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Crumbs" type="HBoxContainer" parent="Margin/Root"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="Body" type="HSplitContainer" parent="Margin/Root"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="CanvasScroll" type="ScrollContainer" parent="Margin/Root/Body"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +horizontal_scroll_mode = 1 +vertical_scroll_mode = 1 + +[node name="SchemeCanvas" type="Control" parent="Margin/Root/Body/CanvasScroll"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("2_canvas") + +[node name="Details" type="PanelContainer" parent="Margin/Root/Body"] +custom_minimum_size = Vector2(380, 0) +layout_mode = 2 + +[node name="DetailScroll" type="ScrollContainer" parent="Margin/Root/Body/Details"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +horizontal_scroll_mode = 0 + +[node name="Detail" type="VBoxContainer" parent="Margin/Root/Body/Details/DetailScroll"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/separation = 8 + +[node name="Tabs" type="HBoxContainer" parent="Margin/Root/Body/Details/DetailScroll/Detail"] +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="TabInspector" type="Button" parent="Margin/Root/Body/Details/DetailScroll/Detail/Tabs"] +layout_mode = 2 +toggle_mode = true +button_pressed = true + +[node name="TabProblems" type="Button" parent="Margin/Root/Body/Details/DetailScroll/Detail/Tabs"] +layout_mode = 2 +toggle_mode = true + +[node name="TabPlan" type="Button" parent="Margin/Root/Body/Details/DetailScroll/Detail/Tabs"] +layout_mode = 2 +toggle_mode = true + +[node name="DetailTitle" type="Label" parent="Margin/Root/Body/Details/DetailScroll/Detail"] +layout_mode = 2 +theme_override_font_sizes/font_size = 20 +autowrap_mode = 3 + +[node name="DetailMeta" type="Label" parent="Margin/Root/Body/Details/DetailScroll/Detail"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="DetailDescription" type="Label" parent="Margin/Root/Body/Details/DetailScroll/Detail"] +layout_mode = 2 +autowrap_mode = 3 + +[node name="DetailExtra" type="VBoxContainer" parent="Margin/Root/Body/Details/DetailScroll/Detail"] +layout_mode = 2 +theme_override_constants/separation = 6 + +[node name="Apply" type="Button" parent="Margin/Root/Body/Details/DetailScroll/Detail"] +layout_mode = 2 + +[node name="BuildBar" type="PanelContainer" parent="Margin/Root"] +layout_mode = 2 + +[node name="BarRow" type="HBoxContainer" parent="Margin/Root/BuildBar"] +layout_mode = 2 +theme_override_constants/separation = 12 + +[node name="Banner" type="PanelContainer" parent="Margin/Root"] +visible = false +layout_mode = 2 + +[node name="BannerLabel" type="Label" parent="Margin/Root/Banner"] +layout_mode = 2 +size_flags_horizontal = 3 +horizontal_alignment = 1 diff --git a/scenes/mod_manager_screen.tscn b/scenes/mod_manager_screen.tscn new file mode 100644 index 0000000..0664cb2 --- /dev/null +++ b/scenes/mod_manager_screen.tscn @@ -0,0 +1,127 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/ModManagerScreen.cs" id="1_screen"] +[ext_resource type="PackedScene" path="scenes/components/mod_filter_panel.tscn" id="2_filter"] +[ext_resource type="PackedScene" path="scenes/components/mod_grid_view.tscn" id="3_grid"] +[ext_resource type="PackedScene" path="scenes/components/mod_detail_view.tscn" id="4_detail"] + +[node name="ModManagerScreen" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 0 +script = ExtResource("1_screen") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.054902, 0.058824, 0.082353, 1) + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 12 + +[node name="Root" type="VBoxContainer" parent="Margin"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="Header" type="HBoxContainer" parent="Margin/Root"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="Close" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 + +[node name="Title" type="Label" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 +theme_override_font_sizes/font_size = 24 +theme_override_colors/font_color = Color(0.956863, 0.941176, 0.905882, 1) +uppercase = true + +[node name="Spacer" type="Control" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Search" type="LineEdit" parent="Margin/Root/Header"] +custom_minimum_size = Vector2(220, 0) +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Sort" type="OptionButton" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Refresh" type="Button" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Result" type="Label" parent="Margin/Root/Header"] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Body" type="HBoxContainer" parent="Margin/Root"] +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/separation = 12 + +[node name="Sidebar" type="PanelContainer" parent="Margin/Root/Body"] +custom_minimum_size = Vector2(260, 0) +layout_mode = 2 + +[node name="SidebarScroll" type="ScrollContainer" parent="Margin/Root/Body/Sidebar"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +horizontal_scroll_mode = 0 + +[node name="FilterPanel" parent="Margin/Root/Body/Sidebar/SidebarScroll" instance=ExtResource("2_filter")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Content" type="Control" parent="Margin/Root/Body"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Grid" parent="Margin/Root/Body/Content" instance=ExtResource("3_grid")] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Detail" parent="Margin/Root/Body/Content" instance=ExtResource("4_detail")] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Banner" type="PanelContainer" parent="Margin/Root"] +visible = false +layout_mode = 2 + +[node name="BannerLabel" type="Label" parent="Margin/Root/Banner"] +layout_mode = 2 +size_flags_horizontal = 3 +horizontal_alignment = 1 diff --git a/scenes/mods_hub_screen.tscn b/scenes/mods_hub_screen.tscn new file mode 100644 index 0000000..aecf7a4 --- /dev/null +++ b/scenes/mods_hub_screen.tscn @@ -0,0 +1,39 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="src/ModHubScreen.cs" id="1_hub"] + +[node name="ModHubScreen" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 0 +script = ExtResource("1_hub") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0.054902, 0.058824, 0.082353, 1) + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 12 + +[node name="Root" type="VBoxContainer" parent="Margin"] +layout_mode = 2 +theme_override_constants/separation = 10 diff --git a/src/ModCollectionsScreen.cs b/src/ModCollectionsScreen.cs new file mode 100644 index 0000000..752dd5f --- /dev/null +++ b/src/ModCollectionsScreen.cs @@ -0,0 +1,1894 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using Cthangover.Core.Mods; +using Cthangover.Core.Settings; +using Cthangover.Core.UI; +using Cthangover.Core.UI.Theming; +using Cthangover.Core.Utils; +using Godot; + +using Cthangover.Mods.Interface.Base.Lists; +using Cthangover.Mods.Interface.Theming; +namespace Mods.ModManager +{ + /// + /// Fullscreen scheme editor opened from the main menu: the whole game on one + /// canvas exactly like the approved mockup. The header picks the game and + /// creates new games/mechanics, the canvas shows movable and resizable + /// mechanic contours with freely placed mod chips and dependency lines, and + /// the inspector edits the selected group or mod. + /// + /// All heavy lifting stays in the core: + /// merges documents, expands includes + /// into groups and problems, decides what to + /// download and enable, and persists the + /// arrangement. Edits mutate drafts in _overrides — never the loaded + /// documents — and only "Сохранить" writes them back through + /// , so the player can explore + /// layouts without committing anything. + /// + public partial class ModCollectionsScreen : ModWidget + { + private const string RoleExtra = "extra"; + + private Button _close; + private Button _refresh; + private Button _addMechanic; + private Button _newGame; + private Button _apply; + private OptionButton _gameSelect; + private CheckBox _edgesToggle; + private Button _pillProblems; + private Button _pillPlan; + private Label _modsCount; + private Label _dirty; + private Button _json; + private Button _reset; + private Button _save; + private Label _bannerLabel; + private Label _detailTitle; + private Label _detailMeta; + private Label _detailDescription; + private VBoxContainer _detailExtra; + private PanelContainer _bannerPanel; + private CollectionSchemeCanvas _canvas; + private Button _tabInspector; + private Button _tabProblems; + private Button _tabPlan; + private HBoxContainer _crumbs; + private Button _crumbCollections; + private Label _buildName; + private Label _buildInstall; + private Label _buildEnable; + private Label _buildProblems; + private Label _buildHint; + private Button _buildManager; + private Button _buildApply; + + private List _collections = new(); + private readonly Dictionary _overrides = new(StringComparer.OrdinalIgnoreCase); + private string _currentId; + private ModCollectionGraph _graph; + private ModCollectionPlan _plan; + private ModCollectionLayout _layout = new(); + private string _selectedGroupKey; + private string _selectedModId; + private string _tab = "inspector"; + + /// Mods installed during this session; the registry only sees them after a restart. + private HashSet _sessionInstalled = new(StringComparer.OrdinalIgnoreCase); + private bool _installing; + private bool _restartRequired; + private string _statusMessage; + private Button _duplicate; + private Button _revert; + private Button _delete; + private Label _savesInfo; + + /// Drafts created by "Duplicate", mapped to the game they were copied from (offer to copy its saves). + private readonly Dictionary _duplicatedFrom = new(StringComparer.OrdinalIgnoreCase); + + /// + /// When true the editor runs as the second level of the collections + /// tab: the close/title/new-game/catalog-refresh header controls are + /// hidden (the hosting owns navigation) and + /// the game selector moves into the breadcrumb row. Editing, saving + /// and applying behaviour are unchanged. + /// + public bool Embedded { get; set; } + + /// Raised when the breadcrumbs ask to go back to the games gallery. + public event Action GalleryRequested; + + /// Raised when a "not found" problem asks to search the mod catalog; the argument is the missing id. + public event Action OpenManagerRequested; + + /// Raised after every rebuild so the hosting hub can refresh its header. + public event Action ViewChanged; + + /// Localized, '@key'-resolved title of the collection being edited; null when nothing is selected. + public string CurrentCollectionTitle + { + get + { + var collection = EffectiveCollection(_currentId); + if (collection == null) + return null; + + var raw = collection.GetLocalizedName(TranslationServer.GetLocale()); + return CollectionText.Resolve(raw); + } + } + + /// Shares the hub-wide set of mods installed this session so gallery and editor stay consistent. + public void SetSessionInstalled(HashSet sessionInstalled) + => _sessionInstalled = sessionInstalled ?? new HashSet(StringComparer.OrdinalIgnoreCase); + + /// + /// Opens the scheme editor on the given collection id, falling back to + /// the first available game when the id is null or unknown. Selection + /// is cleared — the same fresh view a game-switch produces. + /// + public void OpenCollection(string collectionId) + { + _currentId = collectionId; + _selectedGroupKey = null; + _selectedModId = null; + // The gallery re-reads the store on every refresh; re-read it here + // too, so a collection that appeared since this editor was built + // opens instead of falling back to the first game. + ReloadCollections(); + } + + /// Creates a fresh player game draft and opens it — the gallery's "build your own game" action. + public void OpenNewGame() => OnNewGamePressed(); + + protected override void Construct() + { + MouseFilter = MouseFilterEnum.Stop; + CthangoverTheme.Apply(this); + + BindSceneNodes(); + SubscribeEvents(); + + CatalogService.LoadCache(); + ReloadCollections(); + StartCatalogRefreshIfNeeded(); + } + + protected override void Destruct() + { + UnsubscribeEvents(); + } + + private void BindSceneNodes() + { + _close = GetNode