カスタムサイドパネルセクションという機能を使うことで、スクリプトを作成する人は Synthesizer V Studio の画面上に常に表示しておくことができ、かつ、操作可能な独自のパネルを作ることができます。一時的なモーダルダイアログや、メッセージボックスとは異なり、サイドパネルセクションは常にアクセスができるため常設の作業スペースとして役に立ちます。
サイドパネルセクションの作成
サイドパネルセクション用のスクリプトは getClientInfo()
が 「type」:
「SidePanelSection」
を返す必要があり、 main()
の代わりに
getSidePanelSectionState()
関数を実装しなければなりません。さらに、
minEditorVersion
は131330(バージョン2.1.2)以上である必要があります。
基本構造
function getClientInfo() {
return {
"name": "My Panel",
"category": "Utilities",
"author": "Your Name",
"versionNumber": 1,
"minEditorVersion": 131330,
"type": "SidePanelSection"
};
}
function getSidePanelSectionState() {
return {
"title": "My Panel",
"rows": [
// UI ウィジェットをここに定義します。
]
};
}
セクションオブジェクトの構造
getSidePanelSectionState()
が返すオブジェクトは以下のプロパティを含みます:
title
:string
- パネル上部に表示されるタイトルrows
:array
- ウィジェット行の配列
レイアウトシステム
サイドパネルは行と列からなる2階層のレイアウトシステムを採用しています。
- 第1階層 (行):
rows
配列にはLabel
またはContainer
ウィジェットのみを含めることができます - 第2階層 (列):
Container
のcolumns
配列内には、TextBox
、Button
、Slider
などのインタラクティブウィジェットを配置できます
行
行は上から下に垂直に方向に積み重ねられます。各行はラベルまたはコンテナのいずれかである必要があります。
"rows": [
// 行 1: ラベル
{
"type": "Label",
"text": "Search options:"
},
// 行 2: ウィジェットを含むコンテナ
{
"type": "Container",
"columns": [
{
"type": "TextBox",
"value": searchValue,
"width": 1.0
}
]
},
// 行 3: もう一つのラベル
{
"type": "Label",
"text": "Results:"
}
]
列と相対幅指定
複数のウィジェットを並べて配置するには、 columns
配列を持つ Container ウィジェットを使用します。列内の各ウィジェットは、利用可能な水平方向のスペースに対する相対的な割合を表す width
プロパティを指定します。
{
"type": "Container",
"columns": [
{
"type": "Button",
"text": "Left",
"value": leftButtonValue,
"width": 0.3 // 幅30%
},
{
"type": "Button",
"text": "Right",
"value": rightButtonValue,
"width": 0.7 // 幅70%
}
]
}
ウィジェットシステム
WidgetValue
サイドパネルセクションは、UIとスクリプト間で双方向にデータを伝送するためにWidgetValue
オブジェクトを使用します。SV.create(「WidgetValue」)
で作成します。
var myValue = SV.create("WidgetValue");
myValue.setValue(0); // 初期化
myValue.setEnabled(true); // ウィジェットの有効化/無効化
// 変更に応答するコールバック
myValue.setValueChangeCallback(function(newValue) {
// 変更への対応
});
ウィジェットタイプ
TextBox
単一行のテキスト入力ウィジェットです。
var textValue = SV.create("WidgetValue");
textValue.setValue("initial text");
{
"type": "TextBox",
"value": textValue,
}
TextArea
複数行テキストの表示または入力を行うためのウィジェットです。
var textAreaValue = SV.create("WidgetValue");
textAreaValue.setValue("Multi-line\ntext here");
{
"type": "TextArea",
"value": textAreaValue,
"height": 80, // ピクセル単位の高さ
}
Button
クリック可能なアクションを実行するボタンです。
// 内部の値は重要ではありません。
// 主にコールバックの受信と、有効/無効状態の設定のために使用されます。
var buttonValue = SV.create("WidgetValue");
buttonValue.setValueChangeCallback(function() {
// Button clicked
SV.showMessageBox("Info", "Button pressed!");
});
{
"type": "Button",
"text": "Click Me",
"value": buttonValue,
}
Slider
範囲と書式を設定可能な数値スライダーです。
var sliderValue = SV.create("WidgetValue");
sliderValue.setValue(3);
{
"type": "Slider",
"text": "Volume",
"format": "%3.1f dB", // printfスタイルの書式指定
"minValue": -6,
"maxValue": 6,
"interval": 0.1,
"value": sliderValue,
}
書式設定の例:
"%3.2f beats"
- 単位付き、小数点以下2桁を表示"%3.0f %%"
- 整数でのパーセント表示"%2.1f Hz"
- 単位付き、小数点以下1桁を表示
CheckBox
真偽値を扱うチェックボックスのウィジェットです。
var checkValue = SV.create("WidgetValue");
checkValue.setValue(true);
{
"type": "CheckBox",
"text": "Apply this to all notes in the group",
"value": checkValue,
}
ComboBox
ドロップダウンセクションを扱うウィジェットです。
var comboValue = SV.create("WidgetValue");
comboValue.setValue(0); // 選択されている項目の添え字
{
"type": "ComboBox",
"choices": ["Option 1", "Option 2", "Option 3"],
"value": comboValue,
}
エディタイベントへの応答
サイドパネルのセクションは、コールバックを使用してエディタの状態変化に応答できます。
選択範囲の変更
SV.getMainEditor().getSelection().registerSelectionCallback(function(selectionType, isSelected) {
if(selectionType == "note") {
// ノートの選択状態変更に応じて、UIを更新します。
...
}
});
SV.getMainEditor().getSelection().registerClearCallback(function(selectionType) {
if(selectionType == "notes") {
// 全てのノートの選択が解除に応じて、UIを更新します。
...
}
});
使用例
var SCRIPT_TITLE = "Selected Note Counter";
function getClientInfo() {
return {
"name": SCRIPT_TITLE,
"category": "Utilities",
"author": "Dreamtonics",
"versionNumber": 1,
"minEditorVersion": 131330,
"type": "SidePanelSection"
};
}
var countValue = SV.create("WidgetValue");
var setLyricsButtonValue = SV.create("WidgetValue");
countValue.setValue("0 notes selected");
countValue.setEnabled(false);
function updateSelectionCount() {
var selection = SV.getMainEditor().getSelection();
var selectedNotes = selection.getSelectedNotes();
var count = selectedNotes.length;
countValue.setValue(count + " note" + (count === 1 ? "" : "s") + " selected");
setLyricsButtonValue.setEnabled(count > 0);
}
setLyricsButtonValue.setValueChangeCallback(function() {
var selection = SV.getMainEditor().getSelection();
var selectedNotes = selection.getSelectedNotes();
if(selectedNotes.length === 0) return;
SV.getProject().newUndoRecord();
for(var i = 0; i < selectedNotes.length; i ++) {
selectedNotes[i].setLyrics("a");
}
});
// 選択コールバックを登録して、カウントを自動的に更新する
SV.getMainEditor().getSelection().registerSelectionCallback(function(selectionType, isSelected) {
if(selectionType == "note") {
updateSelectionCount();
}
});
SV.getMainEditor().getSelection().registerClearCallback(function(selectionType) {
if(selectionType == "notes") {
updateSelectionCount();
}
});
// 初期化
updateSelectionCount();
function getSidePanelSectionState() {
return {
"title": SCRIPT_TITLE,
"rows": [
{
"type": "Label",
"text": "Selection:"
},
{
"type": "Container",
"columns": [
{
"type": "TextBox",
"value": countValue,
"width": 1.0
}
]
},
{
"type": "Container",
"columns": [
{
"type": "Button",
"text": "Set lyrics to 'a'",
"value": setLyricsButtonValue,
"width": 1.0
}
]
}
]
};
}