Перейти к содержимому
SheetForge

Справочник по API — публичная поверхность

Эта страница перечисляет каждый публичный тип в сборках продукта. Всё, что здесь не перечислено, является internal по замыслу — публичная поверхность намеренно узкая.

  • Core (SheetForge.Core + SheetForge.Core.Tooling): 137 публичных типов (Core: 131, Core.Tooling: 6). Core.Tooling — это редакторская половина, содержащая сервисы времени импорта, такие как формирование отчётов и планирование отправки, — она не поставляется в билды игрока.
  • Editor: 53 публичных типа верхнего уровня плюс их публичные вложенные типы.
  • Runtime: 7 типов, плюс сгенерированные результаты.

Это именно та поверхность, против которой компилируются тесты-симуляторы потребителя (без InternalsVisibleTo).

Контракт обнаружения (не тип): сторонний ассет также может обнаружить, что SheetForge установлен, во время компиляции через символ scripting-define SHEETFORGE, который сборка Editor регистрирует самостоятельно. Это define, а не публичный тип, поэтому он не перечислен в таблицах ниже — см. Создание плагинов ▸ Обнаружение SheetForge из другого ассета. (Отдельно от SHEETFORGE_ADDRESSABLES — внутреннего version-define, который лишь отмечает, присутствует ли пакет Addressables.)

Соглашения: сигнатуры сокращены ( = см. XML-документацию в исходном коде); «чистый» означает отсутствие UnityEngine / отсутствие ввода-вывода.


Сборка Core (SheetForge.Core) — чистый C#

Нет UnityEngine, нет ввода-вывода, нет сети, нет знаний о домене. Обеспечивается компилятором: Core ни на что не ссылается.

Контракты регистрации плагинов (SheetForge.Core.Plugins)

ТипВидРоль и ключевые члены
ISheetForgePluginинтерфейсБазовый контракт доменного плагина. string Name · RegisterEnums(EnumRegistry) · RegisterCellParsers(CellParserRegistry)
ISheetForgeValidatorPluginинтерфейсОпциональное дополнение для правил проверки. RegisterValidators(DomainValidatorRegistry)
ISheetForgeEdgePluginинтерфейсОпциональное дополнение для объявлений рёбер. RegisterEdgeContributors(EdgeContributorRegistry)
ISheetForgeMarkerPluginинтерфейсОпциональное дополнение для пользовательских структурных маркеров. RegisterStructuralMarkers(MarkerRegistry)
ISheetForgeTemplatePluginинтерфейсОпциональное дополнение для шаблонов «Создать лист». RegisterTemplates(TemplateRegistry)
ISheetForgeGraphPluginинтерфейсОпциональное дополнение, регистрирующее переопределения холста Data Studio для вкладки. RegisterGraphShapes(GraphShapeRegistry)
ISheetForgeCodeRegistryPluginинтерфейсОпциональное дополнение для целей ссылок, которыми владеет код (заблокированные виртуальные вкладки). RegisterCodeRegistries(CodeRegistryCatalog)
ISheetForgeThemePluginинтерфейсОпциональное дополнение для цветовых пресетов окон. RegisterThemes(ThemeRegistry)
ISheetForgeStudioPluginинтерфейсОпциональное дополнение для декларативных поверхностей авторинга (действия, панели, значки столбцов, подсказки редактора ячеек). RegisterStudioUi(StudioUiRegistry). Живёт в Core, а не в Editor, поэтому одна регистрация отрисовывается и в редакторе на UIToolkit, и в браузере
ISheetForgeStringsPluginинтерфейсОпциональное дополнение, регистрирующее собственные строки интерфейса пакета для каждого языка. RegisterStrings(StringOverlayRegistry). Заменяет собой выведенную из употребления пару ISheetForgeLocPlugin / PluginLocRegistry на стороне Editor, которая могла достучаться только до редактора
ISheetForgePipelinePluginинтерфейсОпциональное дополнение, регистрирующее наблюдателей конвейера. RegisterPipelineObservers(PipelineObserverRegistry)

Композиция и совместимость (SheetForge.Core.Plugins)

Обнаружение зависит от хоста — TypeCache Unity в редакторе, сканирование загруженной сборки в браузере. Всё, что происходит после (создание экземпляров, порядок, изоляция и шлюз совместимости), — это одна общая функция Core, именно она не даёт двум хостам расходиться слот за слотом.

ТипВидРоль и ключевые члены
PluginCompositionстатический классЕдиный путь сборки. Один экземпляр на тип, приводимый к каждому контракту, который он реализует. Два члена и разделение диагностики — под таблицей
PluginSetsealed-классСобранный результат — двенадцать слотов: Enums · Parsers · Validators · EdgeContributors · Markers · Templates · GraphShapes · CodeRegistries · Themes · Strings · StudioUi · PipelineObservers. Новый слот достигает обоих хостов через добавление сюда
SheetForgePluginCompatAttributesealed-атрибут (сборки)[assembly: SheetForgePluginCompat(SheetForgePluginFormat.Current, MinHostVersion = "…", PluginVersion = "…")]. int FormatVersion · string MinHostVersion (числовое сравнение через точку; null/пусто = требования нет) · string PluginVersion (только для отображения, никогда не сравнивается). Читается без создания экземпляра чего-либо и оценивается по сборке: отклонённая сборка теряет каждую регистрацию, а не загружается наполовину. Отсутствие = поколение Minimum, требований к хосту нет
SheetForgePluginFormatстатический классКонстанты поколения: const int Current · const int Minimum. Меняется, только если сам формат плагина заменяется — чисто аддитивный рост оставляет число на месте

PluginComposition — два члена:

  • IReadOnlyList<Type> ContractTypes — фильтр обнаружения. Его порядок фиксирован, поскольку именно он определяет порядок появления диагностики.
  • PluginSet Compose(IReadOnlyList<Type> candidateTypes, string hostVersion, ErrorCollector errors, ICollection<string> failures, Func<string,bool> isProductKey = null) — сам вызов сборки.

Два вида проблем держатся раздельно. Конфликты регистрации и отказы по совместимости становятся структурированной диагностикой в errors; ошибки реализации — сбой конструирования, бросающий исключение колбэк — становятся строками на английском в failures, а передача туда null их отбрасывает.

Завершающий предикат isProductKey — это то, как правило строкового оверлея «плагин не может перезаписать ключ продукта» обеспечивается без того, чтобы Core вообще видел языковые таблицы: правило живёт здесь, хост поставляет только материал. Опустите предикат, и пропускается только это одно правило.

Реестры (SheetForge.Core.Model / .Validation / .Edges)

ТипРоль и ключевые члены
EnumRegistryИмя enum → тип CLR (материал для генерации кода). Register<TEnum>() · Register(name, memberNames) · TryGetMembers · TryGetClrTypeName · TryGetClrAssemblyName · RegisteredEnumNames. Три дополнительных члена описаны под таблицей
CellParserRegistryИмя типа → парсер ячейки (open-closed). Повторная регистрация бросает исключение. Register(ICellValueParser) · TryGet · TryGetCustomRenderer · RegisteredTypeNames · RegisterWrapper(ICellWrapperType) · TryGetWrapper · RegisteredWrapperNames (wrapper-типы)
DomainValidatorRegistryСписок валидаторов только для добавления, порядок сохраняется. Register(IDomainValidator) · Validators
EdgeContributorRegistryСписок поставщиков только для добавления, порядок сохраняется. Register(IEdgeContributor) · Contributors
MarkerRegistryИмя маркера (без @) → пользовательский структурный маркер. Конфликт со встроенным маркером (SheetSyntax.ReservedMarkers@name/@type/@desc/@overlap/@style/@enum/@loc) / дубликат / недопустимый идентификатор бросает исключение. Register(IStructuralMarkerDefinition) · TryGet · IsEmpty · RegisteredMarkerNames · AppendMarkerTokens
TemplateRegistryКлюч шаблона «Создать лист» → шаблон. Пустой/дублирующийся ключ, пустое отображаемое имя, ноль вкладок, пустой TSV вкладки бросают исключение. Register(DataTemplate) · TryGet · Templates · IsEmpty

EnumRegistry — три члена подробно:

  • EnumRegistry(EnumRegistry parent) — дочерний реестр, который читает через родительский и регистрирует только в себе. Родитель хранит зарегистрированные плагином CLR-enum на всю перезагрузку домена, дочерний — определённые в таблице для этого импорта, поэтому импорт никогда не изменяет общий кеш. Регистрация имени, которым уже владеет родитель, бросает исключение, а не затеняет его.
  • Contains(name) — сначала свой, затем родительский, Ordinal.
  • SetClrTypeName(name, fullTypeName) — заполняет имя CLR после регистрации только по строке. Имя сборки остаётся пустым, поскольку тип ещё не существует.

Шаблоны «Создать лист» (SheetForge.Core.Model)

ТипРоль и ключевые члены
DataTemplateЗарегистрированный плагином шаблон: string Key (идентичность в реестре) · string DisplayName (текст, которым владеет плагин) · IReadOnlyList<DataTemplateTab> Tabs (одна или больше)
DataTemplateTabОдна вкладка шаблона: string TabName · string Tsv (полный нормализованный TSV — строки маркеров плюс примерные данные)

Пользовательские типы ячеек (SheetForge.Core.Model)

