Expressions в DaVinci Resolve: полный список с примерами

Expressions на Fusion-странице DaVinci Resolve открывают то, что не выразить одними ключевыми кадрами. Здесь собраны формулы, которые реально пригождаются в работе, — проверенные на практике, а не придуманные для примера. Список не претендует на полноту: это рабочий документ, к которому я сам постоянно возвращаюсь и дополняю.
Проверять expression удобнее всего на узле Text+: вставь его в поле Styled Text — и сразу увидишь результат в читаемом виде, дальше останется только подстроить формулу под задачу.
Ещё момент: сначала пропиши expression, и только потом переименовывай узел. Сделаешь наоборот — ссылка внутри формулы не обновится сама.
Два дефиса -- в конце строки отсекают всё, что после них: например, GetPrefs("Comp.FrameFormat.Rate") -- Returns TL FPS. Удобный способ оставить себе комментарий прямо внутри expression.
Как читать эту шпаргалку
Если ты раньше не касался expressions вообще — вот минимум, без которого дальше половина формул будет выглядеть как заклинание.
Expression — формула вместо ручного значения. У любого параметра (Angle, Width, Center — не важно) справа есть маленький значок или пункт в правом клике «Expression» — нажимаешь, и вместо ползунка появляется текстовое поле. Начиная с этого момента значение параметра на каждом кадре не задаётся руками, а вычисляется по формуле заново.
time — «номер текущего кадра», и это буквально счётчик: на кадре 0 он равен 0, на кадре 24 — равен 24, на кадре 100 — 100. Он растёт сам собой, пока играет таймлайн, без единого keyframe. Вся анимация без keyframes в этой шпаргалке построена на одном и том же трюке: если параметр зависит от time, он меняется каждый кадр автоматически.
Например, expression time в параметре Angle узла Transform означает «угол поворота равен номеру кадра». На кадре 0 угол 0°, на кадре 90 — угол 90°, на кадре 360 — объект вернулся туда же, откуда начал (360° — это полный круг). Число всё время растёт — значит, объект крутится без остановки. В Fusion рост угла в плюс вращает объект против часовой стрелки, поэтому -time (тот же приём, только со знаком минус) крутит его по часовой.
comp.RenderEnd — общая длина композиции в кадрах. Если поделить time на comp.RenderEnd, получится дробь, которая растёт от 0 в начале до 1 в самом конце, — прогресс всей композиции. Это самый частый строительный блок ниже: почти любая анимация «от 0 до 100%» или «уложиться ровно в длину ролика» начинается именно с этого отношения.
Ссылка на другой узел пишется как ИмяУзла.Параметр, например Rectangle1.Width — так можно забрать значение одного параметра и подставить в формулу другого, вообще не трогая keyframes.
И последнее: часть формул ниже начинается с двоеточия : — это значит, что внутри не одна короткая формула, а кусок настоящего кода на Lua (переменные, условия, функции). Точка с запятой разделяет команды внутри такого блока — как в обычном программировании.
Базовые
time
Номер текущего кадра — растёт на 1 каждый кадр сам, без твоего участия. Подставь в Angle — получишь бесконечное вращение против часовой стрелки: угол каждый кадр увеличивается на 1°.
time-1 (time-n)
То же самое значение, что было n кадров назад: time-1 — прошлый кадр, time-10 — на 10 кадров раньше текущего. Пригождается, когда нужно сравнить состояние сейчас с состоянием чуть раньше — например, посчитать, на сколько что-то сдвинулось за кадр.
-time
Тот же time, только со знаком минус — угол уменьшается с каждым кадром, поэтому вращение идёт по часовой стрелке, в обратную сторону от обычного time.
ceil()
Округляет дробное число вверх, до ближайшего целого: и 2.1, и 2.9 одинаково станут 3. Пригождается, когда важно получить целое число, а формула внутри выдаёт дробь.
math.ceil()
То же самое действие, только в записи для Lua-блоков: если строка начинается с :, пиши math.ceil(), а не просто ceil().
floor()
Округляет вниз, до ближайшего целого: и 2.1, и 2.9 станут 2.
math.floor()
floor() в Lua-варианте — для формул, начинающихся с :.
abs
Убирает знак минус: -5 и 5 после abs одинаково дают 5. Полезно, когда важна только величина, а не направление — например, расстояние всегда положительное.
time/600
Делит номер кадра на 600 — получается медленно растущее число. Чем больше делитель, тем медленнее меняется результат: удобный способ «притормозить» анимацию, не трогая keyframes.
time*600
Обратный приём: умножает номер кадра, значение растёт быстрее. Чем больше множитель, тем быстрее анимация.
sin(time)
Синус от номера кадра — плавно и без остановок колеблется между -1 и 1, туда-обратно. Хорошая основа для покачивания, мигания или «дыхания» объекта.
ceil(sin(time))
То же колебание, но округлённое вверх — вместо плавного перехода получается резкий скачок между 0 и 1 каждые два кадра. Годится как переключатель вкл/выкл.
floor(sin(time))
То же самое, но округление вниз — скачок между -1 и 0.
comp.RenderEnd
Сколько всего кадров в композиции. Используется как «знаменатель» почти во всех формулах на прогресс ниже.
comp.RenderEnd/2
Номер кадра ровно посередине композиции — например, чтобы что-то произошло точно «на середине ролика».
(1-(time/comp.RenderEnd)*2)
Прогресс от 0 до 1, который укладывается только в первую половину композиции — во второй половине формула уже не «работает на анимацию». Удобно, если действие должно успеть закончиться независимо от общей длины ролика.
(comp.RenderEnd-comp.RenderStart)
Тоже общее число кадров в композиции, только через разницу конца и начала — на случай, если начало не с нулевого кадра.
time/comp.RenderEnd
Главная формула прогресса во всей этой шпаргалке: 0 в начале композиции, 1 в конце. Практически любая формула «подстроиться под длину таймлайна» начинается именно с этого отношения.
1-(time/comp.RenderEnd)
Тот же прогресс, только задом наперёд: 1 в начале, 0 в конце.
(time*360)/fps
Ровно один оборот в секунду в параметре Angle: 360° делится на fps (число кадров в секунду) и умножается на time — за одну секунду угол успевает пройти полный круг. Вместо fps подставь своё число.
(time*360)/(fps*2)
То же самое, но оборот растягивается на 2 секунды — вдвое медленнее.
360/copies
На узле Duplicate делит полный круг (360°) на количество копий — так копии расставляются по кругу равномерно, без ручного подбора угла для каждой.
ceil(time/fps)
Секундомер, считающий вверх: 1, 2, 3… — растёт на единицу раз в секунду, а не каждый кадр.
ceil((time)/comp:GetPrefs("Comp.FrameFormat.Rate"))
Тот же секундомер, но fps подставляется автоматически из настроек композиции — не нужно вписывать число руками и следить, чтобы оно совпадало с реальным.
ceil((comp.RenderEnd-time)/fps)
Обратный секундомер: считает не вверх, а вниз, до конца композиции.
ceil((comp.RenderEnd-time)/comp:GetPrefs("Comp.FrameFormat.Rate"))
Тот же обратный отсчёт, но с автоматическим fps.
max(floor(30-(time/fps)),0)
Отсчёт целыми секундами от 30 до 0, который останавливается на нуле и не уходит в минус — за это как раз отвечает max(...,0).
ceil(time/comp.RenderEnd*100)
Процент прохождения композиции: 0 в начале, 100 в конце.
ceil(time/comp.RenderEnd*100) .. "%"
То же самое, но со знаком % на конце строки. В Lua строки склеиваются двумя точками .., и текст всегда берётся в кавычки.
ceil((1-time/comp.RenderEnd)*100)
Процент, который остался до конца композиции, — обратный отсчёт в процентах.
ceil((1-time/comp.RenderEnd)*100) .. "%"
То же самое, с приклеенным %.
math.floor(PolylineStroke1.WriteOnEnd*100).."%"
Забирает значение прогресса у эффекта Wipe On (обводка, которая постепенно «дорисовывается») и превращает в проценты с подписью — удобно вывести рядом текстом.
math.floor(Circle1.Radius*100)
Счётчик, растущий вместе с радиусом узла Circle: если радиус анимирован ключами, число будет расти синхронно с ним.
math.floor(Rectangle1.Width*50).."%"
Проценты, завязанные на ширину маски Rectangle — например, подпись «заполнено на N%» рядом с прогресс-баром на основе маски.
Случайность и условия
:randomseed(floor(time/6)) ; return random()
Случайное число от 0 до 1, которое меняется не каждый кадр, а раз в 6 кадров: floor(time/6) держит одно и то же «семя» случайности 6 кадров подряд, поэтому значение дёргается ступеньками, а не мельтешит.
iif(time >= 0 and time <=30, (random(0,20)), 20)
С 0 по 30 кадр — случайное число от 0 до 20, дёргающееся каждый кадр, а после 30 кадра значение застывает на 20. iif(условие, если_да, если_нет) — это и есть «если-то-иначе» в одну строку, самая частая конструкция в expressions.
iif(time<10, 5, iif(time >= 0 and time <=30, (random(0,20)), 20))
Тот же трюк, но с задержкой перед стартом: до 10 кадра держит фиксированное значение 5, а с 10 по 30 кадр включается случайность из формулы выше и застывает на 20.
:if time < 10 then return 0; else return 90; end
Развёрнутая запись «если-то-иначе» на Lua, словами if/then/else/end — работает только если строка начинается с двоеточия. Короче то же самое пишется как iif(time<10,0,90).
:freq = 0.1;amplitude = 3.5; decay = 0.1; y = amplitude*math.cos(freq*time*2*math.pi)/math.exp(decay*time); function hello() x = time*0.02;return x; end; return (y + hello());
Затухающее колебание: сначала раскачивается заметно, потом амплитуда сама уменьшается со временем — как маятник, который постепенно останавливается. freq отвечает за частоту колебаний, amplitude — за размах, decay — за скорость затухания. Есть смысл вынести все три в CustomTool ползунками, чтобы настраивать на глаз, а не переписывать формулу.
Прогресс и загрузка
"Progress: " .. ceil(time/comp.RenderEnd*100) .. "%"
Готовая подпись «Progress: 42%», которая растёт сама вместе с проигрыванием — просто подставь в Styled Text узла Text+.
ceil((1-time/comp.RenderEnd)*100) .. "%"
Тот же процент, только тающий: со 100% к 0%.
"Progress: " .. ceil((1-time/comp.RenderEnd)*100) .. "%"
То же самое, но с подписью «Progress:» впереди тающего процента.
"Loading " .. ceil(time/24) .. "/" .. ceil(comp.RenderEnd/fps)
Имитация загрузки в духе «Loading 3/12», где числа считаются в секундах. Замени 24 в первой части на свой fps, если он отличается.
Работа с текстом
((Text1.Output.DataWindow[4]-Text1.Output.DataWindow[2])/Text1.Output.Height)
DataWindow — это область, которую текст реально занимает в кадре, а не размер текстового блока. Формула вычисляет её высоту в пикселях — пригождается, если нужно, например, подстроить фон точно под размер надписи.
((Text1.Output.DataWindow[3]-Text1.Output.DataWindow[1])/Text1.Output.Width)
То же самое, но ширина занятой текстом области. Индексы DataWindow идут по границам: [1] — левый край, [2] — верхний, [3] — правый, [4] — нижний.
Text1.StyledText.Value или Text1.StyledText[0]
Достаёт сам текст, набранный в узле Text+, как строку — чтобы использовать его в других формулах: посчитать длину, склеить с другим текстом и так далее.
Text1.StyledText.Value .. Text2.StyledText.Value
Склеивает текст из двух узлов Text+ в один. .. — оператор склейки строк в Lua.
string.len(Text1.StyledText.Value)
Считает, сколько всего символов в тексте — включая пробелы и знаки препинания.
:_, mylines = string.gsub(Text1.StyledText.Value, "\n", ""); return mylines
Считает количество строк — ищет символы переноса строки и считает, сколько раз функция их нашла и заменила.
:_, myspaces = string.gsub(Text1.StyledText.Value, "%s", ""); return myspaces
Считает количество пробелов в тексте — буквально, а не что-то ещё, несмотря на похожее название переменной в оригинале этого рецепта.
:_, myletters = string.gsub(Text1.StyledText.Value, "%a", ""); return myletters
Считает буквы, без пробелов и цифр.
:_, mylower = string.gsub(Text1.StyledText.Value, "%l", ""); return mylower
Считает символы в нижнем регистре — сюда же попадают и цифры.
:_, myupper = string.gsub(Text1.StyledText.Value, "%u", ""); return myupper
Считает символы в ВЕРХНЕМ регистре.
:_, alphanumeric = string.gsub(Text1.StyledText.Value, "%w", ""); return alphanumeric
Считает буквы и цифры вместе, без пробелов и знаков препинания.
:_, myvow = string.gsub(Text1.StyledText.Value, "[AEIOUaeiou]", ""); return myvow
Считает гласные буквы (латиница — AEIOU).
:_, novow = string.gsub(Text1.StyledText.Value, "[^AEIOUaeiou]", ""); return novow
Считает всё, кроме гласных: согласные, пробелы, цифры и знаки — «наоборот» от предыдущей формулы.
:_, mydigits = string.gsub(Text1.StyledText.Value, "%d", ""); return mydigits
Считает цифры.
:_, punctuation = string.gsub(Text1.StyledText.Value, "%p", ""); return punctuation
Считает знаки препинания: точки, запятые и похожее.
:_, controlchar = string.gsub(Text1.StyledText.Value, "%c", ""); return controlchar
Считает управляющие символы — они не отображаются на экране (перенос строки, табуляция), но формально тоже часть текста.
:_, myhex = string.gsub(Text1.StyledText.Value, "%x", ""); return myhex
Считает символы, которые годятся в шестнадцатеричной записи — цифры 0-9 и буквы A-F. На глаз их легко перепутать с пробелами, отсюда и оговорка в оригинальном рецепте.
:_, myletters = string.gsub(Text1.StyledText.Value, "%A", ""); return myletters
Считает всё, что НЕ буквы, — цифры, пробелы и знаки препинания вместе.
[^AEIOUaeiou]
Общее правило для всех формул выше: если сделать заглавной букву класса после % (например, %a → %A), результат переключается на противоположный — «буквы» превращаются в «не буквы». То же самое делает знак ^ перед классом символов в квадратных скобках: «всё, кроме перечисленного».
Эффект «печатной машинки» — Write On
min(time/(comp.RenderEnd/2),1)-(Text1.Delay)
Резко останавливает перемешивание букв (scramble, когда буквы «трясутся» и постепенно складываются в слово) ровно на середине композиции — вторая половина уже показывает читаемый текст без изменений. Delay — ползунок 0–0.25, добавляющий паузу перед стартом эффекта. Чтобы буквы, наоборот, распадались из слова в кашу, повесь на композицию TimeSpeed со скоростью -1 — время пойдёт в обратную сторону.
1-(time/comp.RenderEnd)
Та же логика перемешивания, но в обратном направлении: от каши к читаемому слову.
time/(comp.RenderEnd/fps)
Классический эффект «печатной машинки»: один символ текста проявляется за каждый кадр.
time/(comp.RenderEnd/fps)*2
То же самое, только скорость печати вдвое выше — два символа за кадр.
time/(comp.RenderEnd/comp:GetPrefs("Comp.FrameFormat.Rate"))/2
Половинная скорость печати, с автоматическим fps — не нужно заранее знать частоту кадров. На «неровных» значениях вроде 23.976 буквы иногда проявляются между кадрами, поэтому стоит проверить результат глазами.
time/(comp.RenderEnd/comp:GetPrefs("Comp.FrameFormat.Rate"))/(Text1.WriteOn)
Та же печать, но скорость крутит ползунок WriteOn (целое число, шаг 2) — можно менять темп прямо в инспекторе, не трогая формулу.
Маски
floor(-1*((Rectangle1.Height))/2) или floor(-Rectangle1.Height)/2
Координата нижнего края маски Rectangle — половина высоты со знаком минус.
floor((Rectangle1.Height)/2)
Координата верхнего края той же маски. По аналогии Width вместо Height должен давать боковые границы — автор рецепта сам ещё не проверял.
Point(Rectangle1.Center.Y-(Rectangle1.Width/2)+(Rectangle1.Width/2))
Ставит точку ровно на внутренний левый край маски — удобно, чтобы «пришить» другой объект точно к границе.
Point(Rectangle1.Center.Y-(Rectangle1.Width/2)-(Rectangle1.Width/2))
То же самое, но точка ставится на внешней стороне левого края — за пределами маски.
Point(Rectangle1.Center.X, (Rectangle1.Center.Y+(Rectangle1.Height/2)))
Верхняя точка прямоугольной маски — центр плюс половина высоты.
Point(Rectangle1.Center.X, (Rectangle1.Center.Y-(Rectangle1.Height/2)))
Нижняя точка прямоугольной маски.
Point(Rectangle1.Center.X+(Rectangle1.Width/2))
Правая точка прямоугольной маски.
Point(Rectangle1.Center.X-(Rectangle1.Width/2))
Левая точка прямоугольной маски.
math.floor(((Transform1.XSize*100)-100)+100).."%"
Процент «до пустоты»: чем уже становится маска по ширине (Transform1.XSize), тем меньше число — удобно для подписи вроде «осталось N%».
math.floor((100-Transform1.XSize*100)).."%"
Процент «до заполнения» — растёт по мере того, как маска расширяется. Обратный вариант предыдущей формулы.
Точки для масок удобнее не считать вручную, а собрать через null-объект и трансформацию — так же надёжно, но без риска ошибиться в формуле.
Дата и системные функции
Text1.StyledText = os.date('%x')
Подставляет в текст текущую дату компьютера, на котором открыт проект. Что именно выводится, регулируется кодом после % — таблица ниже.
| Код | Что выводит |
|---|---|
%a |
сокращённый день недели (Wed) |
%A |
полный день недели (Wednesday) |
%b |
сокращённый месяц (Sep) |
%B |
полный месяц (September) |
%c |
дата и время (09/16/98 23:48:10) |
%d |
число месяца, 01–31 (16) |
%H |
час, 24-часовой формат, 00–23 (23) |
%I |
час, 12-часовой формат, 01–12 (11) |
%M |
минуты, 00–59 (48) |
%m |
месяц, 01–12 (09) |
%p |
«am» или «pm» |
%S |
секунды, 00–61 (10) |
%w |
день недели, 0–6, где 0 — воскресенье (3) |
%x |
дата (09/16/98) |
%X |
время (23:48:10) |
%Y |
год полностью (1998) |
%y |
год двумя цифрами (98) |
%% |
символ % как есть |
Запуск файлов и веб-страниц из кнопки
Одна строка кода умеет открывать браузер с локальным html-файлом или веб-страницей прямо по нажатию кнопки на узле — например, кнопка на узле открывает документацию проекта или галерею отрендеренных кадров. Windows и Mac запускают внешние программы по-разному (start и open), поэтому под каждую систему — своя строка.
os.execute ("start ../galleries/gallery.html" )
Открывает локальный html-файл в браузере по умолчанию — Windows.
os.execute ("open ../galleries/gallery.html" )
То же самое для Mac.
os.execute('start "" "https://example.com/"')
Открывает веб-страницу — Windows.
os.execute('open "" "https://example.com/"')
Открывает веб-страницу — Mac.
А так эта команда превращается в настоящую кнопку прямо на узле — код добавляется в текстовый редактор скрипта узла (Edit Controls → Script), строкой ниже ViewInfo = OperatorInfo { Pos = { 0, 82.5 } },:
UserControls = ordered() {
ScriptButton = {
LINKS_Name = "ScriptButton",
LINKID_DataType = "Number",
INPID_InputControl = "ButtonControl",
INP_Integer = false,
BTNCS_Execute = [[
os.execute('open "" "https://example.com"')
os.execute('start "" "https://example.com"')
]],
ICS_ControlPage = "Controls"
}
}
Ссылка на значение другого узла
Transform1:Angle
Забирает текущее значение угла у узла Transform1 и подставляет его сюда. Общий вид записи — ИмяУзла:Параметр — так можно сослаться на любое свойство любого другого узла в композиции, не только на Angle.
Значение в конкретный момент времени
Rectangle1:GetValue("Width", 10)
Ширина узла Rectangle1 не сейчас, а именно на 10-м кадре — застывший «снимок» значения на конкретный момент, даже если сам параметр анимирован и меняется.
Rectangle1.Width
А это — просто текущее, «живое» значение ширины на каждом кадре, без привязки к конкретному моменту.
Merge1:GetValue("Center", time-1).X
Координата X точки Center с прошлого кадра — пригождается, чтобы сравнить, куда объект сдвинулся за один кадр, например для расчёта скорости.
self:GetValue(....)
Тот же приём, но для параметра этого же узла — self означает «у самого себя», а не у соседнего узла.
Значение с предыдущего узла в цепочке
Практического применения на каждый день у этого приёма не так много, но он гибкий — например, можно менять цвет фигуры в зависимости от её собственной ширины на предыдущем шаге цепочки.
self:GetSourceTool("[connected input]"):GetValue("[source parameter]", [source time])
Читает значение параметра не у себя, а у узла, который подключён на вход текущего. [connected input] — это имя именно входа (например, EffectMask), а не имя узла. [source time] — на каком кадре смотреть это значение: можно взять фиксированный кадр (0), а можно завязать на time, чтобы значение менялось вместе с проигрыванием.
self:GetSourceTool("EffectMask"):GetValue(("Width*2",time*2))
Пример применения формулы выше: смотрит на вход EffectMask и берёт его ширину на кадре, который вдвое больше текущего, — то есть развитие эффекта опережает саму композицию в 2 раза.
iif(time>=25 and time<=200, ceil(((time-25)/(200-25)*100)) .. "%",iif(time<25,"0%","100%"))
Прогресс, который включается не с самого начала, а с 25-го кадра, доходит до 100% к 200-му, а до и после остаётся неподвижным на границах — 0% и 100%. Замени 25 и 200 на нужные тебе кадры и вынеси их в ползунки, чтобы настраивать без правки формулы.
Настройки композиции — comp:GetPrefs
comp:GetPrefs()
Возвращает сразу весь набор настроек текущей композиции.
comp:GetPrefs("Comp.FrameFormat.Rate")
Частота кадров таймлайна одним числом. Самое частое применение — подставлять её вместо ручного fps в других формулах: не нужно вписывать число руками и рисковать ошибиться, если проект переоткроют с другой частотой.
comp:GetPrefs("Comp.FrameFormat.Width")
Ширина таймлайна в пикселях — например, 1920 для проекта в 1080p.
comp:GetPrefs("Comp.FrameFormat.Height")
Высота таймлайна в пикселях — например, 1080 для проекта в 1080p.
self.Input.OriginalWidth
Ширина не таймлайна, а именно входного видео на этом узле. Если в 1080p-проект вставлен 4K-ролик, формула вернёт честные 3840, а не 1920 таймлайна — разница важна, когда нужно работать с реальным разрешением исходника.
self.Input.OriginalHeight
То же самое, только высота — 2160 для 4K-исходника на 1080p-таймлайне.
KeyframeStretcher
min(Background1.GlobalOut,F1.FPS)
Подстраивает KeyframeStretcher под длину узла по его собственным Global In/Out — если общая длина композиции меняется, узел не «уезжает» и не обрезается, а пересчитывается сам.
Dissolve Switch
iif((comp.RenderEnd-time)<(comp.RenderEnd/2),0,1)
Переключает вход Dissolve с заднего плана (0) на передний (1) ровно в момент, когда пройдена половина композиции, — простой способ «сменить картинку» без анимации самого перехода.
Несколько таких переключателей можно связать в цепочку через iif, чтобы одним параметром (в примере — Animation) управлять сразу несколькими состояниями: например, крутить один ползунок, а переключаться между тремя разными картинками. На комбо-переключателе — iif(Animation>=1,1,0), на Switch 01 — iif(Animation>=1,1,0), на Switch 02 — iif(Switch02.Animation>1,1,0).
TimeStretcher
Мощный узел, вариантов expressions под него можно придумать бесконечно много.
time<Hold_Frame and time or time>Hold_Frame+Hold_Time and time-Hold_Time or Hold_Frame
Формула держит анимацию на паузе: до кадра Hold_Frame время идёт как обычно, затем «застревает» на Hold_Time кадров — анимация как будто останавливается, — а после снова продолжается, просто со сдвигом. Оба значения удобно вынести в Edit Controls ползунками: Hold_Frame — с какого кадра пауза, Hold_Time — насколько кадров она длится.
Готовый узел с этим expression, чтобы разобрать по частям: TimeStretcher Animation Pause Node.
If-Then-Else
iif(Merge1.Blend > 0.5, 1, 0)
Если Blend больше 0.5 — на выходе 1, иначе — 0. Именно так expressions обычно «принимают решения»: привычного if в интерфейсе нет, но есть iif() как его короткая замена.
(Merge1.Blend > 0.5) and 1 or 0
Тот же результат без iif() — через логические and/or: (условие) and значение_если_да or значение_если_нет. Работает так же, просто другой синтаксис записи.
Операторы
| Оператор | Что делает |
|---|---|
x + y |
x плюс y |
x - y |
x минус y |
x < y |
1.0, если x меньше y, иначе 0.0 |
x > y |
1.0, если x больше y, иначе 0.0 |
!x |
1.0, если x = 0, иначе 0.0 |
-x |
(0.0 - x) |
+x |
(0.0 + x) — по сути не делает ничего |
x ^ y |
x в степени y |
x * y |
x умножить на y |
x / y |
x разделить на y |
x % y |
остаток от деления x на y |
x <= y |
1.0, если x меньше или равно y, иначе 0.0 |
x >= y |
1.0, если x больше или равно y, иначе 0.0 |
x = y / x == y |
1.0, если x точно равно y, иначе 0.0 (обе записи равнозначны) |
x <> y / x != y |
1.0, если x не равно y, иначе 0.0 (обе записи равнозначны) |
x & y / x && y |
1.0, если и x, и y не равны 0.0 (обе записи равнозначны) |
x | y / x || y |
1.0, если x или y (или оба) не равны 0.0 (обе записи равнозначны) |
Формулы для Number Out / Point Out
Доступны прямо во вкладках Number Out и Point Out, как часть expression:
| Функция | Что возвращает |
|---|---|
n1..n9 |
значение Number Input 1..9 |
p1x..p9x |
X координата Positional Control 1..9 |
p1y..p9y |
Y координата Positional Control 1..9 |
time |
текущий кадр |
pi |
число π |
e |
число e |
log(x) |
логарифм x по основанию 10 |
ln(x) |
натуральный логарифм x (по основанию e) |
sin(x) |
синус x (x в градусах) |
cos(x) |
косинус x (x в градусах) |
tan(x) |
тангенс x (x в градусах) |
asin(x) |
арксинус x, в градусах |
acos(x) |
арккосинус x, в градусах |
atan(x) |
арктангенс x, в градусах |
atan2(x, y) |
арктангенс x,y, в градусах |
abs(x) |
абсолютное (положительное) значение x |
int(x) |
целая часть x |
frac(x) |
дробная часть x |
sqrt(x) |
квадратный корень x |
rand(x, y) |
случайное значение между x и y |
rands(x, y, s) |
случайное значение между x и y по seed-у s |
min(x, y) |
меньшее из x и y |
max(x, y) |
большее из x и y |
dist(x1, y1, x2, y2) |
расстояние между точками x1,y1 и x2,y2 |
dist3d(x1,y1,z1,x2,y2,z2) |
расстояние между 3D-точками |
noise(x) |
плавный Perlin-шум по x |
noise2(x, y) |
плавный Perlin-шум по x и y |
noise3(x, y, z) |
плавный Perlin-шум по x, y и z |
if(c, x, y) |
x, если c ≠ 0, иначе y |
Плавность анимации — easing
Easing — это форма кривой скорости, а не сама скорость. Обычный time/comp.RenderEnd даёт линейное движение — равномерное от начала до конца. Easing-формулы ниже дают ту же дробь от 0 до 1, но не по прямой, а по кривой: In — старт медленный, разгон к концу; Out — старт быстрый, торможение к концу; InOut — медленно-быстро-медленно, S-образная кривая, самая похожая на «живое» движение. Названия семейств — Sine, Quad, Cubic, Quart, Quint, Expo, Circ, Back — это просто нарастающая «крутизна» кривой: чем дальше в списке, тем резче разгон и торможение. Подставляй любую формулу вместо обычного time/comp.RenderEnd там, где движение должно быть не линейным.
Sine
1 - cos((time/comp.RenderEnd * pi) / 2)sin(((time/comp.RenderEnd) * pi) / 2)-(cos(pi * (time/comp.RenderEnd)) - 1) / 2Quad
(time/comp.RenderEnd) * (time/comp.RenderEnd)1 - (1 - (time/comp.RenderEnd)) * (1 - (time/comp.RenderEnd))iif((time/comp.RenderEnd) < 0.5, 2 * (time/comp.RenderEnd) * (time/comp.RenderEnd), 1 - pow(-2 * (time/comp.RenderEnd) + 2, 2) / 2)Cubic
(time/comp.RenderEnd)^31-(1-time/comp.RenderEnd)^3iif((time/comp.RenderEnd < 0.5), (((time/comp.RenderEnd)^3)*4), 1-(((1-time/comp.RenderEnd)^3)*4))Quart
(time/comp.RenderEnd) ^ 41 - pow(1 - (time/comp.RenderEnd), 4)iif((time/comp.RenderEnd) < 0.5, 8 * (time/comp.RenderEnd) * (time/comp.RenderEnd) * (time/comp.RenderEnd) * (time/comp.RenderEnd), 1 - pow(-2 * (time/comp.RenderEnd) + 2, 4) / 2)Quint
(time/comp.RenderEnd)^51 - pow(1 - (time/comp.RenderEnd), 5)iif((time/comp.RenderEnd) < 0.5, 16 * (time/comp.RenderEnd) *(time/comp.RenderEnd) * (time/comp.RenderEnd) * (time/comp.RenderEnd) * (time/comp.RenderEnd), 1 - pow(-2 * (time/comp.RenderEnd) + 2, 5) / 2)Expo
pow(2, 10 * (time/comp.RenderEnd) - 10)1 - pow(2, -10 * (time/comp.RenderEnd))iif((time/comp.RenderEnd) < 0.5, pow(2, 20 * (time/comp.RenderEnd) - 10) / 2, (2 - pow(2, -20 * (time/comp.RenderEnd) + 10)) / 2)Circ
1 - sqrt((1 - (time/comp.RenderEnd) ^ 2))sqrt(1 - pow((time/comp.RenderEnd) - 1, 2))iif((time/comp.RenderEnd < 0.5), (1 - sqrt((1 - (2 * (time/comp.RenderEnd)) ^ 2))) / 2, (sqrt(1 - (-2 * (time/comp.RenderEnd) + 2) ^ 2) + 1) / 2)Back
(1.70158 + 1) * (time/comp.RenderEnd) * (time/comp.RenderEnd) * (time/comp.RenderEnd) - 1.70158 * (time/comp.RenderEnd) * (time/comp.RenderEnd)1 + (1.70158 + 1) * pow((time/comp.RenderEnd) - 1, 3) + 1.70158 * pow((time/comp.RenderEnd) - 1, 2)iif((time/comp.RenderEnd) < 0.5, (pow(2 * (time/comp.RenderEnd), 2) * ((2.594909 + 1) * 2 * (time/comp.RenderEnd) - 2.594909)) / 2, (pow(2 * (time/comp.RenderEnd) - 2, 2) * ((2.594909 + 1) * ((time/comp.RenderEnd) * 2 - 2) + 2.594909) + 2) / 2)Обратный отсчёт — Fake Timer
Text("9:".. max(30-floor(time/comp:GetPrefs("Comp.FrameFormat.Rate")),0))
Через узел Text+ делает таймер обратного отсчёта в формате 9:30, 9:29, 9:28… «9» перед двоеточием — просто часть строки, замени на любое число или слово под свой формат.
max(floor((Text1.N1+1)-(time/comp:GetPrefs("Comp.FrameFormat.Rate"))),0)
Та же идея, но стартовое число задаётся не в самой формуле, а ползунком N1 (или через CustomTool) — удобнее менять таймер без захода в код.
Сохрани эту шпаргалку в закладки — при работе с Fusion-страницей к ней придётся возвращаться регулярно. И не расстраивайся, если expression не заработал с первого раза: большинство формул выше завязаны на конкретные имена узлов — Text1, Rectangle1, Merge1 — проверь, что в твоём проекте они называются именно так, либо поправь имена под свои.
Обсуждение
0На этой странице
Шпаргалки
Ёмкие разборы инструментов DaVinci Resolve — сохраняй, возвращайся, когда нужно быстро вспомнить деталь.
Все шпаргалки