merge: asset-deletion line into master (16 spec suites, 169 cases)

This commit is contained in:
2026-09-12 14:50:27 +07:00
8 changed files with 1736 additions and 2 deletions
+48 -2
View File
@@ -245,12 +245,58 @@ BOM обязателен: без него Excel ломает кириллицу.
---
## Удаление отмеченных ассетов
Кнопка **Delete ticked assets…** внизу панели, рядом с выгрузкой. Работает по тому же набору галочек.
Удаление — единственная операция инструмента, которая уничтожает работу безвозвратно, поэтому проходит **через два окна**.
### Окно 1 — наше
Показывает весь отмеченный набор построчно: имя, тип, путь, **сколько ассетов снаружи набора ещё ссылается** на строку (в тултипе — их имена), и статус.
- Ссылающиеся ассеты, которые сами удаляются вместе с целью, **в счётчик не попадают**. Иначе удаление блюпринта вместе с его единственным мешем выглядело бы опасным, хотя оно чистое.
- Референсеры запрашиваются тем же `NoRequirements`-запросом, что и аудит: hard-only потерял бы каждую soft-ссылку, а soft-ссылка ломается точно так же — просто в рантайме, а не при загрузке.
- Файл, помеченный **read-only на диске**, отмечается заранее. Под VCS, которая держит невытянутые файлы нередактируемыми, без этой пометки удаление падало бы по одному файлу в середине пачки.
- Кнопка удаления неактивна, пока не поставлена галочка «I understand these files will be removed from the project».
### Окно 2 — родное от UE
После подтверждения набор уходит в `ObjectTools::DeleteAssets(..., bShowConfirmation=true)`, и открывается **штатное окно Delete Assets** движка — со списком ссылок, `Force Delete` и `Replace References`.
Оно не имитировано, а вызвано: своя реализация замены ссылок означала бы свою реализацию `FAssetDeleteModel`, ошибки которой всплыли бы на чужом проекте.
### Что удалять запрещено
Отказы показываются в списке с причиной, строку нельзя отметить — молча выкинуть её из набора было бы хуже, чем отказать вслух.
| Отказ | Почему |
|---|---|
| **Уровень** (`.umap`) | Уровень — это единица, относительно которой инструмент меряет использование. Удалив его, обесцениваешь каждую другую строку результата. Плюс движок сам отказывается удалять открытую карту, и итог зависел бы от того, какая карта сейчас загружена |
| **OFPA-пакет** (`__ExternalActors__`, `__ExternalObjects__`) | Это не ассет, а размещённый на карте актор. Удалять его мимо level-редактора — значит править карту за его спиной, без его undo |
| **`/Engine`, `/Script`, `/Temp`** | Не контент этого проекта |
| **Уже отсутствует** | В реестре нет ассета под этим именем — удалять нечего |
### ⚠️ Набор для удаления не расширяется зависимостями
В отличие от выгрузки. Выгрузка тянет зависимости, чтобы меш приехал с материалами; удаление, расширенное так же, снесло бы контент, который никто не отмечал, — одна общая текстура утащила бы половину проекта.
Удаляется ровно отмеченное и никогда больше.
### ⚠️ После удаления результат помечается устаревшим
Удалённые строки убираются из таблицы, но всё, что на них ссылалось, сохраняет прежние счётчики ссылок, а ассет, бывший `UsedByAssetsOnly` через удалённый блюпринт, теперь имеет другой вердикт. Панель говорит об этом прямо и просит перезапустить аудит, а не выдаёт старые числа за свежий замер.
И главное — то же, что и везде в этом инструменте: **`Unreferenced` не означает «не используется»**. Реестр не видит путей, собранных строками, содержимого DataTable и событий FMOD. Окно удаления повторяет это предупреждение прямо в тексте.
---
## Архитектура
```
AssetUsageAuditCore UncookedOnly — весь анализ, ноль UI
AssetUsageAuditEditor Editor — Slate-панель, настройки, команды
AssetUsageAuditTests UncookedOnly — 15 spec-сьютов, 159 кейсов
AssetUsageAuditTests UncookedOnly — 16 spec-сьютов, 169 кейсов
```
**Инвариант Core:** не линковать `UnrealEd`, `AssetTools`, `ToolMenus`, `Slate`, `SlateCore`, `EditorSubsystem`. `AssetTools` editor-only транзитивно через `UnrealEd`.
@@ -340,7 +386,7 @@ WP_Example → BP_GameMode → PDA_MenuConfig → L_Other → …
-unattended -nopause -nosplash -stdout -abslog="<abs path>"
```
**159 кейсов в 15 spec-сьютах**, префикс `AssetUsageAudit.*`.
**169 кейсов в 16 spec-сьютах**, префикс `AssetUsageAudit.*`.
Три набора работают на **настоящем контенте проекта**, а не на выдуманных именах: `ExporterLive` (копирование, коллизии, раскрытие OFPA), `ExchangeExport` (конвертация) и `GraphFidelity` (сверка графа с реестром). Субъект они ищут через Asset Registry и берут **самый маленький** OFPA-уровень — на `WP_Example` тест копировал бы гигабайты. Если контент не найден, тест пишет предупреждение и не падает, поэтому в логе стоит смотреть на предупреждения: их отсутствие означает, что тесты реально работали с контентом.