Технические примечания временного рефактора Секвенсора

0
3
Технические примечания временного рефактора Секвенсора
В версии 4.20 UE4 были внесены существенные изменения в способ представления времени в Sequencer. Это было сделано для лучшей поддержки кинематографических систем передач и контекстов, где точность кадра имеет огромное значение. На этой странице описаны концептуальные изменения высокого уровня, а также подробные изменения кода C++ для целей обновления.

Что изменилось?

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

Способ интерпретации этих тиков определяется на уровне каждой последовательности с помощью Tick Resolution в секвенсоре, которое определяет количество тиков в секунду. Используя этот механизм, пользователь контролирует, насколько детальными могут быть данные секвенсора. Например, для приложений реального времени, где точность кадров менее важна, можно выбрать очень высокое разрешение, тогда как Master Sequence для визуализированного кинематографического объекта может выбрать фактическую желаемую частоту кадров для проекта.

Этот подход обеспечивает большую гибкость для Sequencer в различных контекстах без ущерба для надежности или производительности. По умолчанию контент, созданный до 4.20, будет обновлен с разрешением тика 60 000 кадров в секунду, которое охватывает все общие частоты кадров, кроме 23.976 (NTSC). По умолчанию для новых последовательностей разрешение по тикам будет равно 24, 000, что охватывает все обычные целые числа, а также 23.976 (NTSC). 

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

  • MovieScene.LegacyConversionFrameRate (По умолчанию: 60000 кадров в секунду)
    • Задает разрешение кадра по умолчанию для данных UMovieScene, сохраненных до 4.20. 
    • Не влияет на активы, (пере)сохраненные с 4.20+.
  • LevelSequence.DefaultTickResolution (По умолчанию: 24000 кадров в секунду)
    • Задает разрешение по умолчанию для вновь создаваемых последовательностей уровней.
  • LevelSequence.DefaultDisplayRate (По умолчанию: 30 кадров в секунду)
    • Определяет частоту кадров отображения по умолчанию для вновь созданных последовательностей уровней; также определяет частоту кадров с блокировкой кадров, где для последовательностей установлены блокировки по кадрам.

Имейте в виду, что Sequencer по-прежнему поддерживает оценку данных ключевых кадров с использованием подкадра с плавающей запятой, что означает, что мы все еще можем выполнять плавную интерполяцию во время выполнения даже для последовательностей с очень низким разрешением тиков. Только границы раздела и сами ключевые кадры ограничены разрешением галочки.

Вся информация о времени для данной последовательности теперь находится в раскрывающемся меню Display Rate на панели инструментов секвенсора, где во всплывающей подсказке описывается разрешение тиков текущей последовательности:Технические примечания временного рефактора Секвенсора

Это меню позволяет вам изменить частоту кадров дисплея, режим отображения времени и тип оценки. Общие показатели отображения, которые совместимы с разрешением тиков текущей последовательности, отображаются на верхнем уровне. 

Можно отображать с использованием частоты кадров, которая несовместима с разрешением тиков, но это не рекомендуется.

После создания можно изменить разрешение тиков последовательности, но имейте в виду, что преобразование последовательности в разрешение тиков, не кратное его текущему разрешению, может привести к тому, что границы раздела и ключи будут округлены до нового разрешения, что может быть найдены в меню Advanced Options.меню Advanced Options ue4

Примечания к обновлению C++

Для поддержки нового формата времени потребовалась большая доработка многих внутренних классов Sequencer и MovieScene и структур данных. Учитывая размер и масштаб изменений, было невозможно обеспечить изящный путь устаревания для некоторых API.

В этом разделе подробно объясняются основные изменения и приводится пример миграции кода с 4.19 на 4.20.

Изменения и Дополнения

  • Модуль TimeManagement: предоставляет общие связанные со временем структуры данных и утилиты манипулирования и обработки:
КодОписание
FFrameNumber

(32 bits)

32-разрядное целое число, в основном используемое для представления бесконтекстного тика или номера кадра. Не поддерживает преобразование из любого другого числового типа, кроме int32.
FFrameTime

