FOnline Engine
Current 2026.1.118-dev GitHub
Документация Docs/ru/how-to/content/image-format.md

Форматы изображений и спрайтов

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.

Обзор конвейера

  1. Смонтированные исходники образуют граф до выбора корней фильтрами выходов.
  2. Загрузчики строят FrameCollection; mesh дополняет/обрезает RGBA и находит привязки.
  3. Публикуются корневые контейнеры и SpriteInfo/<PackName>.foinfo.
  4. 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, массивы, владение, длительности, ошибки, проверки и откат.

Практики авторинга

  1. Предпочитайте PNG, явные ключи FOFRM и ссылки на одиночные кадры. Преобразуйте неоднозначный/неподдерживаемый TGA; храните lowercase-расширения и верный регистр путей.
  2. Одна анимация на дескриптор; вложенность усложняет flattening и тайминг.
  3. Порядок: Frame/Frames, Size/FrameSizes, Offset, FrameOffsets, метаданные; продолжения начинайте с одного пробела. Runtime допускает другой порядок/отступы.
  4. FrameOffsets меняет размещение; импортированные Motion задают root motion представления. Проверяйте визуально оба; движение/коллизии они не задают.
  5. Оборачивайте SPR, если нет проектной factory; изучите generated options и native fixtures перед изменением селекторов.
  6. Распространяйте assets/palettes с разрешением и проектными сведениями о происхождении.
  7. Проверяйте визуально размеры, прозрачные поля, filtering, hit masks, направления, частоту и поведение при старте/остановке.
  8. После изменения кода контейнера/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.

Затем проверьте затронутый встраиваемый проект:

  1. Перегенерируйте image-format model/reference и просмотрите агрегированный diff контракта image-format.
  2. Перезапеките затронутые ресурсы закреплённой ревизией Engine проекта.
  3. Запустите узкие project resource/prototype checks, разрешающие эти пути.
  4. Запустите видимую клиентскую сцену, использующую каждое изменённое изображение, анимацию, направление, отражение, alpha edge, hit area и поддерживаемый renderer/profile.
  5. Для 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.

Введите запрос.