ТипРоль и ключевые члены
ICellValueParserРазбирает одну скалярную ячейку. Неудача = добавить в context.Errors + вернуть false (никогда не бросать исключение). string TypeName · bool TryParse(CellParseContext, string, out object)
ICustomCellTypeНеобязательный помощник для генерации кода/round-trip. Type ValueType · bool TryRender(object, out string text, out string reason)
IReferencingCellTypeОпциональная возможность, которую может дополнительно реализовать зарегистрированный ICellValueParser, чтобы ключ, зарытый в его собственной нотации, получил полноценную обработку как RecordId@Tab — целостность + подсказки, распространение переименования ключа с сохранением полезной нагрузки, рёбра и порты графа, пикер , обнаружение сирот, правила экспортируемых выпадающих списков. Обнаруживается через приведение типа зарегистрированного парсера (отдельной регистрации нет). bool TryGetTokenKey(elementText, out key) · string MakeToken(key) · bool TryRetargetToken(elementText, newKey, out newText) · bool TryRemoveToken(elementText, key, out newText) (пустой результат = элемент исчезает) · bool TryRewriteKeys(elementText, IReadOnlyDictionary<string,string> renames, out newText). Один вызов = один элемент (вся ячейка либо один элемент, разделённый ;), поэтому полезная нагрузка не может содержать ;; @target должен называть настоящую вкладку таблицы (иначе UnknownTargetTab). Никогда не бросает исключение — false/null означает «не удалось интерпретировать», а перезаписи сохраняют остаток
IRefBearingValueПоловина вышеописанного на стороне значения, реализуемая разобранным значением: IEnumerable<string> ReferencedKeys (порядок объявления = порядок диагностики и бюджета подсказок; null/пустые записи пропускаются). Сканер читает это; текстовые хуки выше переписывают ячейку. Нужны оба — разобранное значение не может восстановить нотацию автора, а текст нельзя проверить, не прочитав его
ICellWrapperTypeОбобщённая форма значения-wrapper'а MyWrapper<T> (например, Pair<int> = 1~2) — wrapper владеет внешним синтаксисом, а Core рекурсивно разбирает внутренний тип. string Name · bool TrySplit(string, out IReadOnlyList<string> pieces, out string reason) · string JoinCanonical(IReadOnlyList<string>) · Type OpenClrType · object Assemble(IReadOnlyList<object>, Type closed) · bool TryDisassemble(object, out IReadOnlyList<object>, out string reason)
WrapperValueРазобранный IR ячейки-wrapper'а — несёт стратегию wrapper'а + предоставляет доступ к внутренним CellValue (поэтому ссылки внутри проходят через проверку, переименование ключа/вкладки и экспорт). ICellWrapperType Wrapper · IReadOnlyList<CellValue> Inner
IStructuralMarkerDefinitionПользовательская строка @marker (значения по столбцам, проверяемые по отдельности — обобщение @overlap). string MarkerName (без @) · string Description · void ValidateCell(MarkerCellContext)
MarkerCellContextОдин вызов проверки ячейки маркера. string MarkerName · string RawText · string FieldName · CellCoordinate Coordinate · void Reject(string reason, string suggestion = null) (→ MarkerCellInvalid)
CellParseContextКонтекст одного вызова разбора. TypeToken Type · CellCoordinate Coordinate · ErrorCollector Errors · EnumRegistry Enums

Константы грамматики таблицы (SheetForge.Core.Model)

Пакет, который читает или пишет текст ячейки, работает по той же грамматике, что и импортёр — разбивает ячейку-список, составляет строку @type, проверяет, не занято ли уже имя.

Эти константы — единственный источник истины для этой грамматики, поэтому пакет никогда не переопределяет собственный разделитель заново: скопированный символ разойдётся с оригиналом в тот день, когда грамматика изменится. Списки выдаются только для чтения, поэтому ничто из того, что делает пакет, не может изменить саму грамматику. Нотация, которую они описывают, полностью задокументирована на странице Синтаксис таблиц — это программный доступ к ней.

ТипВидРоль
SheetSyntaxстатический классГрамматика таблицы в виде констант, сгруппированных ниже

