Ядро авторинга — построение второй поверхности авторинга
Продвинутый уровень. Для авторов ассетов/инструментов, которые хотят построить собственный интерфейс авторинга (например, холст с графом узлов) поверх движка SheetForge. Командам, использующим Data Studio, эта страница не нужна.
Окно авторинга — это не движок. Data Studio — и работающее рядом с ним веб-приложение — являются потребителями независимого от окна ядра авторинга.
Всё, что они делают, работает через публичные типы, которые третья поверхность может использовать точно так же: подготовка изменений, проверка, оркестрация отражения, границы undo, повторный импорт. Уже существуют две таких поверхности — это практическое доказательство того, что этот шов реален, а не является умозрительным.
Прежде чем строить целую поверхность, проверьте, не покрывает ли эту потребность уже существующая точка расширения. Плагин может добавить команды, панели, значки и виджеты ячеек в поставляемое окно, вообще не владея собственным окном, — описав их как данные, так что они отрисовываются и в редакторе, и в браузере — см. Создание плагинов §4.16. Эта страница — для случая, когда вам нужен собственный холст.
Сборка-симулятор потребителя без IVT (SheetForge.Tests.Consumer, без доступа InternalsVisibleTo в Core или Editor) реализует виртуальную поверхность авторинга от начала до конца, используя только публичный API. Если бы ей понадобился internal-член, сборка не скомпилировалась бы (CS0122). Поэтому она служит исполняемой спецификацией поверхности, описанной ниже.
Движок из трёх объектов
┌─────────────────────┐ ┌──────────────────────────┐ ┌───────────────┐
│ AuthoringSession │────▶│ AuthoringDispatcher │────▶│ BaselineStore │
│ (staging state) │ │ .Reflect() │ │ (round-trip │
│ │ │ (the full cycle) │ │ snapshots) │
└─────────────────────┘ └────────────┬─────────────┘ └───────────────┘
│ binds
┌────────────▼─────────────┐
│ AuthoringDispatchCallbacks│
│ (view concerns — YOUR UI) │
└──────────────────────────┘AuthoringSession — состояние подготовленных изменений
Обычный класс [Serializable] (намеренно не ScriptableObject). Храните его в поле [SerializeField] вашего EditorWindow, и вы бесплатно получаете нативные для Unity снимки Undo и переживание перезагрузки домена — тот же механизм, что стоит за Ctrl+Z в поставляемом окне.
Он владеет всем подготовленным состоянием:
- правками ячеек (
Edits), новыми строками (NewRows), операциями структуры (StructOps); - изменениями порядка по вкладкам (
Reorders), переименованиями вкладок (TabRenames); - якорями baseline, изолированными правками.
Поверх этого состояния он предоставляет API для изменения/запроса:
SetStaged(...)— подготовить правку ячейки. Правки несут логический адрес (вкладка · RecordId · поле); физический порядковый номер строки — это производный кеш, заново разрешаемый непосредственно перед отражением.ResolveBaselineEdits(provider)— перепривязать все правки к текущему baseline. Разрешимые правки продолжают действовать. Три неразрешимых случая (внешнее переименование / внешнее удаление / конфликт ключа) перемещаются вIsolatedEdits: исключаются из отражения, помечаются значком, никогда не отбрасываются молча и никогда не блокируют сессию.- Поверхность чтения baseline:
TabNames,TryGetBaselineTable(tab, out SheetTable)— типизированный доступ к схеме (TypeToken,@desc,@overlap) без необходимости самостоятельно трогать парсер. EffectiveStructOps()/PendingStructCount()— составленное, каноническое представление операций структуры.- Хуки перепривязки (
RemapFieldName/RemapRecordId/RemapTab) поддерживают согласованность подготовленного состояния при переименованиях. LastProjectionResultкеширует последнюю проекцию.
AuthoringDispatcher — оркестрация отражения
var dispatcher = new AuthoringDispatcher(session, callbacks, baselineStore);
dispatcher.Reflect(); // the entire cycle, one callReflect() выполняет весь цикл по порядку:
- предварительную проверку
- отражение для конкретного источника — точечная запись для локального, безопасная перезапись для Google, ваша собственная цель для пользовательских провайдеров
- очистку сохранённого состояния
- границу подтверждения
ClearUndo - автоматический повторный импорт с отчётом
Также:
BuildProjectionResult()— проекция текущего подготовленного состояния без побочных эффектов в видеImportResult(проверка «как если бы уже отражено»). Используйте её для живых значков ошибок.- Публичные
Session/Callbacks/Baselines— пользовательские провайдеры источников используют их, чтобы собрать свои цели отражения.
AuthoringDispatchCallbacks — контракт вашего интерфейса
Набор из 13 общих делегатов, которые диспетчер вызывает для каждой заботы, связанной с представлением: ResolveSettings, диалоги подтверждения (ConfirmKeyRenames, ConfirmTabRenames, …), RenderReport (Action<ImportReport> — допускает null, это лишь наблюдение), PushApprover, TriggerReimport, ClearUndo, Rebuild и так далее.
14 диалоговых делегатов, специфичных для встроенных источников Local/Google, вынесены в отдельный опциональный набор BuiltInSourceDialogs — внешней поверхности или провайдеру никогда не нужно их привязывать.
Поставляемое окно привязывает реализации по умолчанию, показывающие диалоги; ваш холст привязывает свои собственные (либо пустые операции). Движок никогда не рисует интерфейс сам.
Материал для графа
Для проекции вида «узел = запись, ребро = ссылка ∪ объявление»:
ReferenceScanner(Core) — единственный источник истины для перечисления вхождений ссылок по всем таблицам: скаляры, элементы списков, явные значения по умолчанию. То же самое перечисление использует валидатор ссылок, поэтому ваш граф и проверка согласованы по построению.Scan(tables)/ScanTable/ScanField/IsReferenceField.IEdgeContributor/EdgeSpec/EdgeContributorRegistry(Core) — доменные плагины объявляют рёбра, которые сканер не видит (внутри значений пользовательских типов, связей через столбецtype, рёбер записи с записью полезной нагрузки). Собирайте их черезPluginRegistry.BuildEdgeContributorsредактора.ReferenceIndex/RecordEdge(Core) — собранный снимок, на котором работает собственный холст Data Studio:Build(...)один раз объединяет отсканированные ссылки с рёбрами от поставщиков, после чегоOutEdges/InEdges/InCountотвечают за O(1) на запись. Полный список членов — в Справочнике по API.IRecordCanvasAugmenter/CanvasAugmentBuilder(Core) — контракт переопределения для вкладки, если вы хотите, чтобы доменные пакеты расширяли ваш холст так же, как они расширяют холст Studio (виртуальные узлы, дополнительные рёбра, подсказки по слою и отображению).ProjectionErrorMapper(Editor, чистый) — сопоставляет физическую координату ошибки проекции (вкладка/строка/поле) логическому адресу (вкладка/RecordId/поле), чтобы вы могли привязывать значки ошибок к узлам, а не к номерам строк.
Вспомогательные элементы
| Тип | Для чего использует ваша поверхность |
|---|---|
ImportEvents | Две шины, обе — публичные контракты. ImportCompleted (ImportCompletedArgs: Tabs · BakeFolder) срабатывает, когда автоцепочка прошла весь путь до запекания, так что подписчик может читать запечённые ассеты. BaselineUpdated (BaselineUpdatedArgs: Tabs · Quarantined) срабатывает всякий раз, когда снимок таблицы был сохранён — включая прогон, провалившийся проверку, — на это подписывается поверхность, которая хочет показать проваленные таблицы и дать людям их исправить. Подпишитесь на обе, если ваше представление показывает и таблицы, и запечённые значения; отписывайтесь симметрично в OnDisable. |
IPipelineObserver | Если знать об этом должен плагин, а не окно, — это более лёгкий путь: зарегистрируйте наблюдателя и получайте неизменяемый PipelineRunView в конце каждого цикла импорта, вообще без зависимости от редактора — это работает и в браузерном хосте. См. Создание плагинов §4.17. |
RecordIdMinter | Предлагает id для новых записей — определение префикса + безопасная от коллизий уникализация. API для подсказок, намеренно не автонумерация. |
EphemeralSoApply | Временно предпросматривает подготовленные значения поверх запечённых SO (повторный импорт восстанавливает исходное). Применяет вычислимое подмножество; возвращает причины пропуска для столбцов в ожидании и ошибок разбора. Ничто в поставляемом интерфейсе больше не использует его, так что поверхность, которой нужен этот предпросмотр, сама владеет кнопкой для него. |
KeyRenamePlanner | Планирует переименования ключей (3 этапа: извлечение / распространение / точечное применение) — так же, как это делает поставляемое окно. Подтверждения переименования вкладок проходят через публичный колбэк ConfirmTabRenames. |
SourceProviderRegistry | Разрешает активный провайдер источника точно так же, как это делает интерфейс настроек. |
Базовые правила, которые обеспечивает ядро (и которые вы наследуете)
- Таблица остаётся канонической — ваша поверхность готовит изменения и отражает их; она никогда не пишет в SO.
- Сначала проверка, потом отражение —
Reflect()ничего не записывает, если предварительная проверка не проходит. - Никаких молчаливых потерь — неразрешимые правки изолируются с указанием причины; подтверждения проходят через ваши колбэки.
- Undo интегрируется нативно — храните сессию в сериализуемом поле и регистрируйте снимки undo на своём окне;
ClearUndoотмечает границу отражения. - Независимость от домена — ядро не содержит ни одного домен-специфичного термина (это проверяется защитными тестами). Ваш домен подключается через контракты плагинов, а не через правки ядра.
Похожие страницы
- Справочник по API — сигнатуры всего, что упомянуто здесь
- Создание плагинов — контракты, которые ваш домен использует наряду с ядром
- Data Studio — поведение, которое ваша поверхность повторяет или заменяет