如果你正在创建一个自定义图层,甚至有可能在你的图层中包括自定义控制预置。如果你的图层有控制你的图层的实时行为的按钮,这就很方便了。
数据结构
下面的数据结构是一个输出样本,需要在你的组合中的`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 脚本来生成停表层的远程控制。请注意,你可以通过改变代码的第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
1TP7吨的定位
当使用多个按钮时,按钮的布局必须手动控制。这意味着按钮是用 "x "和 "y "属性在网格上定位的,就像 "宽度 "和 "高度 "属性一样,是以网格单元的倍数给出的。位置是相对于按钮组被拖到的左上角网格单元而言的。
1TP7吨的行动
Buttons 可以有多个操作,也可以只有一个操作,或者一个操作都没有。操作目标和操作类型有多种有效组合。
请注意,"textInput "和 "numericInput "操作应各自独立,因为无法保证遥控器中一致的用户体验。
行动目标
行动目标是mimoLive文件内的元素。它们以分层的方式被处理:
文档ID "总是在运行时绘制,所以它不必出现在预设中。
- 如果 "layerId "和 "variantId "都没有给出,行动将在文档本身被触发。
- 如果给了 "layerId",该动作将在指定的层上被触发。
- 如果 "layerId" 和 给出 "variantId",该动作将在指定的变量上被触发。只有在这种情况下,可以指定额外的 "toggleSwitchKey "或 "signalKey"(见下面的动作类型)。
行动类型
行动类型 | 解释 | 附加属性 | 有效目标 |
---|---|---|---|
拨动活页 | 切换实时状态 | 没有 | 文件(开始/停止显示),层,变量 |
设置Live | 将直播状态设置为 "直播" | 没有 | 文件(开始显示),层,变量 |
设置关闭 | 将直播状态设置为 "关闭" | 没有 | 文件(停止显示),层,变量 |
信号 | 触发一个信号 | signalKey, signalName(推荐)。 | 变体 |
拨动开关 | 切换一个布尔型输入值 | toggleSwitchKey, toggleSwitchName(推荐)。 | 变体 |
文本输入 | 打开一个文本输入字段,在提交时,更新输入键的值。 | inputKey, inputName (推荐) | 层、变体、源 |
数字输入 | 控制输入键的数值的滑块。 | inputKey, inputDescription (有最小值和最大值的对象), inputName (推荐) | 层、变体、源 |
"textInput" 和 "numericInput" 动作类型从 mimoLive 5.2 开始可用。
Button活的状态
"liveState "对象可用于配置按钮的理货灯状态,它可以是开(红色标记)、过渡(黄色标记)或关(无标记)。
真实的国家来源
与按钮动作目标类似,实时状态可以从多个来源获得:
- 文档ID "总是在运行时绘制,所以它不必出现在预设中。
- 如果 "layerId "和 "variantId "都没有给出,则使用文档的实时状态(展示已经开始或没有)。
- 如果给出 "layerId",则使用该层的实时状态。
- 如果给了 "layerId "和 "variantId",就会使用变体的实时状态。
- 只有在这种情况下,可以指定额外的 "propertyPath",以表明必须使用变体的输入或输出值的布尔属性。
- 另一种可能性(与propertyPath相互排斥!)是指定一个 "dynamicSourceId "属性,将实时状态查找重定向到一个源(通过ID获取),它尊重所选源的动态变化(例如在视频切换器中)。dynamicSourceId "的值在变体的输入值中被查找。
给出属性的完整路径,从变体开始作为根,例如 "inputValues.some_Boolean_Property "或 "outputValues.other_Property"。
- 如果给出 "sourceId",则使用源的实时状态。
Button Text
行动按钮可以显示主要和次要的文本行,两者都可以是静态或动态的。
初级文本
这个文本将是按钮将为用户做什么的主要指标。如果按钮预设包含一个文本属性,它是一个静态文本,将按原样显示。
另外,可以给一个dynamicText,使其包含mimoLive层或使用简单模板语法的变体属性。在模板字符串中,常规字符可以与大括号中的属性路径相结合:
"template": "{\{propertyPath\}}"
属性路径是相对于使用 "layerId"、"variantId"、"sourceId "和 "filterId "解析的对象而评估的。目标解析遵循这些规则:
- 文档ID "总是在运行时绘制,所以它不必出现在预设中。
- 如果 "layerId "和 "variantId "都没有给出,那么属性路径将相对于文档进行评估。
- 如果给出了 "layerId"(和可选的 "variantId"),则属性路径是相对于一个层/变体进行评估的。
- 一个变体的父层可以通过以 "layer "开头的路径来访问,例如 "aslayer.name"。
输入值和输出值的第一个路径段必须是camelCased("inputValues.tvIn..."),而不是API文档中的kebab-cased("input-values.tvIn...")。
- 静态文本将始终优先于动态文本,因为这允许用户用一些可能对他们的情况更有用的自定义文本来覆盖动态文本。
二级文本
为了给用户提供关于一个按钮的更多信息,比如它的父层的名字,可以使用 "subtext "或 "dynamicSubText "属性给出一个辅助文本。
模板语法和对象解析遵循与主要文本完全相同的规则。
Button文字和图标尺寸
按钮上的文字和图标的大小可能根据上下文而变化。通过 "fontScale "选项,你可以指定一个相对于当前屏幕尺寸计算的默认尺寸的比例。"1 "将是默认尺寸。小于1(如0.8)将降低字体大小,大于1(如1.5)将增加字体大小。
Button预览
动作按钮可以显示它们所控制的源的预览图像,或文档中任何其他可用的源。
取决于来源是否是静态的(只有被拖入mimoLive的图像),一个静态的 PNG 表示的源被加载一次,它确实支持一个alpha通道。对于任何其他来源,一个 录像带 源的表现形式会定期更新。动态来源的目标刷新率是每秒5帧,但当发现网络连接速度不足以重复加载预览帧时,这个刷新率就会降低。
目前不支持在动作按钮上显示文件的程序输出。图层默认图像虽然在来源列表中不可见,但可供预览。
为了指定一个源预览,使用了一个对象解析机制:
- 文档ID "总是在运行时绘制,所以它不必出现在预设中。
- 如果给了 "sourceId",则使用该ID的源来进行预览。
- 如果 "layerId"、"variantId "和 "dynamicSourceId "都给定了,源的ID将在 "dynamicSourceId "中的键下的指定层的变体上查找。这可以用来引用像视频切换器的源A-G,即使它们在文件中被改变。
Button 颜色
通过使用 "color "属性,按钮可以用任何颜色代码进行着色,这些代码可以在 HTML (例如,"#f80"、"#ff0088"、"橙色 "或 "rgb(255,66,88)")。
Button Icon
Buttons 可以显示一个图标来表示其功能。要查看所有可用图标的列表,请在运行 mimoLive 并启用远程控制时打开 http://localhost:8989/icons/demo.html。
使用图标的普通名称,例如 "后退 "或 "箭头向下"。