Маркеры

  • CommentPrefix (#) · MarkerPrefix (@).
  • По одной константе на каждую встроенную строку-маркер: NameMarker · TypeMarker · DescMarker · OverlapMarker · StyleMarker · EnumMarker · LocMarker.
  • RequiredMarkers — три, которые обязана нести каждая таблица.
  • ReservedMarkers — все встроенные имена. Сверьтесь с ним, прежде чем называть собственный маркер: конфликт отклоняется при регистрации.

Разделители

  • ListSeparator (;) — между элементами списка.
  • EntrySeparator (,), FieldSeparator (:), SectionSeparator (|), KeyTimeSeparator (@) — слои внутри одного значения, из-за чего ; никогда не встречается в собственном тексте значения.
  • StyleKeyValueSeparator (=) — внутри ячейки @style.

Нотация @type

  • OptionalSuffix (?) · DefaultSeparator (=) · TargetSeparator (@, как в RecordId@Tab).
  • ListTypeName · ListOpen (List<) · ListClose (>).

Имена типов

  • По одной константе на каждое встроенное имя: IntTypeName · FloatTypeName · BoolTypeName · StringTypeName · RecordIdTypeName · IntIdTypeName · AssetRefTypeName · LocRefTypeName · ColorTypeName · AnimationCurveTypeName · GradientTypeName · EnumTypeName.
  • BuiltinScalarTypes и IsBuiltinScalarTypeName(name) — отвечают на вопрос «это имя уже встроенное?» ещё до того, как под этим именем зарегистрируют парсер.
  • StyleKeyNames (title, color) · LocReservedColumns (smart, comment).

Значения

  • TrueCanonical / FalseCanonical — канонический текст bool.
  • NumberCellStylesNumberStyles, с которым читается каждая числовая ячейка. Разделители тысяч исключены, а культура всегда инвариантна, поэтому локальная десятичная запятая громко завершается ошибкой вместо того, чтобы незаметно изменить число.

Доменная проверка (SheetForge.Core.Validation)

ТипРоль и ключевые члены
IDomainValidatorМежстолбцовое/межвкладочное правило. Нарушения → ctx.Errors как DomainRuleViolation со всеми 4 элементами. string Name · Validate(DomainValidationContext)
DomainValidationContextTables (вкладка → SheetTable) · KeyIndices · AssetKeys (null = пропущено) · Errors

Стык рёбер (SheetForge.Core.Validation / .Edges)

ТипРоль и ключевые члены
ReferenceScanner (статический)Единственный источник истины для перечисления вхождений ссылок. Scan(tables) · ScanTable · ScanField · IsReferenceField(TypeToken), плюс два предиката ссылок, описанных под таблицей
RefKeyKind (enum)Сравнивается ли ссылка со строковым (RecordId) или целочисленным (IntId) пространством ключей. Возвращается ReferenceScanner.GetReferenceKind; потребители ветвятся по нему. Только для добавления
ReferenceOccurrence (структура)Одно вхождение — Kind · FromTab · RowNumber · ColumnNumber · FieldName · TargetTab · TargetId · ToCoordinate()
ReferenceOccurrenceKind (enum)Scalar · ListElement · ExplicitDefault · WrapperElement · CustomElement (ссылка, которую IRefBearingValue объявил вне собственной нотации — координаты на уровне ячейки, поскольку внутренняя раскладка принадлежит этому типу). Только для добавления, поэтому существующие значения сохраняют смысл
IEdgeContributorОбъявляет рёбра, которые не видит сканер. Без диагностики. string Name · ContributeEdges(EdgeContributionContext, ICollection<EdgeSpec>)
EdgeSpecОдно ребро — FromTab/FromRecordId/ToTab/ToRecordId (+ необязательные FieldName, PayloadTab/PayloadRecordId для рёбер записи, Label)
EdgeContributionContextTables + KeyIndices только для чтения (без сборщика ошибок — рёбра не являются проверкой)
IAuthorableEdgeContributorОпциональная возможность, которую IEdgeContributor может дополнительно реализовать, чтобы его ребро можно было редактировать на холсте графа. bool TryPlanConnect(EdgeAuthoringContext, fromTab, fromRecordId, toTab, toRecordId, out EdgeCellWrite) · bool TryPlanDisconnect(EdgeAuthoringContext, RecordEdge, out EdgeCellWrite)false = ничего не подготавливается, а возможность отключена с указанием причины; оба выполняются внутри try/catch
IEdgeTokenEditorОпциональная возможность, которую IEdgeContributor может дополнительно реализовать, чтобы остаток его токена (всё, что не является ключом) можно было редактировать в инспекторе линии. bool TryDescribeToken(EdgeAuthoringContext, RecordEdge, out EdgeTokenDescription) · bool TryPlanSetModifier(EdgeAuthoringContext, RecordEdge, string newModifier, out EdgeCellWrite) — оба читают одну и ту же ячейку (ребро знает, куда указывает, но не то, как оно записано сегодня); false = строка скрыта либо честно отключена; оба выполняются внутри try/catch
EdgeTokenDescriptionЧто представляет собой токен и как редактировать его остаток — TokenText (фрагмент для подсветки) · ModifierText · HasModifier · ModifierLabel · IsChoice · Options / OptionLabels. new EdgeTokenDescription(tokenText) = без остатка, строка не отрисовывается; конструктор выбора откатывается к свободному тексту, когда список вариантов пуст
IBatchAuthorableEdgeContributorОпциональная возможность, родственная IAuthorableEdgeContributor (не наследование): планы подключения/отключения в виде списка записей ячеек — для данных, где один жест должен изменить сразу несколько парных ячеек. bool TryPlanConnectMany(EdgeAuthoringContext, fromTab, fromRecordId, toTab, toRecordId, out IReadOnlyList<EdgeCellWrite>) · bool TryPlanDisconnectMany(EdgeAuthoringContext, RecordEdge, out IReadOnlyList<EdgeCellWrite>) — весь список подготавливается как один шаг отмены либо не подготавливается вовсе; одиночные поставщики продолжают работать (запасной вариант), а пакетная форма побеждает, когда один класс реализует обе
IVirtualNodeFactoryОпциональная возможность: жесты «создать» на холсте, которые не являются новой строкой таблицы. IReadOnlyList<VirtualNodeKind> KindsFor(EdgeAuthoringContext, tab, recordId) (вызывается при каждом построении меню — держите его лёгким) · bool TryPlanCreate(EdgeAuthoringContext, tab, recordId, VirtualNodeKind, out IReadOnlyList<EdgeCellWrite>)false = сессия не затронута. План не может указывать на запись, созданную в том же жесте
VirtualNodeKind (структура)Один создаваемый вид — Id (возвращается дословно при выборе) · Label (уже переведённый текст меню; / создаёт вложенность) · IsUsable. Безопасен к null, безопасен к default
IEdgeSlotDeclarerОпциональная возможность: порты, которые (виртуальный) узел открывает без необходимости в живом ребре. IReadOnlyList<DeclaredSlot> DeclareSlots(EdgeAuthoringContext, nodeTab, nodeRecordId) — объявленные слоты присоединяются к меню подключения, пикеру портов и строкам портов карточки; вызывается при каждой отрисовке, поэтому реализации должны быть лёгкими и без побочных эффектов
DeclaredSlot (структура)Один объявленный слот — FieldName (уникален в пределах узла; должен совпадать с FieldName ребра поставщика, чтобы линии закреплялись) · TargetTab · IsList · IsUsable. Безопасен к null, безопасен к default
EdgeAuthoringContextВход для планирования — Tables + string CellText(tab, recordId, field), который возвращает ячейку в её текущем виде (baseline плюс подготовленные изменения), так что две связи, созданные подряд, видят друг друга
EdgeCellWrite (структура)План: TabName · RecordId · FieldName · NewRawText (пусто = очистить) · IsAddressable. Адресуется по ключу, а не по номеру строки

ReferenceScanner — два предиката ссылок:

  • GetReferencedTab(TypeToken) — единственный предикат, который спрашивает каждый потребитель: «это ссылка, и куда». Он отвечает для RecordId@Tab, для IntId@Tab (целочисленное пространство ключей), для внутренностей wrapper'а и для пользовательского типа с пометкой IsCustomReference. Именно поэтому одна опция — а для IntId@Tab одно расширение этого предиката — включает их все разом.
  • GetReferenceKind(TypeToken)RefKeyKind — сравнивается ли ссылка со строковым или целочисленным пространством ключей, так что распространение переименования, выпадающий список и пикер ветвятся правильно.
  • GetReferenceKind(TypeToken, tables) — перегрузка, осведомлённая о таблицах.

Базовая ссылка сама заявляет своё пространство (RecordId / IntId). У ссылающегося пользовательского типа нет нотации, чтобы это заявить — MyType@Tab единственно возможное написание, — поэтому его пространство выводится из идентичности целевой вкладки: собственный ключ RecordId означает строковое пространство, один лишь IntId означает целочисленное, а неизвестная вкладка или null-таблицы откатываются к строковому пространству — тот же ответ, что даёт перегрузка только с токеном. Именно этот вывод позволяет существующей реализации IReferencingCellType нацелиться на вкладку с ключом IntId без единой изменённой строки.

Индекс графа ссылок (SheetForge.Core.Edges)

Неизменяемый снимок, который объединяет отсканированные ядром ссылки и рёбра от поставщиков в одну модель, индексированную в обе стороны. Материал отображения — он никогда не производит диагностику (Diagnostics проекции остаётся единственным источником истины о проблемах).

ТипВидРоль и ключевые члены
RecordEdge (структура)значениеОдно ребро. RecordEdgeOrigin Origin · FromTab · FromRecordId (пусто для рёбер уровня поля) · FieldName · RowNumber / ColumnNumber (с отсчётом от 1; 0 = уровень поля/вкладки) · ToTab · ToRecordId (предполагаемый id, даже когда он не разрешён) · bool IsDangling (фиксируется во время сборки) · Label · PayloadTab / PayloadRecordId (рёбра записи)
RecordEdgeOrigin (enum)CoreReference (прочитано из ячейки RecordId@Tab — имеет координаты) · Contributor (объявлено IEdgeContributor — уровень записи)
ReferenceIndexsealed-классСнимок. статический Build(tables, keyIndices, contributorEdges, codeRegistries, extraKeys = null) (последние три могут быть null; extraKeys = вкладка → ключи, которые существуют, но ещё не разобраны, например строки, только что подготовленные поверхностью авторинга, поэтому ссылки на них не рисуются как сломанные) · AllEdges (детерминированный порядок: from-tab Ordinal → строка → столбец → вхождение) · OutEdges(tab, recordId) / InEdges(tab, recordId) (никогда не null) · int InCount(tab, recordId) · bool TryGetRowKey(tab, rowNumber, out recordId) · DanglingEdges

Холст записи Data Studio (SheetForge.Core.Graphing)

Холст сам решает, что рисовать: он проходит по индексу ссылок наружу от открытой вами записи (терминуса) и раскладывает результат детерминированно. Плагин не заменяет эту картину — он добавляет к ней. Всюду чистые данные: столбцы — это ячейки сетки, а не пиксели, а цвета — это свободная строка Category, которую окно сопоставляет с палитрой.

ТипВидРоль и ключевые члены
IRecordCanvasAugmenterинтерфейсПереопределение холста для одной вкладки, вызываемое после сборки замыкания. Augment(GraphBuildContext, CanvasAugmentBuilder, string terminusTab, string terminusRecordId). Если ничего не добавлено, базовая картина остаётся как есть; исключение перехватывается окном и становится предупреждением в консоли на английском. Идентичность принадлежит данным (виртуальный узел проигрывает настоящей записи с тем же ключом); презентация — подсказка отображения — нет
CanvasAugmentBuildersealed-классПоверхность записи, всего четыре вещи — члены и правила под таблицей
GraphShapeRegistrysealed-классИмя вкладки → переопределение холста. Register(tabName, IRecordCanvasAugmenter) (дублирующаяся вкладка / пустое имя / null бросают исключение) · TryGet · IsEmpty
GraphBuildContextsealed-классВход переопределения только для чтения. Tables (вкладка → SheetTable) · ReferenceIndex References · IReadOnlyList<CodeRegistrySource> CodeRegistries (пусто, никогда не null). Без сборщика ошибок — холст является отображением, а не проверкой
GraphSpecBuildersealed-классПомощник сборки графа. конструктор (GraphBuildContext) · статический NodeKey(tab, recordId) (единая истина, на которую указывают линии) · AddNode(GraphNodeSpec) (побеждает первый (Key, Column)) · AddWire(GraphWireSpec) · AddWire(fromKey, toKey, label, fromTab, fromRecordId, fieldName, isCyclic = false, cyclicNote = null) (перегрузка, которая также называет ячейку, в которой записана связь, — именно это делает линию редактируемой)
GraphSpecsealed-классСобранный результат, который рисует холст — Nodes · Wires (сборка проходит через builder; конструктор internal)
GraphNodeSpecsealed-классОдин узел. Key · Tab · RecordId · Title · Subtitle · Category · CellCoordinate Address · Column / Row (ячейки сетки, которые холст уже вычислил — здесь они переносятся, а не выбираются) · IsFocus (терминус) · IsMissing · InCount · IsCyclic
GraphWireSpecsealed-классОдна линия. FromKey · ToKey · Label · IsCyclic · CyclicNote, плюс необязательная владеющая ячейка: FromTab · FromRecordId · FieldName · RecordEdge? SourceEdge (null = линия только для отображения; тогда холст сообщает, что её нельзя редактировать). Пять аргументов отображения не изменились, поэтому существующие вызовы компилируются и отрисовываются идентично
IAuthorableGraphShapeинтерфейсОпциональная возможность, которую может дополнительно реализовать IRecordCanvasAugmenter. IReadOnlyList<string> CreatableTabs(GraphBuildContext, string tabName) — где холст может создавать запись (пусто = нигде). Два значения по умолчанию без неё описаны под таблицей

CanvasAugmentBuilder — поверхность записи. Всего четыре вещи:

  • AddNode(tab, recordId, title = null, category = null) / AddNode(tab, recordId, title, category, CellCoordinate address)виртуальный узел для идентичности, не являющейся записью таблицы (ключ события, атом кода); вкладка может быть пустой.
  • AddEdge(fromTab, fromRecordId, toTab, toRecordId, label = null, fieldName = null, fieldOnTarget = false, isCyclic = false, cyclicNote = null)дополнительное ребро, которое сканер ядра не видит. Указание fieldName говорит, в какой ячейке записана связь, fieldOnTarget говорит, что эта ячейка находится на стороне прибытия, а не отправления, а пара параметров цикла помечает петлю для отображения с примечанием, которое известно только домену.
  • SetLayer(tab, recordId, layer)абсолютная подсказка слоя (0 = крайний слева, отрицательное = ещё левее, всё остальное сдвигается вправо для компенсации). SetLayerRelative(tab, recordId, offset) — то же самое, но отсчитываемое от терминуса (−1 = столбец сразу слева от него), разрешаемое относительно столбца терминуса до того, как его сдвинула любая подсказка.
  • SetSubtitle(tab, recordId, subtitle)подсказка отображения, единственная вещь, которая применяется к уже существующим записям и к записям, не показанным на экране (их читает пикер подключения).

Элементы с пустым ключом игнорируются, а то, что было собрано, — internal, поскольку правила слияния живут в одном месте. Каждое расширение — это добавленный в конец аргумент, поэтому переопределение, написанное против более ранней поверхности, всё ещё компилируется.

IAuthorableGraphShape — два значения по умолчанию без неё:

  • Список создаваемых вкладок, который заменяет эта возможность, — та же ось, что также решает, откроется ли холст вообще и как далеко достанет проход по строкам в ожидании, — охватывает каждую вкладку, достижимую из вкладки фокуса, следуя по схеме транзитивно.
  • Каскад связывания, который пользователь видит на самом деле, начинается с вкладок, на которые нацелены нарисованные в данный момент порты.

Оба отбрасывают вкладки-реестры кода и вкладки без ключевого столбца. Вкладка, которую вернул этот метод, но которую не принимает ни один нарисованный порт, остаётся в каскаде связывания с прикреплённой причиной, а собственные ограничения окна по-прежнему применяются поверх.

Цветовые пресеты (SheetForge.Core.Theming)

ТипРоль и ключевые члены
ThemeRegistryId пресета → тема. Пустые id, дубликаты и два зарезервированных встроенных id бросают исключение. Register(SheetForgeTheme) · TryGet · Themes · IsEmpty · IsBuiltInId(id) · BuiltInDefaultId · BuiltInHighContrastId
SheetForgeThemeОдин цветовой пресет. Id · DisplayName · DarkColors / LightColors (IReadOnlyDictionary<ThemeColorSlot, uint>, копируется при создании) · TryGetColor(dark, slot, out rgb) · IsEmpty
ThemeColorSlotenum — 33 цветовые роли, которые пресет может переопределить (поверхности, линии, текст, семантические цвета, метки подготовки, поверхности сбоя, затемнение, граф). Цвета — это 0xRRGGBB: Core не ссылается ни на один тип движка, а полупрозрачные заливки выводятся из цвета слота плюс фиксированная альфа. Только для добавления.

Пресет переопределяет только те слоты, которые он называет; каждый остальной слот сохраняет значение продукта по умолчанию, поэтому пресет остаётся валидным по мере добавления новых слотов. Регистрация никогда не применяет пресет — пользователь выбирает его в Preferences ▸ SheetForge ▸ Theme.

Декларативные поверхности авторинга (SheetForge.Core.Studio)

Плагин описывает, что показать — оболочку как данные, предикат и эффект как делегаты, — а каждый хост рисует это собственными виджетами: UIToolkit в редакторе, React в браузере. Нигде не встречаются числа раскладки. Что сказать — дело плагина, как разместить — дело рендерера.

Каждый enum здесь только для добавления, поэтому регистрация сохраняет смысл по мере роста словаря.

ТипВидРоль и ключевые члены
StudioUiRegistrysealed-классТо, что заполняет RegisterStudioUi. AddAction(StudioActionDescriptor) · AddPanel(StudioPanelDescriptor) · AddColumnBadge(StudioColumnBadgeDescriptor) · AddCellEditorHint(StudioCellEditorHint) · Actions / Panels / ColumnBadges / CellEditorHints · IsEmpty
StudioUiNodesealed-классОдин описанный фрагмент, неизменяемый, собираемый через статические фабрики — фабрики, читаемые свойства и правило URL под таблицей
StudioUiNodeKindenum13 видов выше (RowLink)
StudioActionDescriptorsealed-классОдна команда. Id (уникален) · LabelKey (ключ Loc; незарегистрированный отображается дословно) · StudioActionPlacement Placement · Func<StudioSurfaceContext,bool> AppliesTo · Action<StudioSurfaceContext> Execute · ConfirmKey (необязательно — хост сначала задаёт это предложение). Хост заново проверяет AppliesTo при вызове, поэтому устаревший пункт меню отвечает честным no-op'ом и перерисовкой
StudioActionPlacementenumInspector · RowContextMenu · TopbarMenu · ColumnHeaderMenu · CanvasNodeMenu. Каждое место заполняет разные поля контекста — место строки несёт запись, место столбца — имя столбца, место холста — запись этого узла
StudioPanelDescriptorsealed-классОдна панель в правой панели Studio. Id · TitleKey · Func<StudioSurfaceContext,StudioUiNode> Build — пересобирается на каждом такте пересчёта, поэтому не хранит состояние. Без зарегистрированной панели правая панель вообще не рисуется
StudioColumnBadgeDescriptorsealed-классОдин значок рядом с заголовком столбца. Func<StudioSurfaceContext,string,string,StudioUiNode> Provide (контекст, вкладка, поле) — null означает ничего на этом столбце
StudioCellEditorHintsealed-класс«Используй этот встроенный виджет для этого типа» — выбор вида, а не предоставление его. TypeName (точное имя типа CellParserRegistry; ячейка списка сопоставляется по имени своего элемента; ячейки wrapper'а сохраняют канонический текст и никогда не сопоставляются) · StudioCellEditorArchetype Archetype · GetOptions (только для выпадающего списка — Func<context, tab, field, IReadOnlyList<StudioCellOption>>) · SliderMin / SliderMax · ToggleTrueValue / ToggleFalseValue. Четыре конструктора, по одному на форму материала. Учитывается после того, как зарегистрированный IStudioCellEditorProvider отказался, и до встроенных веток; подсказка пакета учитывается раньше приведённых ниже встроенных подсказок, поэтому регистрация такой подсказки для Color, AnimationCurve или Gradient переопределяет редактор по умолчанию для этого типа. List<>, чья подсказка элемента — ColorPicker, CurveEditor или GradientEditor, становится редактором-плашкой в обоих хостах
StudioCellEditorArchetypeenumDropdown · MultilineText · Slider · Toggle · ColorPicker (текст ячейки #RRGGBB / #RRGGBBAA) · CurveEditor (текст ячейки = каноническая нотация CurveValue) · GradientEditor (текст ячейки = каноническая нотация GradientValue). Только для добавления — два новейших значения: 5 и 6
BuiltinCellEditorHintsстатический классТри подсказки, которые заявляет сам Core, — ColorColorPicker, AnimationCurveCurveEditor, GradientGradientEditor — проходящие тем же путём, что и подсказки пакета, поэтому редактор и браузер не могут выбрать для них разные виджеты. IReadOnlyList<StudioCellEditorHint> All (фиксированный порядок) · bool TryGet(typeName, out hint) (Ordinal). Хосты сначала обращаются к StudioUiRegistry.CellEditorHints, а затем откатываются к этой таблице
StudioCellOptionsealed-классОдин кандидат выпадающего списка — Value (канонический текст, записываемый в ячейку) · Label (то, что читает человек; по умолчанию Value)
StudioSurfaceContextsealed-классЕдинственный стык, который видит и через который действует расширение. Чтение: Tables · ReferenceIndex References · CodeRegistries · Tab · RecordId · Field · ActionArgument (значение, которое подготовил узел Input). Опосредованное изменение, и ничего больше: Action<string,string,string,string> StageCell · Action<IReadOnlyList<EdgeCellWrite>> StageCells (один шаг Undo, всё или ничего) · Action<string,string> FocusRecord · Action RequestRebuild. Подготовка проходит через собственный шлюз окна, так что источник только для чтения, работающий конвейер или вкладка из книги блокируют её с указанием причины (конструктор internal: хост собирает его сам)

StudioUiNode — фабрики, чтение и правило URL:

  • Фабрики: Row · Label · Chip · Badge · Button · Rule · Heading · KeyValue · Table(headerRow, rows) · List · Progress · Input · Link, плюс WithTooltip(text), который возвращает новый узел, а не изменяет этот.
  • Чтение: Kind · Text · Tooltip · ThemeColorSlot? Tone (никогда не жёстко заданный цвет, поэтому он следует за темой) · ActionId · Detail · Ratio · Url · Children.
  • статический bool IsAllowedUrl(url) — только http/https. Один предикат, который спрашивают оба хоста, поэтому они не могут разойтись в том, что безопасно открывать.

Строки интерфейса плагинов (SheetForge.Core.Model)

ТипРоль и ключевые члены
StringOverlayRegistryКоллектор и оверлей поиска для зарегистрированных плагином строк интерфейса; Loc.Tr (редактор) и t() (браузер) обращаются к нему раньше таблиц продукта. Register(key, language, value) · Register(key, IReadOnlyDictionary<string,string> byLanguage) · bool TryGet(key, language, out value) · RegisteredKeys. Сопоставление языков и четыре отказа — под таблицей

StringOverlayRegistry — сопоставление и отказы. language — это код IETF ("en", "ko", "zh-Hans", "pt-BR", …), сопоставляется без учёта регистра. Поиск откатывается запрошенный язык → английский → промах, и этот откат живёт здесь, чтобы оба хоста отвечали одинаково.

Четыре регистрации отклоняются, каждая с записью причины, понятной разработчику, а не молчаливым провалом:

  • встроенный ключ продукта — оверлей может добавлять ключи, но никогда не перезаписывать собственные предложения или пути меню продукта;
  • пара ключ+язык, уже зарегистрированная другим пакетом — побеждает найденная первой, иначе порядок установки решал бы, что на экране;
  • пустой ключ или значение;
  • код языка, которого продукт не знает, — он никогда не сворачивается в английский.

Наблюдение за конвейером (SheetForge.Core.Plugins / .Model)

ТипРоль и ключевые члены
IPipelineObserverУведомление только для чтения. void OnImportCompleted(PipelineRunView view) — один раз на явный цикл импорта, в его конце, при успехе или неудаче. Намеренно нет хука, который изменял бы значение или добавлял диагностику (это принадлежит типу ячейки и IDomainValidator), и нет ни одного, что выполнялся бы на предварительной проверке подготовки. Исключение изолируется, а его причина собирается; результат импорта не меняется. Будущие точки наблюдения приходят как родственные интерфейсы возможностей, приводимые из зарегистрированного наблюдателя, поэтому реализация, написанная сегодня, продолжает компилироваться
PipelineObserverRegistryСписок наблюдателей только для добавления, порядок сохраняется. Register(IPipelineObserver) · Observers
PipelineRunViewНеизменяемый снимок, который получает наблюдатель — Success (проверка, то есть был ли собран реестр; результаты генерации кода/запекания читаются из диагностики) · Tables (вкладки, которые разобрались; при неудачном прогоне отсутствуют только те вкладки, которые не удалось разобрать, потому что «никакой частичной сборки» — это правило результата, а не правило наблюдения) · Diagnostics (тот же список, что показывает отчёт) · SkippedTabs · EnumTabs. Коллекции копируются при создании, а конструктор internal, поэтому наблюдателю никогда не передаётся наполовину собранный снимок

Реестры кода (SheetForge.Core.Graphing)

Цели ссылок, которые живут в коде, предоставленные поверхности авторинга как заблокированные виртуальные вкладки. Потребляются Data Studio (боковая панель / граф / инспектор), а не валидатором импорта.

ТипВидРоль и ключевые члены
CodeRegistryCatalogsealed-классКорень регистрации. Register(CodeRegistrySource) (null / пустое имя вкладки / дублирующееся имя вкладки бросают исключение) · TryGet(tabName, out source) · Sources · IsEmpty
CodeRegistrySourcesealed-классОдна заблокированная виртуальная вкладка. string TabName · IReadOnlyList<CodeRegistryEntry> Entries (порядок регистрации = порядок отображения)
CodeRegistryEntrysealed-классОдна запись. string Key (на что может указывать ссылка) · string Label · IReadOnlyList<string> Raises (null нормализуется в пустой список). Core обращается со всеми тремя как с непрозрачными строками

Модель чтения IR (SheetForge.Core.Model)

ТипРоль и ключевые члены
SheetTableРезультат разбора одной вкладки. SheetSchema Schema · IReadOnlyList<SheetRecord> Records
SheetSchemastring TabName · Fields · TryGetField(name, out FieldSchema) · SheetStyle Style (метаданные отображения @style этой таблицы) · bool IsLocalizationSheet (маркер @loc присутствует) · IReadOnlyList<LocaleColumn> LocaleColumns (языковые столбцы в исходном порядке столбцов — пусто у таблицы, которая не является таблицей локализации, никогда не null) · TryGetLocaleColumn(localeCode, out LocaleColumn) (поиск по коду, без учёта регистра) · TryGetSourceLocale(out LocaleColumn) (первый языковой столбец; false, когда такого нет)
SheetStyleЗначение строки @style — метаданные отображения для одной таблицы. string Title (метка группы боковой панели) · string ColorHex (#RRGGBB в исходном виде) · bool HasColor · статический None (без оформления). Никогда не читается генерацией кода, запеканием или отпечатком схемы
LocaleColumn (структура)Один языковой столбец таблицы локализации — то, что строка @loc записала в этом столбце. string Code (код точно в исходном виде; Core проверяет форму написания, а не существование самого языка) · string FieldName · int ColumnNumber (с отсчётом от 1) · bool IsSource (первый языковой столбец — тот, чей текст читают встроенные предпросмотры и в который пишет чеканка)
SheetRecordint RowNumber (исходный, с отсчётом от 1) · Values (поле → CellValue) · TryGet · индексатор
FieldSchemaName · TypeToken Type · Description · ColumnNumber · DefaultValue · AllowOverlap · IReadOnlyDictionary<string,string> MarkerValues (имя пользовательского маркера → текст ячейки этого столбца)
TypeTokenРазобранная ячейка @type. RawText · TypeName · TypeArgument · TargetName · IsList · IsOptional · HasExplicitDefault · DefaultValueText · AllowsEmptyCell · IsSelfKey · IsIntId (только собственный целочисленный ключ этой вкладки — ссылочная форма IntId@Tab читается через TargetName + ReferenceScanner.GetReferencedTab, так же, как и RecordId@Tab) · TypeToken InnerToken / IsWrapper (wrapper-типы — рекурсивная внутренняя часть) · IsCustomReference (этот столбец — MyType@Tab, где парсер реализует IReferencingCellType; ReferenceScanner.GetReferencedTab — единственный предикат, который это читает, именно так все потребители заработали без изменения сигнатуры) · AssetTypeName (<Type> из AssetRef@Group<Type> в исходном виде, null, если ограничения нет; Core хранит только имя — его разрешением занимается IAssetTypeResolver — и оно проставляется также на токене AssetRef внутри списка или wrapper'а). Три последних параметра конструктора (innerToken, isCustomReference, assetTypeName) имеют значения по умолчанию, поэтому существующие вызовы компилируются, а более ранние конструкторы с 8 и 10 аргументами остаются перегрузками, поэтому уже скомпилированные сборки плагинов продолжают работать без пересборки
CellValue (структура)Одно типизированное значение ячейки; без null (IsDefaulted помечает материализованные значения по умолчанию). object Value · IsDefaulted · AsList · статические Of / Defaulted
RecordId (структура)Значение ключа (сравнение Ordinal). string Value · IsEmpty
RecordRefValue (структура)Значение ячейки RecordId@Tab. TargetTab · Id
IntRefValue (структура)Значение ячейки IntId@Tab — целочисленный близнец RecordRefValue. string TargetTab · int Id · bool IsEmpty · статический Empty(tab) (необязательный IntId@Tab?, указывающий в никуда)
LocRefValue (структура)Значение ячейки LocRef@Tab — локализационный близнец RecordRefValue, оставленный отдельным типом, чтобы потребитель по одному лишь значению знал, что оно указывает на строковую таблицу. string TargetTab · string Key · bool IsEmpty · статический Empty(tab) · ReferencedKeys. Оно реализует IRefBearingValue, так что сканер ссылок обращается с ним точно так же, как со ссылкой Core
AssetRefValue (структура)Значение ячейки AssetRef@Group. Group · Key (ключ вложенного ассета — parent[sub])
EnumValue (структура)Значение ячейки Enum<T> (пара строк — преобразование в CLR-тип выполняется при запекании). EnumName · MemberName

Типизированные ссылки на ассеты (SheetForge.Core.Model)

<Type> в AssetRef@Group<Type> разрешает хост — Core не знает ни движка, ни сборок проекта, — а Core лишь оценивает результат. Всё здесь — чистые данные.

ТипВидРоль и ключевые члены
IAssetTypeResolverинтерфейсAssetTypeResolution Resolve(string rawName) — одно имя на входе, один результат на выходе; одно и то же имя всегда даёт один и тот же ответ (реализации могут кешировать). Внедряется в ImportPipeline отдельно от AssetKeyIndex, поэтому имена типов разрешаются даже в проекте, где ещё нет настроек Addressables; если резолвер не внедрён (headless, браузер), диагностика по именам типов просто не производится. Реализация на стороне Editor разрешает имена по загруженным в проекте типам ассетов, производным от UnityEngine.Object (без списка разрешённых типов; компоненты и типы, доступные только редактору, исключены)
AssetTypeResolutionsealed-классРезультат для одного имени — RawName · AssetTypeResolutionStatus Status · FullName (полное имя CLR, вложенные типы через +; только для Resolved и NotReferenceable) · AssemblyName (сборка, на которую должна ссылаться сгенерированная сопутствующая сборка, — задана для типов из asmdef-сборок, null для модулей движка и неразрешённых имён) · Candidates (никогда не null: неоднозначные кандидаты либо предложения ближайшего совпадения для неизвестного имени). Фабрики Resolved(raw, fullName, assemblyName) · Unknown(raw, suggestions) · Ambiguous(raw, candidates) · NotReferenceable(raw, fullName, assemblyName)
AssetTypeResolutionStatusenumResolved · Unknown (такого типа нет) · Ambiguous (короткое имя совпадает с несколькими типами — укажите полное имя) · NotReferenceable (тип находится в предопределённой сборке, такой как Assembly-CSharp, на которую сгенерированный код не может сослаться)

Генерация кода читает разрешённый словарь, который производит конвейер, и генерирует AssetReferenceT<global::FullName> для разрешённого имени; имя, которое не находится в этом словаре, никогда не генерируется дословно — поле откатывается к AssetReference, и собирается предупреждение AssetTypeUnresolvedFallback. Разрешённое полное имя также учитывается в отпечатке схемы.

Визуальные типы значений (SheetForge.Core.Model)

Независимые от движка модели значений для трёх встроенных визуальных типов. Каждая из них неизменяема, реализует IEquatable и владеет собственной текстовой формой (TryParse / Render) — той же нотацией, которую описывает страница «Синтаксис таблиц», — поэтому тип плагина, хранящий цвет, кривую или градиент, может переиспользовать их вместо изобретения второй нотации. Editor запекает их в UnityEngine.Color / AnimationCurve / Gradient и считывает их обратно; браузер получает их значения через evaluator'ы ниже, а не реализует математику заново.

ТипВидРоль и ключевые члены
ColorValuereadonly-структураЧетыре байта R · G · B · A · статический Default (#00000000) · статический TryParse(text, out value, out error) (принимает #RGB / #RGBA / #RRGGBB / #RRGGBBAA) · Render() (заглавными буквами; шесть цифр для непрозрачного значения)
CurveValuesealed-классKeys (по возрастанию времени) · PreWrap / PostWrap · статический Empty (без ключей — единственное состояние без текстовой формы; Render() даёт "") · статический Create(keys, preWrap, postWrap)единственный путь конструирования: сортирует по времени, отклоняет повторяющиеся моменты времени и применяет CurveTangentSolver, так что правило «режим побеждает» действует с момента появления кривой · статический TryParse (ключи с 2/4/7/8 полями, Once принимается как псевдоним ClampForever, касательные Infinity/-Infinity) · Render() (ключи с 8 полями, суффикс wrap только когда нужен)
CurveKeyreadonly-структураTime · Value · InTangent · OutTangent · InWeight · OutWeight · CurveWeightedMode WeightedMode · CurveTangentMode LeftMode / RightMode · bool Broken; конструктор с десятью аргументами и без собственной нормализации
CurveWrapenumClampForever · Loop · PingPong · Default — словарь wrap-режимов Unity по именам (отображение значения на WrapMode — задача бейкера)
CurveTangentModeenumFree = 0 · Auto = 1 · Linear = 2 · Constant = 3 · ClampedAuto = 4 — имя и значение идентичны AnimationUtility.TangentMode, поэтому бейкер сопоставляет по имени и никогда не трогает упакованные биты касательных Unity
CurveWeightedMode[Flags] enumNone = 0 · In = 1 · Out = 2 · Both = 3 — какая сторона ключа использует взвешенные (Безье) касательные
CurveTangentSolverстатический классCurveKey[] Apply(IReadOnlyList<CurveKey> sortedKeys) — вычисляет числа касательных, которые диктует режим, применяя стадии в порядке движка (Linear на своей стороне → ClampedAuto на обеих сторонах → Auto на обеих сторонах → Constant на своей стороне), оставляя стороны Free и веса нетронутыми. CurveValue.Create вызывает его, поэтому вызывающему коду редко приходится делать это самому
CurveEvaluatorстатический классfloat Evaluate(CurveValue, float time) · float[] Sample(CurveValue, int count) (count ≥ 2, равномерно распределены от первого до последнего ключа) — интерполяция Эрмита между ключами, взвешенная Безье на сторонах, где установлен флаг веса, удержание значения, когда касательная бесконечна, и четыре режима обёртывания за пределами диапазона ключей; проверено против AnimationCurve.Evaluate на случайных кривых
GradientValuesealed-классColorKeys · AlphaKeys (от 1 до 8 каждого вида, по возрастанию времени) · GradientBlend Mode · GradientColorSpace ColorSpace · статический Default (белый, полностью непрозрачный, Blend) · статический Create(colorKeys, alphaKeys, mode, colorSpace) (проверяет количества и диапазоны 0…1, квантует время до 16 бит, как это делает Unity, стабильно сортирует) · статический TryParse (три или четыре секции, разделённые `
GradientColorKeyreadonly-структураColorValue Color (альфа игнорируется — у альфы свои собственные ключи) · float Time
GradientAlphaKeyreadonly-структураfloat Alpha · float Time
GradientBlendenumBlend · Fixed · PerceptualBlend
GradientColorSpaceenumUninitialized (не записывается; читается как Gamma) · Gamma · Linear — затрагивает только PerceptualBlend
GradientEvaluatorстатический классColorValue Evaluate(GradientValue, float time) · ColorValue[] Sample(GradientValue, int count) — линейное, ступенчатое или перцептивное (Oklab) смешение с отдельно смешиваемыми ключами альфа-канала, округлённое до байтов; проверено против Gradient.Evaluate на случайных градиентах

Ошибки и результаты (SheetForge.Core.Model / .Reporting)

ТипРоль и ключевые члены
ImportErrorСтруктурированная, нейтральная к локали ошибка. Code · Severity · Coordinate · ActualValue · Expected · Suggestion
ImportErrorCode (enum, 105)Полный каталог «почему» — семейства, которые он охватывает, перечислены под таблицей. Только для добавления — таблицы рендереров привязаны к значениям членов
ImportSeverity (enum)Error (блокирует результат) · Warning
CellCoordinate (структура)Вкладка · строка (с отсчётом от 1) · столбец (с отсчётом от 1) · поле; вычисляет букву столбца таблицы. Фабрики ForTab / ForRow
ErrorCollectorПриёмник по принципу «собирать всё». All · HasErrors · ErrorCount · Add
ImportResultРезультат конвейера. Инвариант: Success == false ⇔ Registry == null. Success · Registry · Diagnostics · SkippedTabs · EnumTabs (вкладки, прочитанные как листы определений enum, поэтому никогда не разбираемые как таблицы данных — хранятся отдельно от SkippedTabs, которое означает «таблица ещё не записана», поэтому счётчик пропущенных в отчёте остаётся достоверным; оба — это множества сохранения, которые оставляют сгенерированный код, запечённые ассеты и адреса для этих вкладок) · статические Succeeded / Failed
ImportReport (.Reporting, сборка SheetForge.Core.Tooling)Вход для рендереров отчёта — Timestamp · SourceDescription · TabCount · RecordCount · Success · Diagnostics · ErrorCount · WarningCount · SkippedTabCount (сколько из TabCount были пустыми таблицами, пропущенными, а не импортированными, — заголовок печатает это число, чтобы количество вкладок не приняли за «всё импортировано»)
ImportReportText (.Reporting, сборка SheetForge.Core.Tooling, статический)Отрисовывает отчёт в собственную понятную человеку строку продукта, ничего не записывая в консоль и не добавляя ссылку перехода или строку машинных координат (это относится к собственному соглашению консоли). string Render(ImportReport report, IReadOnlyDictionary<string,string> languageTable = null, string operationName = null) — опустите таблицу для английского; имя операции, если оно опущено, читается из той же таблицы, чтобы предложение никогда не смешивало два языка. Вызывающему коду на стороне редактора обычно нужен SheetForgeActions.RenderReportText(report), который подставляет текущий язык редактора (чистая сборка не может читать EditorPrefs)

ImportErrorCode — семейства, которые он охватывает:

  • маркеры, схема, типы, ячейки, ключи/ссылки и ключи ассетов;
  • источники/файлы, csv/xlsx, идентификаторы генерации кода, addressables, baseline/экспорт, Google/аутентификация/отправка и шаблоны;
  • плагины — PluginRegistrationConflict, а также PluginIncompatible, когда декларация совместимости сборки выходит за рамки того, что читает этот хост;
  • IntId — DuplicateIntId, а для ссылок IntId@TabUnresolvedIntId · TargetTabHasNoIntId;
  • @overlap и DomainRuleViolation;
  • листы определений enum — EnumSheetMarkerConflict · DuplicateEnumName · EnumSheetEmptyColumn · InvalidEnumIdentifier · InvalidEnumUnderlyingType · InvalidEnumMemberValue;
  • DropdownNotSupportedByFormat, что является предупреждением, а не ошибкой;
  • типизированные ссылки на ассеты — UnknownAssetType · AmbiguousAssetType · AssetTypeNotReferenceable (один раз на столбец, в строке @type), AssetTypeMismatch на каждую ячейку, и предупреждение генерации кода AssetTypeUnresolvedFallback.

Индексы и утилиты (SheetForge.Core.Validation / .Model / .Parsing / .Unparse)

ТипРоль и ключевые члены
TabKeyIndexИнформация о ключе одной вкладки — строковый ключевой столбец плюс множество целочисленных ключей IntId этой вкладки, так что и RecordId@Tab, и IntId@Tab разрешаются по нему. TabName · KeyField · HasKeyColumn · Keys · Contains(id)
KeyIndexBuilder (статический)Строит индексы ключей (строковые ключи и множество целочисленных ключей IntId, за один проход), сообщает об ошибках ключей, проверяет столбцы IntId. Build(SheetTable, ErrorCollector) · ValidateIntIdColumns
AssetKeyIndexГруппа → набор допустимых ключей (Editor заполняет из каталога Addressables, включая ключи вложенных ассетов; внедрение null = пропуск проверки ассетов). Register(group, keys) · HasGroup · HasKey · KeysOf · GroupNames, плюс слой типов, которым пользуется AssetRef@Group<Type>: RegisterTyped(group, key, satisfiedTypeFullNames) (ключ и замыкание полных имён типов, в виде которых его можно загрузить, — собственный тип, базовые типы, интерфейсы, типы его вложенных ассетов; повторная регистрация объединяет замыкание) · HasTypeInfo(group, key) · SatisfiesType(group, key, typeFullName). Ключ, зарегистрированный обычным Register, не имеет замыкания и освобождён от проверки типа, а не проваливает её
LocalizationCoverage (статический)Покрытие по каждому языку и ключи-сироты для таблицы локализации. Чистый расчёт, который возвращает списки, а не собирает ошибки, потому что непереведённая ячейка и неиспользуемый ключ — это нормальные состояния, а не выходы, которые нужно блокировать. IReadOnlyList<LocaleCoverage> Compute(SheetTable) · IReadOnlyList<string> FindOrphanKeys(locTabName, tables) (ключи, на которые ничто не указывает; намеренно консервативно — любая известная сканеру форма ссылки считается использованием, так что живой перевод никогда не назовут сиротой)
LocaleCoverage (sealed class)Покрытие одного языка. LocaleColumn Locale · int TotalKeys · int TranslatedKeys · IReadOnlyList<string> MissingKeys (в порядке строк таблицы, никогда не null) · bool IsComplete
TextSuggestion (статический)Предложения ближайшего совпадения (ограниченный, детерминированный алгоритм Левенштейна). FindNearest · Distance · DistanceWithin
BuiltinCellParsers (статический)CreateDefaultRegistry() — 12 встроенных парсеров (int, float, bool, string, Enum, RecordId, AssetRef, IntId, LocRef, Color, AnimationCurve, Gradient).
CanonicalValueRenderer (статический)Значение → каноническая строка ячейки (экспорт/отправка). TryRender(…) (делегирует ColorValue / CurveValue / GradientValue собственному Render(); кривая без ключей рендерится как пустая ячейка) · RenderFloat(float) (кратчайший round-trip)

План отправки (SheetForge.Core.Unparse)

Публичны, потому что IPushApprover.Approve(PushPlan) их предоставляет; чистые данные.

ТипРоль
PushPlan (сборка SheetForge.Core.Tooling, как и три строки ниже)Весь план отправки. Tabs · HasWork
PushTabPlanОдна вкладка: Writes · Appends · Deletes (ключ + номер строки; DeleteNotices остаётся представлением только по ключу)
PlannedCellWriteОдна запись ячейки — координаты, ячейка baseline, новое значение/текст, флаг строкового семейства
PlannedRowAppendОдна добавленная строка — полные тексты ячеек + столбцы строкового семейства

Сборка Editor (SheetForge.Editor)

Настройки, локализация, композиция (SheetForge.Editor.Pipeline / .Localization)

ТипРоль и ключевые члены
SheetForgeSettings (SO)Ассет настроек. Поля: sourceProviderId (единственная ось выбора источника; пусто = встроенный LocalFile) · localFolderPath · bakeOutputFolder · generatedCodeFolder · generatedNamespace · exportFolderPath · exportFormat · spreadsheetId · googleAccessMode · serviceAccountKeyPath · gidMap (список GidMapEntry { tabName, gid }). Разрешённые свойства Effective*.
Loc (статический)Точка входа локализации. Tr(key) · TrContent(…) · Table · константа MenuRoot. Tr разрешается в четыре шага: зарегистрированная плагином строка (текущий язык, затем английский — этот откат обеспечивает сам оверлей, см. StringOverlayRegistry) → встроенная таблица (текущий язык, затем английский) → сам ключ. Для строк плагина существует ровно один канал регистрации, поэтому вопрос «чья регистрация побеждает» никогда не возникает
PluginRegistry (статический)Обнаруживает плагины через TypeCache, затем передаёт кандидатов в PluginComposition.Compose. Build · BuildValidators · BuildEdgeContributors · BuildStructuralMarkers · BuildTemplates · BuildGraphShapes · BuildCodeRegistries · BuildThemes · BuildAll (комплект) · InvalidateCache() (сбрасывает кеш на время перезагрузки — то же соглашение, что и SourceProviderRegistry.InvalidateCache; также сбрасывает кеш шлюза совместимости, так что изменившийся набор обнаружения переоценивается заново). Комплект и изоляция слотов — под таблицей
ImportEvents (статический)Шина событий на стороне редактора — публичный контракт: внешние ассеты могут подписаться. event Action<ImportCompletedArgs> ImportCompleted · RaiseImportCompleted(ImportCompletedArgs) срабатывают, только когда импорт прошёл весь путь до запекания, так что подписчик может читать запечённые ассеты. event Action<BaselineUpdatedArgs> BaselineUpdated · RaiseBaselineUpdated(BaselineUpdatedArgs) срабатывают всякий раз, когда снимок таблицы был сохранён — включая прогон, провалившийся проверку, — именно так поверхность авторинга обновляется при импорте в карантине. Две оси, намеренно не объединённые: одна означает «таблицы сдвинулись», другая — «ассеты сдвинулись»
BaselineUpdatedArgs (sealed)Полезная нагрузка сохранения baseline. IReadOnlyList<string> Tabs (вкладки, записанные в снимок) · bool Quarantined (провалил ли проверку только что сохранённый снимок)
SheetForgeActions (статический)Фасад запуска — тот же цикл, что запускает клик по меню, вызываемый из скрипта CI, хука сборки или собственной кнопки. RunImport() · RunExport() · RunPush() · RunHealthCheck() · RunLocalizationSync() (каждый делегирует; разрешение настроек, проверка Addressables, взаимное исключение, модальные подтверждения, индикатор прогресса и возобновление генерация кода→компиляция→запекание — всё остаётся внутри продукта) · bool IsBusy · bool TryBeginExclusiveScope(out IDisposable scope) (false + scope = null, когда что-то уже выполняется; освобождает именно scope, и повторный Dispose не может освободить чужой запуск) · string RenderReportText(ImportReport) (собственные предложения продукта на текущем языке редактора, без записи в консоль). Семантика завершения — под таблицей
SheetForgeEditorInfo (статический, пространство имён SheetForge.Editor)Якорь сборки Editor — const Version, зеркало SheetForgeRuntimeInfo для проверки функциональности на стороне редактора
ImportCompletedArgs (sealed)Полезная нагрузка завершения, передаваемая подписчикам. IReadOnlyList<string> Tabs (вкладки, запечённые при этом завершении) · string BakeFolder (папка Database-SO). Паттерн args-объекта — будущие поля не сломают сигнатуру события.
GoogleSheetAccessMode (enum)SheetsApi (с аутентификацией, доступен для записи) · ExportUrl (без аутентификации, только для чтения)
ExportFormat (enum)Tsv · Csv · Xlsx · Json · MatchSource

PluginRegistry — комплект и изоляция слотов. Вложенный PluginBundle предоставляет собранный PluginSet Set — единую истину из двенадцати слотов, благодаря которой новый слот можно прочитать, не расширяя комплект, — плюс девять удобных окон в него: Enums · Parsers · Validators · EdgeContributors · Markers · Templates · GraphShapes · CodeRegistries · Themes. Более ранние конструкторы с шестью и восемью аргументами сохранены как перегрузки, которые по умолчанию делают более поздние реестры пустыми, что ведёт себя идентично версиям до появления этих контрактов.

Изоляция — забота Core, а не этого типа: о плагине, который бросает исключение во время регистрации, предупреждают по имени и пропускают, а каждый другой слот и каждый другой плагин всё равно регистрируются.

SheetForgeActions — семантика завершения. RunImport/RunPush являются fire-and-forget. Их тела async void, поскольку главный поток редактора не может блокироваться на сетевом вводе-выводе, так что возврат не означает завершения — подпишитесь на ImportEvents.ImportCompleted для этого. RunExport/RunHealthCheck/RunLocalizationSync завершаются синхронно — RunLocalizationSync проходит путь таблица → StringTable, который проходит завершение импорта, а без пакета Unity Localization показывает уведомление об установке и ничего не меняет.

Стык провайдера источника (SheetForge.Editor.Sources)

ТипРоль и ключевые члены
ISheetSourceProviderКонтракт провайдера. Id · DisplayNameKey · CreateTabSource(settings) · GetVisibility(settings) · CanAuthor(settings) · CreateReflectTarget(dispatcher, settings)
ISourceReflectTargetЦель записи обратно. void Reflect()
SourceVisibilityКакие поля настроек показывать — 5 булевых флагов
SourceProviderRegistry (статический)Обнаружение/разрешение. All · ResolveActive(SheetForgeSettings) и ResolveActive(string providerId) (разрешает прямо по id, без ассета настроек на руках) · TryGet · InvalidateCache
ITabSourceАбстракция получения данных. Description · Task<TabSourceResult> FetchAsync()
TabSourceResultВкладки (имя → исходный TSV) + диагностика + форматы по вкладкам; частичный результат допустим. Статический Create
TabSourceFormat (enum)Tsv · Csv · Xlsx · GoogleSheet

Точки расширения Data Studio (SheetForge.Editor.Studio)

На стороне редактора, поскольку они затрагивают UIElements / состояние окна — та же обоснованная асимметрия, что и у ISheetSourceProvider. Все четыре контракта обнаруживаются через TypeCache (конструктор без параметров; без вызова регистрации), и все вызываются внутри try/catch. Само окно (DataStudioWindow) — internal.

Что-либо, выразимое как данные, принадлежит словарю Core ISheetForgeStudioPlugin — он тоже отрисовывается в браузере. Эти же контракты — лазейки без потолка для того, что описание сказать не может.

Последние четыре записи — это не контракты, а инструменты, которые может использовать смонтированный виджет:

  • собственные значения оформления окна только для чтения, чтобы виджет выглядел так, будто он на своём месте;
  • выпадающий список ключей, чтобы виджет ячейки выбирал ключи так же, как встроенная ячейка;
  • и сброс кеша обнаружения, чтобы ваши собственные тесты могли заново обнаружить пробу.
ТипВидРоль и ключевые члены
IStudioGraphWidgetинтерфейсДоменная полоса над холстом графа (Core не поставляет ни одной). bool AppliesTo(StudioGraphContext) · VisualElement Create(StudioGraphContext) (пересоздаётся при каждой перестройке графа — не храните состояние; null ничего не добавляет)
StudioGraphContextsealed-классТолько для чтения: Tab и FocusRecordId (терминус) · SheetRecord FocusRecord (null, если не разрешено) · Tables · ReferenceIndex References · CodeRegistries. Две выведенные из употребления оси остаются ради совместимости сигнатур и помечены [Obsolete]: ShapeId (всегда "record") и ModeId (всегда пусто). Сравнение с любой из них компилируется и никогда не бывает истинным, поэтому теперь об этом сообщает компилятор, а не остаётся мёртвая ветка — удалите проверку. Нет поверхности подготовки — виджеты только отображают (конструктор internal: окно собирает его)
IStudioCellEditorProviderинтерфейсОтрисовывает одну ячейку сетки для именованного типа. string TypeName (совпадает с именем типа CellParserRegistry или именем wrapper'а, Ordinal; пусто = отказ) · VisualElement CreateEditor(StudioCellEditorContext) — возврат null отклоняет эту ячейку, и её берёт на себя встроенный виджет. Дублирующая заявка на то же имя типа предупреждает и сохраняет первую найденную
StudioCellEditorContextsealed-классЧто получает виджет ячейки: Tab · FieldName · TypeToken Type · CurrentRawText (канонический текст с применёнными подготовленными изменениями) · Action<string> Commit (однократное действие — собственный шаг отмены) · Action<string> CommitTyping (серия нажатий клавиш — объединяется в один шаг на ячейку) · Func<string,IReadOnlyList<string>> ReferenceKeys (те же ключи-кандидаты, что предлагает встроенный пикер). Оба commit-а проходят через контроль подготовки окна (конструктор internal: окно собирает его)
IStudioInspectorActionинтерфейсДополнительная кнопка в инспекторе узла. string LabelKey (ключ Loc; незарегистрированный = отображается дословно, пустой = имя типа) · bool AppliesTo(StudioInspectorContext) · void Execute(StudioInspectorContext)
StudioInspectorContextsealed-классЧтение: Tab · RecordId · SheetRecord Record · Tables · References · CodeRegistries. Опосредованное изменение: Action<string,string,string,string> StageCell · Action<IReadOnlyList<EdgeCellWrite>> StageCells, оба подробно описаны под таблицей. Сервисы: Action<string,int,string> FocusCell · Action RequestRebuild. AuthoringSession намеренно не предоставляется
IStudioPanelProviderинтерфейсПроизвольная панель UIToolkit в правой панели Studio — лазейка рядом с описательным StudioPanelDescriptor. string Id · string TitleKey · bool AppliesTo(StudioSurfaceContext) · VisualElement CreatePanel(StudioSurfaceContext) (null ничего не рисует в этом такте). Зарегистрируйте описательную панель под тем же Id, и каждый хост берёт то, что может нарисовать: редактор предпочитает эту, браузер рисует описательную — так что «насколько далеко заходит браузер, настолько же далеко и редактор» не требует второго контракта. Элемент живёт один такт пересчёта, поэтому не хранит состояние
StudioPaletteстатический классЗначения цвета, отступов и типографики только для чтения, которыми рисует само окно, чтобы смонтированный вами виджет соответствовал окну, а не хардкодил hex-цвета. Каждый слот разрешается во время чтения, поэтому виджеты бесплатно следуют режиму яркости и цветовому пресету. Выбор значений (пресеты, яркость, значения по умолчанию) остаётся internal — виджеты следуют палитре, а не перекрашивают её. Список членов — под таблицей
StudioThemeстатический классВсего четыре члена: CategoryColor(category) (тот же детерминированный тон, что окно даёт этой категории) · Np(text) (безопасная интерполяция в rich-text метку) · Mono / ApplyMono(element) (политика моноширинного шрифта: только ключи, адреса и числа — у моноширинных шрифтов нет глифов CJK). Всё остальное в этом типе — internal
StudioKeyPickerстатический классОдин член: Show(Rect screenAnchor, string targetTab, IReadOnlyList<string> candidates, Action<string> picked, string acceptsLabel = null) — тот же выпадающий список, что открывает встроенная ячейка ссылки, для виджета ячейки, которому нужно достать ключ внутри собственной нотации. Он выбирает один ключ из переданных вами кандидатов и возвращает его; создание записи, оставление ячейки пустой, множественное переключение списка и вопрос о том, какой порт получает выбор, — это собственные правила встроенной ячейки ссылки, поэтому их нет в этом фасаде. picked обязателен (ArgumentNullException до создания какого-либо окна); без кандидатов и без чего предложить он логирует, вместо того чтобы открывать пустой список. Сам тип окна остаётся internal
StudioPluginRegistryстатический классОдин публичный член: InvalidateCache() — сбрасывает кеш обнаружения на время перезагрузки, чтобы проба, которую только что включили ваши собственные тесты, была обнаружена заново (та же любезность, которую уже предлагали PluginRegistry и SourceProviderRegistry; этот реестр был исключением). Обнаруженные списки остаются internal: ничто снаружи не может прочитать или заменить то, что смонтирует окно

StudioInspectorContext — два делегата подготовки:

  • StageCell принимает вкладку, recordId, поле и канонический сырой текст. Окно регистрирует шаг Undo, увеличивает поколение проекции и подготавливает логический адрес.
  • StageCells делает то же самое для нескольких ячеек, которые должны измениться вместе: один нативный шаг Undo, всё или ничего. Если хотя бы одну нельзя подготовить, сессия вообще не затрагивается.

Неудача в любом случае молчалива на экране, и объясняет себя только сам шлюз. Источник только для чтения, уже выполняющийся конвейер или вкладка из книги xlsx записывают причину в консоль. Пустой список, запись без вкладки или поля и ключ записи, не разрешающийся ни в одну строку, ничего не делают и ничего не говорят.

StudioPalette — члены:

  • 33 цветовых слота: Canvas · Panel · Band · Chrome · Surface · Chip · Selection · PendingCell · Line · LineSoft · GridLine · LineHover · Text · TextMuted · TextFaint · RefText · OnAccent · Accent · AccentDim · Warning · Danger · Ok · SheetTone · CodeTone · EditedCell · NewRowCell · NewRowLine · DangerChip · DangerPanel · Scrim · Wire · WireDot · GridDot.
  • IsDark.
  • Отступы: SectionSpace · RowSpace · RuleHeight · ButtonHeight · PrimaryButtonHeight · GlyphWidth.
  • Размеры типографики: HeadingFontSize · SectionFontSize · CaptionFontSize.
  • FromRgb(uint) · ToHex(uint).

Подтверждение отправки (SheetForge.Editor.Push)

ТипРоль
IPushApproverbool Approve(PushPlan, string humanSummary) · bool ApproveStructureRewrite(string, bool hasLiveConflicts) — отказ = ничего не отправляется
AutoPushApproverВсегда подтверждает (для тестов/автоматизации)

Движок авторинга (SheetForge.Editor.Structure / .Pipeline / .Export)

ТипРоль и ключевые члены
AuthoringSessionВладелец подготовленного состояния (сериализуемый — бесплатный Undo + переживание перезагрузки). Edits · IsolatedEdits · NewRows · StructOps · Reorders · TabRenames · EnumMembers (подготовленные добавления членов в листы enum) · AssetRegistrations (подготовленные регистрации Addressables — уровня проекта, поэтому они не участвуют в шлюзах уровня вкладки, но учитываются при входе в отражение, при сбросе и в diff-сводке) · HasAssetRegistrations · StageAssetRegistration(r) (тот же guid, либо та же группа для создания группы, заменяет на месте — побеждает последнее намерение; регистрация без идентичности отклоняется) · RemoveAssetRegistrationsWhere(predicate) · SetStaged · ResolveBaselineEdits · RemapFieldName/RecordId/Tab · StageTabRename · EffectiveStructOps · PendingStructCount · TabNames · TryGetBaselineTable · LastProjectionResult · ClearAll (очищает и регистрации тоже)
AuthoringDispatcherОркестратор отражения. конструктор (session, callbacks, baselines) · Reflect() · BuildProjectionResult() (запрос проекции без побочных эффектов) · IReadOnlyDictionary<string,string> BuildProjectedTabs() (та же проекция в виде TSV на вкладку — то, что цель записи обратно собирается отправить, можно предпросмотреть без записи) · void FinalizeReflectSuccess(IReadOnlyList<string> writtenTabs, IReadOnlyList<TabRenameEntry> committedRenames = null) (финал, которого должна достичь собственная запись обратно источника: сохраняющая обрезка для записанных им вкладок, граница ClearUndo и автоматический повторный импорт — встроенные пути выполняют то же самое приватное тело, поэтому внешний провайдер завершается точно так же, как они; пустой список — это отсутствие операции, сохраняющее подготовленное состояние нетронутым) · Session · Callbacks · Baselines
AuthoringDispatchCallbacks13 общих делегатов для забот представления + IPushApproverResolveSettings · RenderReport (Action<ImportReport>, допускает null) · TriggerReimport · ConfirmKeyRenames · ConfirmTabRenames (допускает null) · ClearUndo · Rebuild · … Встроенные диалоговые делегаты Local/Google вынесены в опциональный набор BuiltInSourceDialogs
BuiltInSourceDialogsОпциональный набор из 14 встроенных диалоговых делегатов источников Local/Google, отдельный от AuthoringDispatchCallbacks — внешним провайдерам они никогда не нужны. NotifyLocalDone принимает пять аргументов; последний — итоговая строка регистрации Addressables для диалога завершения (null, если ничего не было подготовлено)
BaselineStore (.Export)Снимки baseline в виде нормализованного TSV по вкладкам

Типы значений подготовки (SheetForge.Editor.Structure; StagedCellEdit/StagedNewRow находятся в SheetForge.Editor.Windows)

ТипРоль
StagedCellEdit (структура)Одна подготовленная правка — TabName · RowOrdinal · FieldName · RawText · RecordId (логический ключ)
StagedNewRowОдна подготовленная новая строка — TabName · FieldNames · CellTexts
StructureOpОдна операция структуры — Kind · координаты · тексты · перестановка Order
StructureOpKind (enum)AddColumn · RemoveColumn · AddMarker · RemoveMarker · RemoveDataRow · ReorderColumns · ReorderDataRows · RenameColumn · EditColumnType · EditColumnDesc · SetColumnOverlap · SetSheetStyle
TabReorderEntryСостояние изменения порядка по вкладке — Tab · ColOrder · RowOrder
TabRenameEntry (структура)OldName · NewName
StagedEnumMember (структура)Одно подготовленное «добавить этот член в этот enum» — TabName (какой лист enum; пусто = искать во всех) · EnumName · Member. Уровень сессии, а не StructureOp, по той же причине, что и переименование вкладки: у листа enum нет ни таблицы, ни схемы, ни ключевого столбца, поэтому адрес (вкладка, запись, поле) правки ячейки не может назвать «следующий член этого enum». Публичен только потому, что публичен AuthoringSession.EnumMembers (CS0050)
StagedAssetRegistration (структура)Одно подготовленное изменение настроек Addressables проекта, сделанное перетаскиванием или выбором ассета в ячейку AssetRef@GroupStagedAssetRegistrationKind Kind · Guid (ассет; вложенный ассет подготавливает своего родителя) · Group · FromGroup (только для перемещений) · Address (имя файла без расширения для новой записи; уже зарегистрированный ассет сохраняет свой адрес) · AssetPath (для отображения). Фабрики Add(guid, group, address, assetPath) · Move(guid, fromGroup, group, address, assetPath) · CreateGroup(group). Выполняется после успешной записи таблицы, затем очищается. Публичен только потому, что публичен AuthoringSession.AssetRegistrations (CS0050), как и StagedEnumMember
StagedAssetRegistrationKind (enum)Add · Move · CreateGroup
TabBaselineAnchor (структура)TabName · Fingerprint · RecordCount
IsolatedEditПравка с неудачной перепривязкой — Edit · Reason
IsolationReason (enum)Внешнее переименование / внешнее удаление / конфликт ключа

Вспомогательные средства авторинга (SheetForge.Editor.Windows / .Structure)

ТипРоль
KeyRenamePlanner (статический)Планирование переименования ключа + межвкладочного распространения. Plan(…) · вложенный KeyRenamePlan · соседняя структура KeyRename
RecordIdMinter (статический, чистый)Подсказки id. Suggest · DetectCommonPrefix · Uniquify · StagedNewRowKeys
IntIdMinter (статический, чистый)Подсказка следующего IntId для новой записи — Suggest(existingIds)max + 1. Отдельная ось от RecordIdMinter, никогда не повторно использует освободившийся пропуск
ProjectionErrorMapper (статический, чистый)Координата ошибки → логический адрес. TryMap(…) · вложенный LogicalAddress
EphemeralSoApply (статический)Временный оверлей подготовленных значений поверх SO. Apply(…) · InvalidateIndex(…) · вложенные Report / SkipReason / SkippedEdit

Сборка Runtime (SheetForge.Runtime)

autoReferenced — можно использовать из кода игры без ссылки на asmdef.

ТипРоль и ключевые члены
SheetForgeDatabases (статический)Загрузчик времени выполнения — санкционированный путь загрузки. const AddressPrefix = "SheetForge/" · AddressFor(tab) · LoadAsync(tab) · LoadAsync<TDatabase>(tab) · Release(handle) / Release<TDatabase>(db). Хелперы адресов — простые строки, которые компилируются всегда; LoadAsync и Release существуют только под SHEETFORGE_ADDRESSABLES — version-define, устанавливаемым при наличии com.unity.addressables, — именно это позволяет продукту компилироваться без пакета
DefinitionDatabase (абстрактный SO)База каждого сгенерированного Database для вкладки. abstract TabName · abstract Count · virtual IReadOnlyList<object> RecordsUntyped · virtual InvalidateIndex(). RecordsUntyped — это санкционированный способ перечислить запечённую вкладку не зная её сгенерированного типа — второму бейкеру или инспектору, обходящему все вкладки, раньше приходилось использовать reflection для приватного поля records, что превращало имя поля в необъявленный контракт, который молча сломался бы в день, когда генерация кода его переименует. Считайте список доступным только для чтения (таблица канонична). По умолчанию он пуст, поэтому сгенерированный до появления этого члена код всё ещё компилируется и работает; повторный импорт выпускает переопределение
RecordRef (структура)Сериализуемое значение ссылки внутри запечённых SO (строковый id, разрешается при поиске). Id · IsEmpty
IntRef (структура)Сериализуемое значение ссылки по целочисленному ключу внутри запечённых SO — близнец RecordRef для полей IntId@Tab. Поскольку 0 — допустимый id, IsEmpty опирается на бит hasValue. Id · IsEmpty. Генерация кода выводит поле IntId@Tab как IntRef, а TryGet(IntRef) у сгенерированного Database его принимает
LocRef (структура)Сериализуемая ссылка локализации внутри запечённых SO — ячейка LocRef@Tab. Table (вкладка локализации, которая и есть имя коллекции StringTable) · Key · long KeyId (0 означает «ещё не разрешено»: импорт запекает 0, а мост подставляет настоящий id после синхронизации таблиц, так что ссылка переживает переименование ключа) · IsEmpty. Она компилируется всегда — сгенерированный код и запечённые ассеты никогда не содержат тип из пакета локализации, именно это и оставляет пакет необязательным
LocRefExtensions (статический)Единственный член: LocalizedString ToLocalizedString(this LocRef) — он указывает по KeyId, когда тот не 0, и по имени ключа в противном случае, а пустая ссылка превращается в пустой LocalizedString. Он существует только тогда, когда установлен com.unity.localization, под версийным define SHEETFORGE_LOCALIZATION — тот же механизм, что использует SHEETFORGE_ADDRESSABLES для слоя Addressables
SheetForgeRuntimeInfo (статический)const Version

Сгенерированные типы (паттерн — для каждого проекта, не поставляемый API)

Для каждой вкладки Foo генерация кода создаёт в вашем generatedNamespace:

public sealed partial class FooDefinition    // one strongly-typed field per column; @desc → doc/tooltip
public sealed partial class FooDatabase : DefinitionDatabase
{
    // TabName, Count, SchemaFingerprint, Records, RecordsUntyped override,
    // lazy _byId/_byIntId lookups, InvalidateIndex override
}

Загружайте через SheetForgeDatabases.LoadAsync<FooDatabase>("Foo").

Оба класса генерируются как partial, поэтому вы можете добавлять производные члены — вычисляемое свойство, реализацию интерфейса, оператор — в собственном файле рядом со сгенерированным, и повторный импорт его не перезапишет. Одна граница: не добавляйте сериализуемые поля в своей части. Запечённый ScriptableObject перестраивается из таблицы при каждом импорте, поэтому всё, что сериализует только ваша часть, возвращается к значению по умолчанию — если значение принадлежит данным, ему место в столбце. (Ключевое слово partial не затрагивает SchemaFingerprint, который вычисляется только из схемы, поэтому превращение классов в partial не сделало недействительным ни одно существующее запекание.)


Прочие сборки

  • SheetForge.Setup — ни от чего не зависящий бутстрап для случая отсутствия Addressables. Нет публичного API (всё internal; существует, чтобы показать окно с рекомендациями).

  • SheetForge.PluginDemo (один объединённый asmdef + asmdef Demo.Editor; пространство имён содержимого остаётся SheetForge.Skills) — эталонный пакет примера, не API продукта. Он содержит:

    • SkillsPlugin (семь интерфейсов плагина — базовый, валидатор, ребро, шаблон, граф, реестр кода, тема);
    • Modifier + ModifierCellParser (пользовательский тип ячейки), ModifierStatEdgeContributor (поставщик рёбер);
    • ExamplePipelineAugmenter / ExampleReactiveAugmenter (переопределения холста), ExampleCodeAtoms (реестр кода _Refs);
    • ExampleStudioUi (декларативные действия, панель, значок столбца и подсказка редактора ячейки), ExampleImportObserver (наблюдатель конвейера);
    • ExampleStageStripWidget / ExampleInspectorAction / ExampleStudioPanel (точки расширения редактора Data Studio, отрисованные из публичной палитры), ExampleLocStrings (регистрирует эти метки на двух языках — в основной сборке, так что браузер тоже их показывает);
    • декларация SheetForgePluginCompat на уровне сборки;
    • SkillRunner (потребление во время выполнения), сгенерированные типы Example* в пространстве имён по умолчанию SheetForge.Generated (изоляция обеспечивается префиксом Example*, а не отдельным пространством имён).

    Не требующий плагина пример SheetForge.CoreDemo поставляется без единого asmdef (компилируется в Assembly-CSharp).

Похожие страницы