사용자 지정 레이어를 만드는 경우 레이어에 사용자 지정 제어 사전 설정을 포함할 수도 있습니다. 레이어에 라이브 상태에서 레이어의 동작을 제어하는 푸시 버튼이 있는 경우 유용하게 사용할 수 있습니다.
데이터 구조
다음 데이터 구조는 컴포지션의 `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"
}
}
]
}
]
}
프리셋에는 '제목'과 여러 개의 '버튼'이 있지만 버튼이 하나만 있어도 괜찮습니다.
레이어아이디`와 `바리언트아이디` 키는 컴포넌트 입력 키 `tvIn_레이어아이디`와 `tvIn_런타임아이디`의 문자열 데이터로 동적으로 채워야 합니다.
리모컨 프리셋 사용 API in 쿼츠 작곡가
mimoLive의 빌드 인 레이어에는 LUA 스크립트를 사용하여 이 데이터 구조를 동적으로 생성할 수 있습니다. 쿼츠 컴포저는 자체적으로 데이터 구조 생성을 지원하지 않기 때문입니다. 쿼츠 컴포저의 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톤 액션
1TP14톤은 여러 개의 액션, 하나의 액션 또는 전혀 없는 액션을 가질 수 있습니다. 동작 대상과 동작 유형의 유효한 조합은 다양합니다.
"textInput" 및 "numericInput" 동작은 리모컨에서 일관된 사용자 환경을 보장하지 않으므로 그 자체로 사용해야 합니다.
조치 대상
액션 타깃은 mimoLive 문서 내부의 요소입니다. 이들은 계층적 방식으로 주소가 지정됩니다:
'문서 ID'는 항상 런타임에 그려지므로 사전 설정에 있을 필요는 없습니다.
- "layerId" 또는 "variantId"가 모두 지정되지 않으면 문서 자체에서 작업이 트리거됩니다.
- "layerId"를 지정하면 지정된 레이어에서 액션이 트리거됩니다.
- "layerId" 그리고 "variantId"가 주어지면 지정된 이형 상품에서 액션이 트리거됩니다. 이 경우에만 추가 "toggleSwitchKey" 또는 "signalKey"를 지정할 수 있습니다(아래 액션 유형 참조).
작업 유형
작업 유형 | 설명 | 추가 속성 | 유효한 대상 |
---|---|---|---|
토글라이브 | 라이브 상태 전환 | 없음 | 문서(쇼 시작/중지), 레이어, 변형 |
setLive | 라이브 상태를 "라이브"로 설정 | 없음 | 문서(표시 시작), 레이어, 변형 |
setOff | 라이브 상태를 "꺼짐"으로 설정 | 없음 | 문서(표시 중지), 레이어, 변형 |
신호 | 신호 트리거 | 신호 키, 신호 이름 (권장) | 변형 |
토글스위치 | 부울 입력 값 토글 | 토글스위치키, 토글스위치이름(권장) | 변형 |
textInput | 제출 시 입력키의 값을 업데이트하는 텍스트 입력 필드를 엽니다. | 입력 키, 입력 이름 (권장) | 레이어, 변형, 소스 |
numericInput | 입력 키의 숫자 값을 제어하는 슬라이더입니다. | 입력 키, 입력 설명(최소값과 최대값이 모두 있는 객체), 입력 이름(권장) | 레이어, 변형, 소스 |
"textInput" 및 "numericInput" 액션 유형은 mimoLive 5.2부터 사용할 수 있습니다.
1TP7톤 라이브 상태
"liveState" 개체를 사용하여 버튼의 탈리 라이트 상태를 설정할 수 있으며, 켜짐(빨간색 표시), 전환(노란색 표시) 또는 꺼짐(표시 없음)으로 설정할 수 있습니다.
라이브 상태 소스
버튼 액션 타겟과 마찬가지로 라이브 상태는 여러 소스에서 가져올 수 있습니다:
- '문서 ID'는 항상 런타임에 그려지므로 사전 설정에 있을 필요는 없습니다.
- "layerId" 또는 "variantId"가 모두 지정되지 않으면 문서의 라이브 상태가 사용됩니다(표시가 시작되었는지 여부).
- "layerId"가 지정되면 레이어의 라이브 상태가 사용됩니다.
- "layerId"와 "variantId"가 지정되면 이형 상품의 라이브 상태가 사용됩니다.
- 이 경우에만 추가 "propertyPath"를 지정하여 이형 상품의 입력 또는 출력 값에 부울 속성을 사용해야 함을 나타낼 수 있습니다.
- 또 다른 가능성(propertyPath와 상호 배타적입니다!)은 라이브 상태 조회를 선택한 소스(예: 비디오 전환기)의 동적 변경 사항을 반영하는 소스(ID로 가져온)로 리디렉션하는 "dynamicSourceId" 프로퍼티를 지정하는 것입니다. "dynamicSourceId"의 값은 변형의 입력 값에서 조회됩니다.
변형에서 루트로 시작하는 프로퍼티의 전체 경로를 입력합니다(예: "inputValues.some_Boolean_Property" 또는 "outputValues.other_Property").
- "sourceId"가 지정되면 소스의 라이브 상태가 사용됩니다.
1TP7톤 텍스트
작업 버튼은 기본 및 보조 텍스트 줄을 표시할 수 있으며, 둘 다 정적이거나 동적인 특성을 가질 수 있습니다.
기본 텍스트
이 텍스트는 버튼이 사용자에게 어떤 작업을 수행할지 나타내는 기본 표시가 됩니다. 버튼 프리셋에 텍스트 속성이 포함된 경우 정적 텍스트가 그대로 표시됩니다.
또는 간단한 템플릿 구문을 사용하여 mimoLive 레이어 또는 변형 프로퍼티를 포함할 수 있는 dynamicText를 지정할 수 있습니다. 템플릿 문자열에서는 중괄호로 묶인 속성 경로와 일반 문자를 결합할 수 있습니다:
"template": "{\{propertyPath\}}"
속성 경로는 "layerId", "variantId", "sourceId" 및 "filterId"를 사용하여 확인되는 개체를 기준으로 평가됩니다. 대상 확인은 이러한 규칙을 따릅니다:
- '문서 ID'는 항상 런타임에 그려지므로 사전 설정에 있을 필요는 없습니다.
- "layerId" 또는 "variantId"가 모두 지정되지 않은 경우, 속성 경로는 문서를 기준으로 평가됩니다.
- "layerId"(및 선택적으로 "variantId"를 지정하면 레이어/배리언트를 기준으로 속성 경로가 평가됩니다.
- 이형 상품의 상위 레이어는 'aslayer.name'과 같이 '레이어'로 시작하는 경로를 통해 액세스할 수 있습니다.
입력 및 출력 값의 첫 번째 경로 세그먼트는 API 문서에서와 같이 케밥 대소문자("input-values.tvIn...")가 아닌 카멜 대소문자("input-Values.tvIn...")여야 합니다.
- 정적 텍스트는 항상 동적 텍스트보다 우선하므로 사용자가 상황에 더 유용할 수 있는 사용자 지정 텍스트로 동적 텍스트를 덮어쓸 수 있습니다.
보조 텍스트
사용자에게 상위 레이어의 이름과 같은 버튼에 대한 자세한 정보를 제공하려면 "subtext" 또는 "dynamicSubText" 속성을 사용하여 보조 텍스트를 지정할 수 있습니다.
템플릿 구문 및 개체 해상도는 기본 텍스트와 정확히 동일한 규칙을 따릅니다.
1TP7톤 텍스트 및 아이콘 크기
버튼의 아이콘에 표시되는 텍스트는 상황에 따라 크기가 달라질 수 있습니다. "fontScale" 옵션을 사용하면 현재 화면 크기에 대해 계산된 기본 크기에 대한 상대적인 배율을 지정할 수 있습니다. "1"이 기본 크기가 됩니다. 1보다 작으면(예: 0.8) 글꼴 크기가 축소되고 1보다 크면(예: 1.5) 글꼴 크기가 커집니다.
1TP7톤 미리보기
작업 버튼은 제어 중인 소스 또는 문서에서 사용 가능한 다른 소스의 미리보기 이미지를 표시할 수 있습니다.
소스가 정적인지 여부(mimoLive로 드래그한 이미지만 해당)에 따라 정적 PNG 알파 채널을 지원하는 소스의 표현이 한 번 로드됩니다. 다른 소스의 경우 JPEG 소스의 표현은 정기적으로 업데이트됩니다. 동적 소스의 목표 새로 고침 빈도는 초당 5프레임이지만 네트워크 연결 속도가 미리보기 프레임을 반복적으로 로드하기에 충분하지 않다고 판단되면 이 빈도가 감소합니다.
현재 문서의 프로그램 출력을 작업 버튼에 표시하는 것은 지원되지 않습니다. 소스 목록에는 표시되지 않지만 레이어 기본 이미지는 미리 보기에서 사용할 수 있습니다.
소스 미리 보기를 지정하려면 객체 해상도 메커니즘이 사용됩니다:
- '문서 ID'는 항상 런타임에 그려지므로 사전 설정에 있을 필요는 없습니다.
- "sourceId"가 지정되면 해당 ID를 가진 소스가 미리 보기에 사용됩니다.
- "layerId", "variantId" 및 "dynamicSourceId"를 모두 지정하면 지정된 레이어의 변형에서 "dynamicSourceId"의 키 아래에서 소스 ID를 조회합니다. 이는 문서에서 변경된 경우에도 비디오 스위처의 소스 A-G와 같은 소스를 참조하는 데 사용할 수 있습니다.
1TP7톤 색상
'색상' 속성을 사용하면 다음에서 표현할 수 있는 모든 색상 코드로 버튼에 색상을 지정할 수 있습니다. HTML (예: "#f80", "#ff0088", "주황색" 또는 "rgb(255, 66, 88)").
1TP7톤 아이콘
1TP14톤은 기능을 나타내는 아이콘을 표시할 수 있습니다. 사용 가능한 모든 아이콘 목록을 보려면 mimoLive가 실행 중이고 원격 제어가 활성화된 상태에서 http://localhost:8989/icons/demo.html 을 엽니다.
아이콘의 일반 이름(예: "뒤로" 또는 "화살표 아래로")을 사용합니다.