Форматы изображений и спрайтов
FOnline запекает RGBA/legacy-кадры и наборы .fofrm в версионированные
RGBA/mesh-контейнеры для клиентских атласов AtlasSprite/SpriteSheet.
Точные контракты: справочник изображений, каноническая JSON-модель.
Область действия и источник истины
BuildTools/ImageFormatInterface.json ведёт source-anchored контракты импорта,
рецептов, зависимостей, mesh и runtime. BuildTools/docs_image_format.py
проверяет их и строит справочник; обновляйте оба при изменении поведения.
ImageBaker::AddLoader использует const ImageImport::Context&: читайте
*context.Files, разрешайте вложение через context.Resolve(path), объявляйте
переименованные выходы через ResolveOutput, вспомогательные чтения через
dependency discovery. Типы кадров находятся в ImageImport; проект владеет
художественной политикой, настройкой движения и визуальной приёмкой.
Выбор исходного формата
| Задача | Предпочтительный источник | Примечания |
|---|---|---|
| Статическое изображение/прозрачный спрайт | PNG | Авторский lossless-вход; палитра, grayscale малой разрядности, tRNS, 16-битные каналы нормализуются в RGBA8. |
| Существующий TrueColor-выход | TGA | Type 2/10, 24/32 bpp, без image ID, начало снизу слева. |
| Многокадровый/направленный спрайт | FOFRM со ссылками на PNG/TGA | Проверяемые композиция, смещения, дельты кадров, размер и тайминг. |
| Существующий ресурс Fallout | FRM или FR0 | Нужны права распространения и визуальные проверки регрессий. |
| Существующий ресурс Arcanum/Tactics | FOFRM со ссылками на ART/SPR | Параметры выбирают палитры/кадры/отражения/цвета/последовательности; SPR оборачивайте для runtime. |
| Существующий ресурс Infinity Engine | ZAR/TIL/MOS/BAM; FOFRM для выбора | Путь импорта; для новой графики предпочитайте PNG. |
Встроенный image baker не поддерживает JPEG, BMP, GIF, DDS, WebP, AVIF и SVG;
преобразуйте в PNG/поддерживаемый TGA. Возможности renderer/библиотеки не расширяют
контракт ImageBaker/runtime SpriteFactory.
Обзор конвейера
- Смонтированные исходники образуют граф до выбора корней фильтрами выходов.
- Загрузчики строят
FrameCollection; mesh дополняет/обрезает RGBA и находит привязки. - Публикуются корневые контейнеры и
SpriteInfo/<PackName>.foinfo. ResourceManagerпередаёт запечённые байты atlas-спрайтам илиSpriteSheet.
Штатный клиент не запускает исходные декодеры. Запечённый Sprite.png содержит
контейнер Engine; расширение выбирает загрузчик, а не формат нагрузки.
Зависимости, выпуск и инкрементальная выпечка
Входы FOFRM доступны resolver, даже когда шаблоны пакета исключают их самостоятельные выходы. Логические исходники разрешаются через смонтированный каталог и overlay-победителей. План корней подавляет поглощённые кандидаты; полный Master bake и on-demand lookup также сохраняют самостоятельных кандидатов для отдельной игровой ссылки или текстуры модели. Наличие в локальном кеше и включение в поставку — отдельные решения.
Resources.usage.json выбирает поставляемые выходы. У сплющенного FOFRM нет
runtime-зависимости от входного PNG или промежуточного FOFRM: их копии исключаются
при отсутствии самостоятельной ссылки. Для разных преобразований по-прежнему
полезны отдельные корневые обёртки. RawCopy уступает владение изображениям.
Загрузчик с другим NewName заранее объявляет этот путь через ResolveOutput.
Граф использует общий native-парсер ImageRecipe для Frames с кавычками и
учитывает палитры FRM, направления FRX и отсутствие необязательных файлов.
Отсутствующие входы, циклы и глубина более 64 FOFRM-узлов дают ошибку с цепочкой.
Параметры имени относятся к ссылкам, а не к отдельным физическим файлам.
BLAKE2b-отпечатки включают транзитивное содержимое, пути и победителей mount,
отсутствие необязательных файлов, рецепт/options, версии сборки и baking-контракта
и настройки SpriteMesh. Смена байтов определяется при прежних размере и mtime.
Актуальные корни регистрируются в output manifest, поэтому инкрементальная
выпечка сохраняет очистку устаревших выходов. Изменение зависимости не требует
touch дескриптора или принудительной выпечки.
Успешные snapshots и отдельные SpriteInfo entries хранятся в
.baker-cache/Image/<PackName>/; это приватные файлы, не входящие в поставку.
Отсутствующий или повреждённый snapshot вызывает конвертацию. Новые snapshots
публикуются после успешных записей выходов. По актуальным entries общий индекс
SpriteInfo восстанавливается без декодирования неизменившихся пикселей.
Отложенный reindex использует тот же граф и отпечатки, проверяя также пакет,
который объявил выход, чтобы старый overlay-файл не возвращался. Эти правила
baker не очищают уже загруженный клиентский кэш спрайтов.
Грамматика FOFRM
FOFRM использует ConfigFile. Имена регистрозависимы: Source, Fps, Offset,
Frame, Frames, FrameOffsets, Size, FrameSizes.
Корень — направление 0. Hex: [HexDir 1]..[HexDir 5]; square:
[SquareDir 1]..[SquareDir 7]. Используйте точные имена с одним пробелом и индексы,
а не градусы; именованный ноль и старые Dir запрещены.
Имена проверяются до Source/кадров. Диагностика старых имён отмечена
FO_TEMPORARY_COMPAT(FofrmLegacyDescriptor, "2026-12-31"); fallback нет.
Авторская запись: Key = Value. Пробел и \ продолжают логическую строку;
в Frames пишите по одной ссылке на физическую строку, последнюю без \.
Alias целого источника
Source = Actor$r=3.art
Source наследует относительный бинарный источник или FOFRM, сохраняя все
направления, смещения, тайминг и движение. Корневые преобразования действуют
на все направления; именованные разделы переопределяют существующие направления.
Offset прибавляется к смещению исходной последовательности. Source исключает
Frame/Frames; старый Alias отвергается с маркером
FO_TEMPORARY_COMPAT(FofrmWholeCollectionSource, "2026-12-31").
Минимальное статическое изображение
Frame = Icon.png
Frame — один полный путь, Frames — непустой массив String парсера AnyData. Выберите один ключ; пути с пробелами в Frames берите в кавычки, повторы сохраняйте. Число ссылок вычисляется автоматически, ключа Count нет. Fps по умолчанию 10; пути относительны дескриптору.
Frames = \
"Idle 00.png" \
Idle_01.png \
Idle_02.png
Fps = 8
Размещение последовательности и кадров
Offset: знаковые int32 X Y, изначально ноль, переносится из корня/предыдущего направления. FrameOffsets: одна int32 X Y на локальную ссылку до разворачивания; без поля ноль, без наследования. Пустые/неверные пары, переполнение, неверное число или отсутствие ссылок запрещены.
Frames = \
A.png \
B.png
Offset = -24 -63
FrameOffsets = \
2 -1 \
0 3
FrameOffsets: массив String парсера AnyData, строгие целые, одна пара на
продолженную строку. Все кадры ссылки получают Offset + FrameOffsets[i] плюс
дочернее покадровое размещение без накопления. Импортированные Motion прежние
(root motion); NextX_N/NextY_N запрещены до Source.
Физический размер кадров
Size изменяет точные размеры без сохранения пропорций:
Frame = Icon.png
Size = 64 48
Оси Size/FrameSizes — строгие целые AnyData в 1..65535. FrameSizes =
одна пара W H на ссылку. Корневые общие значения служат умолчанием направлениям;
локальные массивы заменяют их. Общая и массивная формы в одной секции запрещены.
Source считается одной ссылкой и применяет умолчания ко всем сохранённым ракурсам.
| Операция | Ключи и значения |
|---|---|
| Входная последовательность | InputDir / FrameInputDirs: существующее направление; явный выбор корневого Source оставляет одну последовательность. |
| Обрезка, затем сетка | Crop / FrameCrops: X Y W H внутри исходника. Grid: клетки W H без остатка, слева направо и сверху вниз. |
| Отражение, затем поворот | Flip / FrameFlips: None, X, Y, XY. Rotate / FrameRotations: 0, 90, 180, 270 по часовой стрелке. |
| Resize, затем холст | Size / FrameSizes; Canvas / FrameCanvases: W H. CanvasOffset / FrameCanvasOffsets: неотрицательные X Y от левого верхнего угла, по умолчанию 0 0; обрезание запрещено. |
| Разворачивание, затем выбор | FrameIndices: непустые индексы AnyData; порядок и повторы разрешены, выход за границы запрещён. Source задаёт умолчание всем ракурсам. |
| Движение | Motion / FrameMotions: пара int16 X Y заменяет импортированное движение; отсутствие сохраняет его. |
| Фильтрация | Resample: Nearest, Bilinear (по умолчанию), Area (уменьшение/равный размер). PixelUsage: Color (по умолчанию), Data, Normal. ColorSpace: Encoded (по умолчанию), Linear; только для Color. |
Каждый Frame-массив содержит одну запись на исходную ссылку, до grid/разворачивания. Пиксельные операции сохраняют заданные Offset/FrameOffsets и движение. Стандартный Bilinear использует Q16-центры и premultiplied alpha; Linear — фиксированную sRGB16. Data фильтрует каналы независимо, Normal нормализует RGB и заменяет ноль на +Z. Data/Normal отключают alpha mesh/crop, включая владельцев общих пикселей, чтобы сохранить каналы вне видимой alpha. Nearest/равный размер сохраняют байты. Точная арифметика и проверки — в справочнике FOFRM.
Наборы направлений
Задавайте одну последовательность либо полную таблицу направлений. Число кадров и тайминги могут различаться. Frame/Frames отвергает пропуски; Source позволяет локально переопределять существующие направления.
Frames = \
Walk_NE_00.png \
Walk_NE_01.png
Offset = -24 -63
Fps = 10
[HexDir 1]
Frames = \
Walk_E_00.png \
Walk_E_01.png
# Continue every configured map direction.
Вложенные ссылки и разворачивание
Frame/Frames принимают зарегистрированные расширения и параметры $.
Композиция добавляет кадры Main, сохраняя покадровое размещение, но отбрасывая дочерние направления и смещения
последовательности. Shared-ссылки проверяются и материализуются до композиции и преобразования пикселей.
Frames = \
FirstCycle.bam \
SecondCycle.bam
Fps = 10
Без явного тайминга Frame/Frames назначает 100 мс каждому итоговому кадру; Source сохраняет исходную шкалу. Duration задаёт общую длительность в мс, FrameDurations — положительную длительность каждого итогового кадра. В одной секции они взаимоисключены с Fps. Корневые Duration/Fps — умолчания, локальный тайминг приоритетнее; FrameDurations не наследуется. В направлении 1..65535 кадров, сумма длительностей — положительный uint32. Duration не меньше числа кадров; целочисленное деление границ сохраняет сумму. Fps положителен и допустим только в корне. Точные проверки приведены в справочнике.
Legacy-ключ Effect
Effect отклоняется до разрешения входов, с маркером
FO_TEMPORARY_COMPAT(FofrmRetiredEffect, "2026-12-31").
Эффект выбирает потребитель через рендерер/прототип/GUI/скрипт.
Устаревшие параметры имени файла
LoadAny удаляет параметры $ перед физическим поиском. ART выбирает палитры,
кадры, диапазоны, ротации и отражения; SPR — именованные последовательности и
направления; BAM — цикл/кадр. Умолчания, ограничение диапазонов, размещение холста
и нормализацию времени описывают параметры имени
и справочник форматов. После импорта
проверьте движение и темп. Стандартная runtime-factory не регистрирует .spr.
ART
Параметры $F, $r=, палитры и отражения описаны в справочнике.
SPR
Выберите именованную последовательность и направление перед композицией FOFRM.
BAM
Выберите цикл/кадр; неверный selector заменяется нулём.
Подробности исходных форматов
PNG
PNG преобразует palette/grayscale, tRNS, 16-битные каналы и отсутствующий alpha
в один кадр RGBA8; повреждение обрабатывается libpng. Точную нормализацию ведёт
справочник исходных форматов.
Политика управления цветом задаётся проектом явно.
TGA
Используйте raw/RLE TrueColor type 2/10, 24/32-bpp, без image ID и с origin снизу слева. Другие типы/разрядность запрещены; importer не учитывает origin bit и не пропускает ID. Предпочитайте PNG без проверенного TGA preset экспортёра. См. справочник исходных форматов.
Исходные размеры — unsigned 16-bit значения, расширяемые до int32_t, включая
значения выше 32767. Число байтов и доступные данные проверяются до выделения памяти.
Обрезанные пакеты и run-пакеты, превышающие оставшуюся часть изображения, отвергаются.
Прежнее поведение последнего raw-пакета сохраняется: полностью потребить его
закодированные данные и оставить только недостающие изображению пиксели.
Fallout FRM и FR0
Палитры FRM/FR0, анимированные цвета, разделённые направления и имена выходов описаны в справочнике исходных форматов. После импорта проверяйте направления, root motion и темп; вспомогательные файлы входят в граф зависимостей.
RIX, ZAR, TIL, MOS и BAM
Compatibility-импортеры сохраняют свои правила палитр, сжатия, прозрачности и тайминга; см. справочник исходных форматов. Для новой графики используйте PNG и FOFRM.
Граница запечённого контейнера
Приватный поток версионируется между ImageBaker и ReadSpriteResource.
Framing, concrete/shared RGBA records, offsets, движение и mesh описаны в
справочнике baking. Скрипты проекта
и внешние инструменты используют исходные форматы вместо чтения или создания
этого потока. После изменения layout пересоберите согласованные binaries и packs.
Runtime-загрузка, atlas и caches
SpriteSheet предоставляет GetCurrentSprite, GetSprite, GetDirection,
GetDirectionCount, GetStateAnimation, GetActionAnimation и
GetSpriteOffset(frame) и GetSpriteMotion(). Смена направления использует виртуальный интерфейс
Sprite::SetDirection, также реализованный спрайтами моделей и частиц.
ResourceManager приводит расширение пути к нижнему регистру и выбирает
зарегистрированную SpriteFactory. Стандартная factory передаёт полный диапазон
байтов в ReadSpriteResource, который проверяет magic, version, records, mesh
geometry, footer и trailing data. Затем factory проверяет инвариант одного или
полного набора направлений.
Ресурс с одним кадром и одним направлением становится AtlasSprite. Его
запечённый draw offset задаёт размещение спрайта;
сериализованные Motion читаются, но игнорируются. Многокадровый или
направленный ресурс становится SpriteSheet. Каждое направление владеет
параллельным sheet, а каждый concrete/shared кадр сохраняет отдельное смещение в
_sprOffset.
Общие обрезанные кадры сохраняют поправку на исходный холст из изображения, на которое ссылаются, и собственную дельту размещения. Общие пиксели не объединяют метаданные размещения и движения.
SpriteSheet поддерживает Prewarm, loop/reverse и смену направлений с сохранением
фазы; Play игнорирует один кадр. GetDuration/GetFrameDurations и границы кадров
используют timespan, сохраняя доли мс. FrameShot, SpriteFrameInfo и декодированные
кадры используют timespan Duration/GetDuration. GetSpriteDurationMilliseconds требует
целые положительные uint32 мс на записи; legacy-границы и layout файлов прежние.
Явные native-конструкторы и Game.CreateSpriteSequence принимают нулевую длительность для ручного выбора кадров. Такие последовательности не проигрываются автоматически; SetTime выбирает кадр по нормализованному индексу. Таймлайн должен быть целиком нулевым или целиком положительным. FOFRM и запечённые ресурсы по-прежнему требуют положительную длительность каждого кадра.
Конкретные RGBA-кадры размещаются в запрошенном AtlasType. Factory требует
положительные размеры, загружает изображение, дублирует однопиксельные края для
linear filtering и создаёт hit mask из alpha через Settings.SpriteHitValue.
Тип атласа также входит в ключ cache копируемых спрайтов, поэтому один путь
может иметь отдельные экземпляры interface/map/one-image.
При SpriteMesh.Enabled ImageBaker считает alpha > AlphaThreshold видимой
маской, ищет кандидаты до MaxTriangles и через AreaSavingsWeight оценивает
сэкономленную площадь исходного кадра относительно отправляемых треугольников.
Каждый выбранный mesh должен покрывать все видимые pixel cells. Недопустимые или
невыгодные кандидаты сохраняют обычный quad; пустая маска записывает явную пустую
геометрию. Mesh frames могут использовать обрезанный или немного дополненный
texture canvas, но их сериализованные offset, логический размер источника и
source origin сохраняют размещение, scaling, интерполяцию map light и координаты
hit-test.
Baker проверяет всю группу SpriteMesh.*, даже когда генерация mesh отключена.
Поэтому standalone-конфиги проекта должны объявлять положительный
MaxTriangles, AlphaThreshold в 0..254 и конечный неотрицательный
AreaSavingsWeight; конфиг минимального проекта
показывает явные стандартные значения для отключённого режима.
Обычные полноразмерные draw спрайта отправляют запечённый индексированный список треугольников. Region crops, tiled patterns, padded custom-effect/outline draws, fonts, blits, runtime model sprites и particles продолжают использовать прямоугольные пути. Точное поведение draw и dump атласа описано в Frontend и рендеринг, а политика кандидатов и поля baking report — в Baking Pipeline.
SpriteInfo/<PackName>.foinfo версии 2 хранит число кадров по направлениям,
покадровые длительности, границы и offsets. Shared объединяет только пиксели;
каждый логический кадр владеет временем, размещением и движением. Общий
EngineMetadata загружает его на server и client без декодирования RGBA payload.
Baker поддерживает индекс по snapshots актуальных выходов; отсутствующий индекс
восстанавливается обычной или отложенной выпечкой.
Каждая copyable load, включая первую, возвращает MakeCopy(); cache сохраняет
factory prototype. Копии SpriteSheet владеют playback и таблицами кадров,
начинают с нулевого кадра/направления, корректных размера/привязки и сохраняют
state/action tags. AtlasSprite::MakeCopy() разделяет atlas pixels/geometry.
Созданные листы сохраняют исходные общие кадры AtlasSprite; независимые абсолютные
смещения отрисовки хранятся в SpriteSheet::_sprOffset отдельно от таблицы покадровых дельт _sprMotion.
Копии сохраняют обе таблицы. Спрайты карты используют выбранную опору отрисовки,
не добавляя её в накопленный motion, позицию света или логическую опору в мире.
Усечение не сокращает следующие загрузки: каждое направление содержит один
спрайт и offset. Отсутствующие файлы/расширения,
неизвестные factories и ошибки загрузки отдельно мемоизируются по пути в
_nonFoundSprites. CleanupSpriteCache() не очищает этот набор. После обновления источника явный вызов ResourceManager::ForgetFailedSprite или
InvalidateSpriteResource разрешает следующую попытку загрузки того же пути.
После FreeSprite именованные скриптовые handles переиспользуют ресурсы по имени/атласу.
При выгрузке карты клиент удаляет эти неактивные handles перед очисткой кешей спрайтов
и атласов; активные скриптовые handles сохраняют свои кадры.
Handle удаляется до Stop. Исключение остановки не оставляет освобождённый экземпляр
в таблице активных handles; прямой вызывающий получает исходное исключение.
Скриптовые 2D-анимации криттеров
Проект передаёт handle через Game.OnCritterAnimationSprite и определяет имена, опоры,
первый/последний кадр и склейку. Движок кеширует независимую последовательность; импорт FRM
и общие замены отделены. Общие getter читают число кадров/направлений, длительность, опорные
смещения и перемещения; Game.CreateSpriteSequence создаёт явно заданные массивы по
направлениям. Неявных правил Fallout нет. Миграция
описывает удалённые события, оба backend, массивы, владение, длительности, ошибки, проверки и откат.
Практики авторинга
- Предпочитайте PNG, явные ключи FOFRM и ссылки на одиночные кадры. Преобразуйте неоднозначный/неподдерживаемый TGA; храните lowercase-расширения и верный регистр путей.
- Одна анимация на дескриптор; вложенность усложняет flattening и тайминг.
- Порядок: Frame/Frames, Size/FrameSizes, Offset, FrameOffsets, метаданные; продолжения начинайте с одного пробела. Runtime допускает другой порядок/отступы.
- FrameOffsets меняет размещение; импортированные Motion задают root motion представления. Проверяйте визуально оба; движение/коллизии они не задают.
- Оборачивайте SPR, если нет проектной factory; изучите generated options и native fixtures перед изменением селекторов.
- Распространяйте assets/palettes с разрешением и проектными сведениями о происхождении.
- Проверяйте визуально размеры, прозрачные поля, filtering, hit masks, направления, частоту и поведение при старте/остановке.
- После изменения кода контейнера/mesh policy пересоберите baker; отпечатки зависимостей учитывают настройки SpriteMesh. Изучите BakingReport.json и Game.DumpAtlases() при изменении triangle cost, padding, crop или fallback.
Диагностика
Сначала проверьте путь ресурса, пакет и usage manifest: самостоятельный вход
поставляется при отдельной ссылке. Ссылки FOFRM разрешаются от каталога дескриптора,
параметры $ удаляются перед физическим поиском. Отказы грамматики, зависимостей,
направлений, пикселей и тайминга описаны в проверках.
Повтор после missing-cache, alpha/hit area атласа, origin TGA и привязки направлений разобраны в разделах выше. Однокадровая коллекция не проигрывается; файловым таймлайнам нужны положительные длительности без общего целочисленного периода кадра. Явные native/script-последовательности с нулевой длительностью поддерживают ручной выбор кадров.
Ошибки всех зарегистрированных image loaders передаются как Image import failed с физическим путём источника, параметрами имени, размером входа и исходным исключением. Это относится и к FOFRM Source, и к вложенным ссылкам Frame; каждый уровень сохраняет свой контекст. Ошибки FileReader также содержат позицию, запрошенный размер и границы буфера. Загрузчики не добавляют записей в лог.
Во время scan независимые ошибки изображений журналируются как
Image baking error, а после завершения всей выбранной работы baker выбрасывает
одно агрегированное исключение Errors during images baking. Исправьте каждый
исходный файл: агрегированное число не является первопричиной.
Порядок проверки
Для изменений документации/модели:
python BuildTools\docs_image_format.py --write
python BuildTools\docs_image_format.py --check
python -m unittest BuildTools.tests.test_docs_image_format
python BuildTools\docs_contract_diff.py --help
python BuildTools\docs_validate.py
Для изменений importer, container, atlas или playback запустите focused native
image-baker и texture-atlas coverage через настроенную цель RunUnitTests.
Test_ImageBaker.cpp покрывает targeted/scan baking, поведение BakeChecker,
PNG/TGA, каждый legacy importer, options, flattening/directions FOFRM, shared
records, переименование выхода и повреждённые входы. Test_TextureAtlas.cpp
покрывает split/search/free allocator.
Затем проверьте затронутый встраиваемый проект:
- Перегенерируйте image-format model/reference и просмотрите агрегированный
diff контракта
image-format. - Перезапеките затронутые ресурсы закреплённой ревизией Engine проекта.
- Запустите узкие project resource/prototype checks, разрешающие эти пути.
- Запустите видимую клиентскую сцену, использующую каждое изменённое изображение, анимацию, направление, отражение, alpha edge, hit area и поддерживаемый renderer/profile.
- Для locomotion offsets также следуйте Sprite Root Motion и проверьте прямое движение, повороты, смену направления и переходы stop/start.
Native tests доказывают инварианты декодирования и контейнера. Они не доказывают framing графики проекта, приоритет resource pack, визуальный темп, filtering, clickability или воспринимаемое скольжение ног.
Checklist изменения
При изменении image surface:
- обновите
BuildTools/ImageFormatInterface.jsonи это руководство в одной правке Engine; - перегенерируйте
Docs/generated/image-format.jsonи все generated image-страницы; - запустите
BuildTools/tests/test_docs_image_format.py, полный documentation suite иdocs_contract_diff.pyотносительно требуемой базы; - запустите focused native tests затронутой границы loader/runtime/atlas;
- обновляйте Baking Pipeline, Client Runtime или Sprite Root Motion, только когда меняется принадлежащее им поведение;
- обновляйте документацию встраиваемого проекта только для конкретных assets, policy, integration и изменений видимой проверки;
- закрепляйте public examples на точной ревизии Engine и не обещайте поддержку формата или option, которую не исполняет их validation route.
Состав importers и native-расширения
PNG/TGA/FOFRM обязательны. Другие importers требуют отдельных FO_IMAGE_* опций. Известный выключенный вход, включая nested FOFRM, сообщает путь и опцию. Соседние ImageBaker-*.h/.cpp закрывают палитры/helpers вместе; ImageBaker-ZarDecoder разделяют ZAR/TIL при включении любого из них.
Native callbacks используют ImageImport::FrameShot, FrameSequence, FrameCollection, LoadFunc и (string_view name, string_view options, FileReader reader, const ImageImport::Context& context). context.Files предоставляет соседние assets, context.Resolve(path) — nesting, третий аргумент AddLoader — выходное имя. Scheduling, meshes и serialization остаются у координатора. Stock client читает baked containers без source-декодеров; runtime extensions/container version сохраняются.
FrameCollection::Main содержит нулевое направление; Dirs — Engine
array<FrameSequence, MAX_DIRS_MINUS_ONE> из семи дополнительных последовательностей
в порядке направлений, изначально пустых. При индексации знаковым ненулевым
направлением используйте numeric_cast<size_t>(direction - 1).
Обход диапазона и ссылки на элементы сохраняют смысл. Собственные loader,
полагавшиеся на неявное преобразование C-массива в указатель, должны передавать
Dirs.data() только на конечной границе внешнего API либо использовать span
как представление с размером. См. запись миграции.
Кадр native-импорта содержит isize32 Size, независимую привязку ipos32 Offset
и покадровую дельту движения анимации ipos32 Motion, накапливаемую при проигрывании. Дельты FRM/FRx и DeltaX/DeltaY
ART заполняют Motion. Знаковые центры BAM и расчёт BBox/центра SPR заполняют Offset,
включая повторные/shared-кадры; движения из этих координат не выводятся.
Преобразования изображения сохраняют привязку и движение в заданных пикселях.
SpriteResource v3 сохраняет размеры uint16 и движение int16; baker проверяет
диапазоны перед записью. Пользовательские native-загрузчики должны заменить
прежние скалярные поля. FOFRM использует Motion/FrameMotions; Move/FrameMoves
отклоняются до разрешения Source.