Если вы создаете пользовательский слой, есть возможность даже включить в него пользовательские пресеты управления. Это пригодится, если в слое есть кнопки, которые управляют поведением слоя в реальном времени.
Структура данных
Следующая структура данных представляет собой пример вывода, который должен присутствовать в вашей композиции под ключом вывода структуры `tvOut_ControlRepresentations`:
{
"tvOut_ControlRepresentations": [
{
"title": "Compact Cut's",
"buttons": [
{
"actions": [
{
"layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
"variantId": "F6F52194-06DE-462E-983A-8D505C533A69",
"type": "signal",
"signalKey": "tvGroup_Control__Cut_1_TypeSignal",
"signalName": "Cut 1"
}
],
"liveState": {
"layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
"variantId": "F6F52194-06DE-462E-983A-8D505C533A69",
"dynamicSourceId": "tvIn_VideoSourceAImage"
},
"sourcePreview": {
"layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
"variantId": "F6F52194-06DE-462E-983A-8D505C533A69",
"dynamicSourceId": "tvIn_VideoSourceAImage"
},
"color": "#BBBBBB",
"width": 1,
"height": 1,
"x": 0,
"y": 0,
"icon": "facetime-video",
"dynamicText": {
"template": "{{inputputValues.tvIn_VideoSourceAName}}",
"layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
"variantId": "F6F52194-06DE-462E-983A-8D505C533A69"
}
}
]
}
]
}
У пресета есть "заголовок" и массив "кнопок", но можно обойтись и одной кнопкой.
Ключи `layerId` и `variantId` должны быть динамически заполнены строковыми данными из входных ключей композиции `tvIn_LayerIdentifier` и `tvIn_RuntimeIdentifier`.
Использование предустановок пульта дистанционного управления API в Quartz Composer
Встроенные слои mimoLive используют LUA скрипт для динамической генерации этой структуры данных, поскольку Quartz Composer не поддерживает самостоятельную генерацию структур данных. Скрипт LUA Скрипт содержит сложную функцию addButton(), которая может быть использована для создания структуры одной кнопки. Обычно вы можете просто использовать эту функцию и не модифицировать ее. Таким образом, можно легко создать новые настройки пульта по умолчанию для собственного слоя.
Например, это LUA скрипт для генерации пультов дистанционного управления для слоя Stop Watch. Обратите внимание, что вы можете перенять этот код, просто изменив строки с 15 по 29.
inLayerIdentifier = QC_STRING
inVariantIdentifier = QC_STRING
outControlRepresentations = QC_STRUCT
main = function()
controlRepresentations = {}
-- first representation
controlRepresenation = {}
-- {
controlRepresenation["Title"] = "Stop Watch"
buttons = {}
-- {
-- addButton(buttonsTable, buttonTitle, subTitle, positionX, positionY, width, height, color, icon, actionTarget, liveStateSource, previewSource)
-- first row
addButton(buttons, "{{outputValues.tvOut_TimeString}}", "", 0, 0, 2, 1, "#333333", "", "", "", "")
addButton(buttons, "Live", "{\{name\}}", 2, 0, 1, 1, "#333333", "", "toggleLive", "layerVariant", "")
-- second row
addButton(buttons, "Start", "", 0, 1, 1, 1, "#33cc33", "play", "tvGroup_Control__Start_TypeSignal", "", "")
addButton(buttons, "Stop", "", 1, 1, 1, 1, "#cc3333", "pause", "tvGroup_Control__Stop_TypeSignal", "", "")
addButton(buttons, "Reset", "", 2, 1, 1, 1, "#cccc33", "stop", "tvGroup_Control__Reset_TypeSignal", "", "")
-- }
controlRepresenation["buttons"] = buttons
-- }
table.insert(controlRepresentations , controlRepresenation)
outControlRepresentations = controlRepresentations
end
function addButton(buttonsTable, buttonTitle, buttonSubTitle, positionX, positionY, width, height, color, icon, actionTarget, liveStateSource, previewSource)
local button = {}
-- {
if #buttonTitle > 0 then
if string.find(buttonTitle, "{{") then
-- dynamic titel
local dynamicText = {}
-- {
dynamicText["layerId"] = inLayerIdentifier
dynamicText["variantId"] = inVariantIdentifier
dynamicText["template"] = buttonTitle
-- }
button["dynamicText"] = dynamicText
else
-- static title
button["text"] = buttonTitle
end -- if dynamic
end -- if buttonTitle
if #buttonSubTitle > 0 then
if string.find(buttonSubTitle, "{{") then
-- dynamic titel
local dynamicSubText = {}
-- {
dynamicSubText["layerId"] = inLayerIdentifier
dynamicSubText["variantId"] = inVariantIdentifier
dynamicSubText["template"] = buttonSubTitle
-- }
button["dynamicSubText"] = dynamicSubText
else
-- static title
button["subtext"] = buttonSubTitle
end -- if dynamic
end -- if buttonSubTitle
button["x"] = positionX
button["y"] = positionY
button["width"] = width
button["height"] = height
if #color > 0 then
button["color"] = color
end -- if
if #actionTarget > 0 then
local actions = {}
-- {
local action = {}
-- {
action["layerId"] = inLayerIdentifier
action["variantId"] = inVariantIdentifier
if string.ends(actionTarget, "_TypeSignal") then
action["type"] = "signal"
action["signalKey"] = actionTarget
action["signalName"] = buttonTitle
elseif actionTarget == "toggleLive" then
action["type"] = "toggleLive"
else
action["type"] = "toggleSwitch"
action["toggleSwitchKey"] = actionTarget
action["toggleSwitchName"] = buttonTitle
end -- if
-- }
table.insert(actions , action)
-- }
button["actions"] = actions
end -- if actionTarget
if #liveStateSource > 0 then
local liveState = {}
-- {
liveState["layerId"] = inLayerIdentifier
liveState["variantId"] = inVariantIdentifier
if string.starts(liveStateSource,"tvIn_VideoSource") then
-- get the live state from a dynamic video source
liveState["dynamicSourceId"] = liveStateSource
elseif liveStateSource == "layerVariant" then
-- nor more information needed
else
liveState["propertyPath"] = liveStateSource end -- if
-- }
button["liveState"] = liveState
end -- if liveState Source
if #previewSource > 0 then
local sourcePreview = {}
-- {
sourcePreview["layerId"] = inLayerIdentifier
sourcePreview["variantId"] = inVariantIdentifier
sourcePreview["dynamicSourceId"] = previewSource
-- }
button["sourcePreview"] = sourcePreview
end -- if
if #icon > 0 then
-- See bottom of documentation page for list of avaiable icon names
button["icon"] = icon
end -- if
-- }
table.insert(buttonsTable, button)
end -- func
function string.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function string.ends(String,End)
return End=='' or string.sub(String,-string.len(End))==End
end
Button Позиционирование
При использовании нескольких кнопок расположение кнопок должно контролироваться вручную. Это означает, что кнопки позиционируются на сетке с помощью атрибутов "x" и "y", которые, как и атрибуты "ширина" и "высота", задаются в кратных ячейках сетки. Позиции задаются относительно левой верхней ячейки сетки, на которую была перетащена группа кнопок.
Button Действия
В Buttons может быть несколько действий, одно действие или вообще ни одного. Существуют различные допустимые комбинации целей действий и типов действий.
Обратите внимание, что действия "textInput" и "numericInput" должны быть самостоятельными, поскольку согласованность действий пользователя в пульте ДУ не гарантирована.
Цели деятельности
Цели действий - это элементы внутри документа mimoLive. Они адресуются в иерархическом порядке:
Идентификатор документа" всегда рисуется во время выполнения, поэтому он не должен присутствовать в предустановке.
- Если не указаны ни "layerId", ни "variantId", действие будет инициировано на самом документе.
- Если указано значение "layerId", действие будет запущено на указанном слое.
- Если "layerId" и "variantId", действие сработает на указанном варианте. Только в этом случае можно дополнительно указать "toggleSwitchKey" или "signalKey" (см. раздел "Типы действий" ниже).
Типы действий
Тип действия | Пояснение | Дополнительные атрибуты | Действительные цели |
---|---|---|---|
toggleLive | Переключить режим реального времени | нет | Документ (начало/остановка показа), слой, вариант |
setLive | Установите состояние "в прямом эфире". | нет | Документ (начало показа), слой, вариант |
setOff | Установите состояние жизни на "выключено" | нет | Документ (Стоп-шоу), Слой, Вариант |
сигнал | Запуск сигнала | signalKey, signalName (рекомендуется) | Вариант |
toggleSwitch | Переключение входного значения булевой величины | toggleSwitchKey, toggleSwitchName (рекомендуется) | Вариант |
textInput | Открывает текстовое поле ввода, которое при отправке обновляет значение по адресу inputKey. | inputKey, inputName (рекомендуется) | Слой, Вариант, Источник |
numericInput | Ползунок, управляющий числовым значением на inputKey. | inputKey, inputDescription (объект с минимальным и максимальным значением), inputName (рекомендуется) | Слой, Вариант, Источник |
Типы действий "textInput" и "numericInput" доступны начиная с версии mimoLive 5.2.
Button Live State
Объект "liveState" можно использовать для настройки состояния индикатора кнопки, который может быть включенным (красная метка), переходным (желтая метка) или выключенным (без метки).
Живые государственные источники
Как и в случае с целями действий с кнопками, состояние в реальном времени может быть получено из нескольких источников:
- Идентификатор документа" всегда рисуется во время выполнения, поэтому он не должен присутствовать в предустановке.
- Если ни "layerId", ни "variantId" не указаны, используется состояние документа в реальном времени (начался показ или нет).
- Если указан "layerId", то используется живое состояние слоя.
- Если указаны "layerId" и "variantId", то используется живое состояние варианта.
- Только в этом случае можно указать дополнительное значение "propertyPath", чтобы указать, что необходимо использовать булево свойство входных или выходных значений варианта.
- Другая возможность (взаимоисключающая с propertyPath!) - указать свойство "dynamicSourceId", которое перенаправляет поиск живого состояния на источник (получаемый по ID), который учитывает динамические изменения выбранного источника (например, в видеопереключателе). Значение "dynamicSourceId" ищется во входных значениях варианта.
*Укажите полный путь к свойству, начиная с варианта в качестве корня, например, "inputValues.some_Boolean_Property" или "outputValues.other_Property".
- Если указан "sourceId", используется состояние источника в реальном времени.
1TP7Тонный текст
Кнопки действий могут отображать основную и дополнительную строки текста, причем обе они могут быть статичными или динамичными.
Основной текст
Этот текст будет основным индикатором того, что кнопка будет делать для пользователя. Если предустановка кнопки содержит свойство text, то это статический текст, который будет отображаться как есть.
В качестве альтернативы можно задать dynamicText, который позволяет включить свойства слоя или варианта mimoLive, используя простой синтаксис шаблона. В строке шаблона обычные символы могут сочетаться с путями свойств, заключенными в фигурные скобки:
"template": "{\{propertyPath\}}"
Пути свойств оцениваются относительно объекта, который разрешается с помощью "layerId", "variantId", "sourceId" и "filterId". Разрешение цели происходит по этим правилам:
- Идентификатор документа" всегда рисуется во время выполнения, поэтому он не должен присутствовать в предустановке.
- Если не указаны ни "layerId", ни "variantId", то пути свойств оцениваются относительно документа
- Если задан "layerId" (и, опционально, "variantId"), то пути свойств оцениваются относительно слоя/варианта.
- Доступ к родительскому слою варианта можно получить, начав путь с "layer", например "aslayer.name".
Первый сегмент пути к входным и выходным значениям должен быть в camelCased ("inputValues.tvIn..."), а не в kebab-cased ("input-values.tvIn..."), как в документах API.
- Статический текст всегда будет превалировать над динамическим, потому что это позволяет пользователям перезаписывать динамический текст каким-либо собственным текстом, который может быть более полезен в их ситуации.
Вторичный текст
Чтобы предоставить пользователю больше информации о кнопке, например, название ее родительского слоя, можно задать вторичный текст с помощью свойств "subtext" или "dynamicSubText".
Синтаксис шаблонов и разрешение объектов подчиняются тем же правилам, что и основной текст.
Button Размер текста и значков
Текст и иконки на кнопках могут иметь разный размер в зависимости от контекста. С помощью параметра "fontScale" вы можете указать относительный масштаб к размеру по умолчанию, рассчитанному для текущего размера экрана. "1" будет размером по умолчанию. Меньше 1 (например, 0,8) уменьшит размер шрифта, а больше 1 (например, 1,5) - увеличит.
Button Предварительный просмотр
Кнопки действий могут отображать изображение предварительного просмотра источника, которым они управляют, или любого другого источника, доступного в документе.
В зависимости от того, является ли источник статическим (только изображения, которые были перетащены в mimoLive), статический PNG один раз загружается представление источника, которое поддерживает альфа-канал. Для любого другого источника загружается JPEG представление источника регулярно обновляется. Целевая частота обновления для динамических источников составляет 5 кадров в секунду, но эта частота снижается, если скорость сетевого соединения оказывается недостаточной для повторной загрузки кадров предварительного просмотра.
В настоящее время не поддерживается отображение программного вывода документа на кнопке действия. Изображения слоя по умолчанию, хотя и не видны в списке источников, доступны для предварительного просмотра.
Для указания исходного превью используется механизм разрешения объектов:
- Идентификатор документа" всегда рисуется во время выполнения, поэтому он не должен присутствовать в предустановке.
- Если указан "sourceId", то для предварительного просмотра используется источник с этим идентификатором.
- Если заданы все значения "layerId", "variantId" и "dynamicSourceId", то идентификатор источника будет искаться в указанном варианте слоя по ключу в "dynamicSourceId". Это можно использовать для ссылки на такие источники, как источники A-G видеокоммутатора, даже если они изменены в документе.
Button Цвет
Используя атрибут "color", кнопки можно раскрасить любым цветовым кодом, который можно представить в HTML (например, "#f80", "#ff0088", "оранжевый" или "rgb(255, 66, 88)").
Button Icon
1TP7Тоны могут отображать иконку, указывающую на их функциональность. Чтобы увидеть список всех доступных иконок, откройте http://localhost:8989/icons/demo.html, пока работает mimoLive и включены пульты дистанционного управления.
Используйте обычное название значка. Например, "назад" или "стрелка вниз".