(64 bits)

Представление времени, содержащее номер контекста без контекста и подкадр с плавающей запятой. В основном используется во время оценки.
FFrameRate

(64 bits)

Дробная частота кадров хранится в виде интегрального числителя и знаменателя (кадры / секунды).
FQualifiedFrameTime

(128 bits)

Композиция FFrameTime и FFrameRate, которая позволяет удобно конвертировать в / из секунд значения и другие частоты кадров.
FTimecode

(20 bytes)

Представление временного кода, содержащее целые числа для часов, минут, секунд и кадров, включая логический флажок для временного кода пропускаемого кадра / без пропуска

Данные MovieScene: UMovieScene теперь содержит разрешение тика и частоту отображения, а также поддерживает предыдущую оценку «Force Fixed Frame Interval» с помощью перечисления типа оценки. Известные изменения в API UMovieScene включают в себя:

КодОписание
UMovieScene::GetEvaluationType()Получает перечисление, определяющее, как оценить эту последовательность:

КодОписание
WithSubFrames (default)Оценка с использованием субкадровой интерполяции
FrameLockedПривязка к последовательности DisplayRate, оценка только номера круглых кадров, без подкадров, установка t.maxfps во время оценки.
UMovieScene::GetTickResolution()Извлекает разрешение тика, с которымFFrameNumbers следует интерпретировать все в пределах этой сцены фильма (если не указано иное)
UMovieScene::GetDisplayRate()Извлекает частоту кадров, которую пользовательский интерфейс, узлы Blueprint и игроки последовательности используют для взаимодействия с этой последовательностью. Также определяет t.maxfps и заблокированную частоту кадров, когда для EvaluationType установлено значение FrameLocked.

Все данные сцены фильма, относящиеся ко времени, были преобразованы в использование FFrameNumber в соответствии с разрешением галочки владельца UMovieScene. Это включает:

    • UMovieSceneSection диапазонов. Диапазоны разделов теперь выставляются исключительно как TRange<FFrameNumber>. Этот диапазон теперь также подразумевает бесконечные верхние или нижние границы и устраняет необходимость в отдельном флаге IsInfinite. Разделы, которые поддерживают бесконечные диапазоны, теперь могут иметь bSupportsInfiniteRange значение true.
    • UMovieScene диапазоны воспроизведения и выбора. И включающие, и исключительные верхние и нижние границы теперь корректно обрабатываются.
    • Суммы до / после ролла
    • UMovieSceneSubSection начальные смещения (в тиковом разрешении внутренней последовательности)
  • Данные Кривой: Все существующие классы кривых (например,FRichCurve, FIntegralCurve, FNameCurve) заменяется внутренне новыми типами каналов, которые работают по времени FFrameNumber во владеющем разрешении UMovieScene, а не плавающего значения. Обратная совместимость с представлениями времени с плавающей запятой невозможна из-за несоответствия типов времени. Поддерживается автоматическое обновление с устаревших аналогов SerializeFromMismatchedTag с использованием устаревшего разрешения для отметки обновления, как описано выше.
  • FRichCurve становится FMovieSceneFloatChannel
  • FIntegralCurve становится FMovieSceneIntegerChannel
  • FStringCurve становится FMovieSceneStringChannel
  • FNameCurve больше не используется внутри
  • Были добавлены FMovieSceneByteChannel (включая перечисления) FMovieSceneBoolChannel 

Пользовательские типы данных кривой, которые ранее использовались TCurveInterface, должны легко переходить на новую модель FMovieSceneXYZChannel, если они предоставляют метод TMovieSceneChannelData<> GetData().

Каналы сцены фильма

Учитывая необходимые критические изменения данных кривой (теперь называемые каналом), была также использована возможность унифицировать несколько путей кода редактора и уменьшить дублирование для секций, которые поддерживают ключевые кадры. Был добавлен новый тип FMovieSceneChannelProxy, который предоставляет редактору и исполняемому коду общий язык для взаимодействия с ключевыми кадрами и управления ими.

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

В этой новой системе есть несколько компонентов с немного другим подходом к настройке редактора:

FMovieSceneChannelProxy

Сохранено UMovieSceneSection: производные типы должны заполнять эту структуру всеми ее каналами, как в примере ниже. Каналы хранятся по своей базе FMovieSceneChannel* в сегментах по производному типу. Учитывая это, любое перераспределение каналов должно немедленно сопровождаться повторным созданием прокси канала; это сделает недействительными любые указатели и указатели на каналы, хранящиеся в старом прокси.

Все взаимодействие с каналами происходит либо через интерфейс FMovieSceneChannel напрямую, либо ISequencerChannelInterface, в зависимости от контекста. Последний регистрируется для каждого типа через модуль секвенсора ISequencerModule::RegisterChannelEditor.

Невыполнение этого условия приведет к ошибочному утверждению во время выполнения при попытке редактирования таких каналов. Предоставляется шаблонный помощник TSequencerChannelInterface, который позволяет перегрузить единую концепцию для любого данного типа канала, разрешенную с помощью зависимого от аргумента поиска (ADL). 

Это позволяет настраивать конкретное поведение без необходимости повторной реализации всего интерфейса, если значения по умолчанию подходят для большинства каналов. Это также означает, что код секвенсора ядра может автоматически заполнять пользовательский интерфейс для данных канала без необходимости вручную определять ISequencerSection интерфейсы и вручную определять макет канала в редакторе, а также во время выполнения. Это упрощает создание пользовательских типов секций в определенной степени, особенно при составлении секций из уже поддерживаемых данных встроенного канала.

Функции реализации по умолчанию для ISequencerChannelInterface определены в пространстве имен Sequencer, но перегрузки следует добавить либо в пространство имен вашего канала, либо в глобальное пространство имен.

Рекомендуется, чтобы пользовательские каналы следовали шаблону хранения времен и значений в параллельных массивах и предоставляли TMovieSceneChannelData<T> GetData() метод взаимодействия с ключами. Интерфейс большинства FMovieSceneChannel русских напрямую отображается на вызываемые функции TMovieSceneChannelData.

Используя этот прокси-подход, все данные, необходимые для создания пользовательского интерфейса и взаимодействия с ключами канала, легко доступны для кода пользовательского интерфейса Sequencer. 

FMovieSceneChannel

Предоставляет интерфейс, через который можно взаимодействовать со всеми данными общего канала. Все каналы, добавленные в прокси канала, должны реализовывать этот тип.

ISequencerChannelInterface

Интерфейс для всех перегрузок, связанных с взаимодействием пользовательского интерфейса и манипуляциями, требуемыми секвенсором для данного канала. Должен быть зарегистрирован через ISequencerModule класс для каждого типа канала (обычно в StartupModule методе вашего редактора).

TMovieSceneChannelTraits

Задает характеристики времени компиляции для типов каналов, таких как расширенные данные редактора, и поддерживает ли канал значения по умолчанию. Многие утилиты пользовательского интерфейса секвенсора используют перегрузки функций, указанные в MovieSceneChannelTraits.h для взаимодействия с каждым конкретным типом канала. Если шаблонные перегрузки по умолчанию несовместимы с вашим типом канала, вам следует перегрузить необходимые функции для конкретного канала.

Другие утилиты

Несколько вспомогательных утилит были добавлены для облегчения работы с диапазонами сцен фильма. Теперь, когда мы используем дискретную временную базу, легче рационализировать границы раздела. Внутренние диапазоны представлены как TRange<FFrameNumber>, что поддерживает инклюзивные, эксклюзивные и открытые границы. Для того чтобы сделать дело с этими диапазонами простых дискретных базисов времени, вы можете использовать MovieScene::DiscreteInclusiveLower, DiscreteExclusiveUpper и DiscreteSize последовательно бороться с различными граничными условиями.

Руководство по Миграции

Из-за характера этих изменений будут изменения C++, которые требуют миграции, если вы написали свои собственные треки, секции или кривые в C++. Пожалуйста, посмотрите подготовленный пример проекта миграции для трека, раздела и типа канала, чтобы помочь в вашем собственном обновлении.