🔧

【DaVinci Resolve】Fusionページの右クリックメニュー項目を追加する方法

2024/10/23に公開

まえがき

こんにちは。火注ゆかなです。
今回の記事は右クリック時に表示されるコンテキストメニューの項目を追加する方法です。こんな風に。


コンテキストメニューに「InputControlテスト」「SliderControlテスト」が追加されている

独自の処理をしたいと思った際、一々メニューバーから「ワークスペース」→「スクリプト」で選択しなくても良くなります。便利ですよね。
設定できるのが Fusion ページだけでなければ最高だったんですけど。

とはいえ、ノードに対して、あるいはインスペクタのコントロールに対して実行できるだけでも使いやすくなるかもしれません。
では説明に入りましょう。

メニュー項目を追加する方法

fu ファイルの設定方法については We Suck Less フォーラムの一部トピックを参考にしました。
https://www.steakunderwater.com/wesuckless/viewtopic.php?p=26730
https://www.steakunderwater.com/wesuckless/viewtopic.php?p=11921#p11921

fuファイルについて

fuファイルとは Fusion 関連のコンフィグ設定ファイルのようです。
あくまで Fusion のみで、Editページなど他の部分には影響しません。

なんで Fusion のみなのかというと、そもそも Fusion は Eyeon Software という会社が開発したアプリケーションでした。[1]
2014年に BlackMagicDesign が Eyeon Software を買収し、DaVinci Resolve に Fusion が組み込まれたという経緯があります。
なので、Fusion 部分とその他の部分で完成度が違うんですよね。

fuファイル は Eyeon Software 時代に実装された Fusion 専用機能なのだと考えれば、他のページの設定ができないことにも納得がいきます。残念ながら。

話を戻しましょう。

fuファイルではメニュー追加の他に、ホットキー(ショートカットキー)設定、アクショントリガー設定もあるようです。
残りの機能については追々説明するとして、今回はメニューの追加のみ説明していきます。

fuファイルの置き場所

fuファイルはConfig:パスマップフォルダに置くとアプリ起動時に読み込まれます。
ファイルの拡張子は.fuです。

パスマップとかよくわからんって人は以下のフォルダに置いてください。
C:\ProgramData\Blackmagic Design\DaVinci Resolve\Fusion\Config\

fuファイルの記述

メニュー追加時の構文

メニュー項目を追加するための構文はこんな感じです。

format.fu
{
    Menus {
        Target = "ChildFrame",  -- Fusion ページのどこで右クリックしたときのメニュー項目を追加するか
        Before "ステレオ" {     -- メニュー項目のどの位置に追加するか(今回はステレオの前)
            'Execute { Name = "ChildFrameテスト1", cmd = [[dump(obj)]]}',    -- 実行するアクション、メニューに表示する名前、アクションの引数を指定
            'Execute { Name = "ChildFrameテスト2", cmd = [[dump(obj)]]}',    -- カンマ区切りで連続挿入も可能
            '_',    -- 半角アンダーバーでセパレータ挿入
        }
    },

    -- 複数のメニュー項目を追加したい場合、上記の記述をカンマ区切りで繰り返す
    Menus {
        Target = "ChildFrame",  -- Fusion ページのどこで右クリックしたときのメニュー項目を追加するか
        After "ステレオ" {      -- メニュー項目のどの位置に追加するか(今回はステレオの後)
            'Execute { Name = "ChildFrameテスト3", cmd = [[dump(obj)]]}',    -- 実行するアクション、メニューに表示する名前、アクションの引数を指定
        }
    },
}


イメージビューのコンテキストメニューに項目が追加された

実行できるアクションはcomp:DoAction(action_id, {args})で実行できるものみたいです。
とはいえ、Fusion用のアクションでないと出来ないことは少ないので、基本的にはコマンドを実行するExecuteが使えれば事足りるでしょう。

RunScriptも使えるかと思いましたが、こちらは Windows 環境だと全角文字を含むファイルパスを参照できないという欠点があるので微妙です。
(文字エンコードを UTF-8 → SJIS に変換すれば良いのですが、それを1行に収めるのは難しいので。特にLuaの場合は。)

一応、Reactor のActionListener.lua起動時に取得した他アクション一覧はトグル内に記載しておきます。
AddToolなど、一部のアクションは Fusion Scripting Guide のFusion、あるいはCompositionのメソッドに同名のものがあるので、その引数名を参考にすれば一応使えるかと。

Fusion アクション一覧(216個)

Bin_New_Reel
Bin_New_Folder
Bin_New_Item
Bin_Icon_Size
Bin_Show_Checker
Bin_View_Mode
Player_Item_Next
Player_Item_Prev
Player_Play
Player_Play_Forward
Player_Play_Reverse
Player_Seek_By
Player_Seek_To
Player_Seek_Start
Player_Seek_End
Player_Seek_Prev
Player_Seek_Next
Player_Set_Loop
Player_Trim_Set_In
Player_Trim_Set_Out
Player_Gamma
Player_Gain
Player_Set_FPS
Player_Set_Time
Player_Guide_Enable
Player_Guide_Select
Player_Channel
Player_Show_Metadata
Player_Sync_Mode
Player_Loop_Set_In
Player_Loop_Set_Out
Player_Loop_Reset
Player_Loop_Set_Shot
Player_Device_DeckLink
Fusion_Screen_Mode
Fusion_View_Show
Fusion_Zone_Expand
Fusion_Time_Set
Fusion_Time_Get
ACTION_GET_TEMPLATES_LIST
ACTION_GET_UI_LAYOUT
ACTION_SET_UI_LAYOUT
ACTION_SHOW_CONSOLE -- コンソールの表示/非表示切り替え
ACTION_PRINT_CONSOLE
ACTION_CLOSE_COMP
ACTION_INSTALL_FILE
No_Action
Viewer_Checker_Enable
Viewer_ROI_Enable
Viewer_ROI_Auto
Viewer_ROI_Lock
Viewer_ROI_Set
Viewer_ROI_Reset
Viewer_DOD_Enable
Viewer_3D_Lighting
Viewer_3D_Wireframe
Viewer_3D_Solid
Viewer_3D_Lights
Viewer_3D_Shadows
Viewer_3D_Transparency
Frame_Activate_SubWnd
Frame_Activate_Frame
Frame_Activate_Next
Frame_Activate_Prev
Comp_Choose_Tool
Comp_Choose_Action
Execute -- 指定コマンドを実行
Comp_New
Comp_Open
Comp_Save
Comp_SaveVersion
AddTool -- ツールを追加(id="Underlay" という風にID指定可能)
AddLUT
RunScript -- 指定パスのコマンドファイルを実行
AddSetting -- 指定パスのマクロ追加?
Layout_Switch
Prefs_Show
App_Exit
Comp_BackgroundRender
Comp_Undo
Comp_Redo
Comp_ShowTimeCode
Comp_TimeCodeFormat
App_About
App_NewImageView
Comp_NewTabbedFrame
Comp_NewFloatFrame
App_Help
App_OnlyActiveComp
App_ShowUI
App_CustomizeToolBars -- Fusionページで使えるツールバーをカスタマイズできる
App_CustomizeHotkeys
App_Cut
App_Copy
App_Paste
App_Delete
App_SelectAll
App_DeselectAll
App_PasteSettings
View_Show
Comp_Close
Comp_SaveAs
Comp_SaveCopyAs
Script_Edit
Layout_Load
Layout_Save
Layout_Reset
Comp_Recent_Open
Comp_Recent_Clear
Utility_Show
Tool_ViewOn
Tool_ViewClear
Bins_Play
Bins_Stop
Bins_Delete
Bins_Rename
Bins_Refresh
Bins_SelectAll
Time_Step_Forward
Time_Step_Back
Time_Step_NextKey
Time_Step_PrevKey
Time_Goto_GlobalStart
Time_Goto_GlobalEnd
Time_Goto_RenderStart
Time_Goto_RenderEnd
Time_Set
Tool_Settings_Activate
Tool_Settings_Store
Viewer_SubView_Enable
Viewer_Lock
Viewer_QuadView
Viewer_Scale_Rel
Viewer_Scale_Abs
Viewer_Buffer
Viewer_Reset
Viewer_SubView_Swap
Viewer_Tools_Disable
Viewer_Unview_All
Viewer_LUT_Enable
Viewer_Show_GainGamma
Viewer_LUT_Edit
Viewer_Channel
Viewer_Guides_Show
Viewer_Controls_Show
Viewer_3D_CentreSelected
Viewer_3D_FitSelected
Viewer_3D_FitAll
View_Zoom_In
View_Zoom_Out
View_Zoom_Fit
View_Zoom_Rectangle
Time_Goto_Key_Next
Time_Goto_Key_Prev
Playback_Mode
Playback_Seek
Playback_Seek_Start
Playback_Seek_End
NetRender_Allow
Comp_Render_Frame
Comp_Render_End
Comp_Activate_Tool
Comp_Set_Active
Comp_StartRender
Comp_Start_Render
Comp_Render
Comp_Abort
Comp_Opened
Drag_Drop
Comp_High_Quality
Comp_Motion_Blur
Comp_Proxy
Comp_Auto_Proxy
Comp_Play_Loop
Comp_Play_PingPong
Reel_Delete_Selected
Target_Show_Menu
Target_Show_Scripts
Console_Show
Comp_Reset
Expose_Tool_Name_Mode
License_Deactivate
Flow_Add_Bookmark
Flow_Go_To_Bookmark
Flow_Manage_Bookmarks
ShapeViewer_Checker_Enable
Effects_ShowSearch
Effects_Search
GraphView_ZoomToFit
GraphView_SortMenu
GraphView_ZoomX
KeyframeView_ZoomY
GraphView_ZoomY
Reactor_Open
Reactor_Reinstall_Reactor
Reactor_Atomizer
Reactor_Fu_Scanner
Reactor_Fuse_Scanner
Reactor_Macro_Scanner
Reactor_Plugin_Scanner
Reactor_Folder
Reactor_Docs_Folder
Reactor_Comps_Folder
Reactor_Config_Folder
Reactor_Temp_Folder
Reactor_Resync
Reactor_Open_Reactor_Log
Resources_Reactor_Online_Repository
Resources_Online_Discussion
Resources_WSL
Resources_Bug_Tracker
Reactor_Prefs
Reactor_About
Open_Comp_in_Script_Editor
Open_All_Comps_In_Script_Editor

複雑なコマンドの記述方法

複雑なコマンドを実行させたい場合、Actionを定義し、それを実行するように設定します。

define_action.fu
{
    -- アクション定義
    Action {
        ID = "ActionTest",              -- アクションID
        Name = "アクション定義テスト",    -- メニュー項目名
        Targets = {
            Composition = {
                Execute = _Lua [=[             -- コマンド文字列の前に _Lua を付ける
print("ユーザによって定義されたアクションです。")  -- ここにLuaコマンドを記述してください
dump(obj)
			    ]=],
            },
        },
    },

    -- 追加メニュー定義
    Menus {
        Target = "ChildFrame",  -- Fusion ページのどこで右クリックしたときのメニュー項目を追加するか
        After "ステレオ" {      -- メニュー項目のどの位置に追加するか(今回はステレオの後)
            'ActionTest{}',     -- 定義したアクション実行
        }
    },
}

実行するコマンドを Python で記述することもできます。

define_py_action.fu
{
    Language = "Python3",       -- コマンドをPythonで指定したい場合はここで言語指定する

    -- アクション定義
    Action {
        ID = "ActionTest",              -- アクションID
        Name = "アクション定義テスト",    -- メニュー項目名
        Targets = {
            Composition = {
                Execute = _Python [=[          -- コマンド文字列の前に _Python を付ける
print("ユーザによって定義されたアクションです。")  -- ここにPythonコマンドを記述してください
print(obj)
			    ]=],
            },
        },
    },

    
    -- 追加メニュー定義
    Menus {
        Target = "ChildFrame",  -- Fusion ページのどこで右クリックしたときのメニュー項目を追加するか
        After "ステレオ" {      -- メニュー項目のどの位置に追加するか(今回はステレオの後)
            'ActionTest{}',     -- 定義したアクション実行
        }
    },
}

メニュー項目を追加できる箇所

具体的にどの部分に設定できるのかわからないと設定のしようがないですよね。
確認が取れている箇所は以下の通りです。


メニュー項目を追加できる箇所一覧

設定箇所 Target objで取得できるオブジェクト
イメージビュー ChildFrame
FuFrame
GLView
PreviewContainer
GLView
タイムビュー TimeView TimeView
ツールバー ActionStripView ActionStripView
フロービュー FlowView FlowView
ノード Operator(全種類のノード)
ノードの種類を限定したいときはTextPlusのようにノードの種類を指定
実行箇所により異なる
Flow (フロービュー上)
各種ノード(スプラインエディタの項目名、またはキーフレームエディタのグラフ)
スプラインエディタ SplineEditorView SplineEditorView
キーフレームエディタ TimelineView TimelineView
エフェクトビュー EffectView Effect Library
(インスペクタ)
ツール
ControlView なし( nil or None )
(インスペクタ)
モディファイア
ModifierView なし( nil or None )
コントロール InputControl(全種類のコントロール)
コントロールの種類を限定したいときはSliderControlのように明確に指定
各種InputControl

確認用のスクリプトはこちらです。
これをConfig:パスマップフォルダに放り込んでアプリを再起動すれば、右クリックした時にどのメニュー項目が追加されてるか確認できます。
実行すると取得オブジェクトをコンソールに表示します。

どんな処理を追加するにせよ、まずはどこで実行するとどんなオブジェクトが返ってくるか確認してみることをオススメします。

add_menu_example.fu
{    -- ここの括弧を忘れずに

    -- 上側(イメージビュー(ChildFrame, FuFrame, GLView, PreviewContainer のどれを指定しても特に違いはない?))
    Menus {    -- メニュー追加(成功、ただしFuFrameと被る)
        Target = "ChildFrame",    -- メニューの追加先(Fusionのビュー)
        Before "ステレオ" {        -- メニュー項目の追加位置
            'Execute { Name = "ChildFrameテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加(成功、ただしChildFrameと被る)
        Target = "FuFrame",    -- メニューの追加先(Fusionのビュー)
        Before "ステレオ" {        -- メニュー項目の追加位置
            'Execute { Name = "FuFrameテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加
        Target = "GLView",    -- メニューの追加先
        After "ステレオ" {        -- メニュー項目の追加位置
            'Execute { Name = "GLView Test", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加(成功)
        Target = "PreviewContainer",    -- メニューの追加先
        After "ビュー" {        -- メニュー項目の追加位置
            'Execute { Name = "PreviewContainerテスト",  cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加(成功)
        Target = "TimeView",    -- メニューの追加先(イメージビューの下、再生フレーム)
        After "Auto Render Range" {        -- メニュー項目の追加位置
            'Execute { Name = "TimeViewテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加
        Target = "ActionStripView",    -- コンテキストメニューの追加先(TimeViewの下、使用頻度の高いツールのアイコンが並んでるツールバー)
        After "カスタマイズ" {        -- メニュー項目の追加位置
            'Execute { Name = "ActionStripViewテスト", cmd = [[dump(obj)]]}',
        }
    },

    -- 下側(フロービュー関連)
    Menus {    -- メニュー追加(成功)
        Target = "FlowView",    -- コンテキストメニューの追加先(ノードを配置するフロービュー)
        After "ツールを追加" {        -- メニュー項目の追加位置("ツールを追加"の後。言語設定に応じたメニュー項目名を指定すること)
            'Execute { Name = "FlowViewテスト", cmd = [[dump(obj)]]}',
            'AddTool { Name = "Add Underlay", id = "Underlay"}',
            '_',    -- 半角アンダーバー1つはセパレータを挿入できる
        }
    },    
    Menus {    -- メニュー追加(成功、ただし、KeyframesView、SplineEditorViewや、インスペクタのノード名の枠でも追加される。範囲が広い。
            --          また、objを実行するとSplineEditorViewのグラフではSplineEditorが返る。ノードがアクティブな場合に表示されるのでバグかも。FlowViewではFlowが返る)
        Target = "Operator",    -- コンテキストメニューの追加先(ノード)
        After "表示" {        -- メニュー項目の追加位置
            'Execute { Name = "Operatorテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加(成功)
        Target = "TextPlus",    -- コンテキストメニューの追加先(ノード(種類指定))
        Before "表示" {        -- メニュー項目の追加位置
            'Execute { Name = "TextPlusテスト", cmd = [[dump(obj)]]}',
        }
    },
    
    Menus {    -- メニュー追加(成功、ただしOperatorも表示される)
        Target = "SplineEditorView",    -- コンテキストメニューの追加先(スプラインエディタ)
        After "表示" {        -- メニュー項目の追加位置
            'Execute { Name = "SplineEditorViewテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加(成功)
        Target = "TimelineView",    -- コンテキストメニューの追加先(Keyframesのビュー)
        After "スケール" {        -- メニュー項目の追加位置
            'Execute { Name = "TimelineViewテスト", cmd = [[dump(obj)]]}',
        }
    },
    
    -- 左側(エフェクト)
    Menus {    -- メニュー追加(成功)
        Target = "EffectView",    -- メニューの追加先(エフェクト一覧)
        After "Show Folder" {        -- メニュー項目の追加位置
            'Execute { Name = "EffectViewテスト", cmd = [[dump(obj)]]}',
        }
    },
    
    -- 右側(インスペクタ)
    Menus {    -- メニュー追加(成功、ただ、ページのところだけ? ページで実行するとobjがnilを返す)
        Target = "ControlView",    -- コンテキストメニューの追加先(ツール)
        After "アイコンとラベルを表示" {        -- メニュー項目の追加位置
            'Execute { Name = "ControlViewテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加(成功、ただ、ページのところだけ? ページで実行するとobjがnilを返す)
        Target = "ModifierView",    -- コンテキストメニューの追加先(モディファイア)
        After "アイコンとラベルを表示" {        -- メニュー項目の追加位置
            'Execute { Name = "ModifierViewテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加
        Target = "InputControl",    -- コンテキストメニューの追加先(コントロール全般)
        After "アニメート" {        -- メニュー項目の追加位置
            'Execute { Name = "InputControlテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加
        Target = "InputControl",    -- コンテキストメニューの追加先(コントロール全般)
        After "設定をペースト" {        -- メニュー項目の追加位置(アニメーション・モディファイア設定不可の場合用。「アニメート」が表示されないため)
            'Execute { Name = "InputControlテスト", cmd = [[dump(obj)]]}',
        }
    },
    Menus {    -- メニュー追加
        Target = "SliderControl",    -- コンテキストメニューの追加先(コントロール(種類指定))
        After "アニメート" {        -- メニュー項目の追加位置
            'Execute { Name = "SliderControlテスト", cmd = [[dump(obj)]]}',
        }
    },
    
    
    
    -- メディアプールには追加できなかった
    -- Menus {    -- メニュー追加
        -- Target = "MediapoolView",    -- コンテキストメニューの追加先
        -- After "新規ビン" {        -- メニュー項目の追加位置
            -- 'Execute { Name = "メディアプールテスト", cmd = [[dump(obj)]]}',
        -- }
    -- },
}


注意点:アプリの言語設定について

影響する人はほぼいないと思いますが、一つ注意点があります。
それはアプリの言語設定です。

メニュー項目を追加する際は、下記のようにAfter "既存のメニュー項目"という形で挿入先の基準を指定しますよね。

{
    Menus {    -- メニュー追加
        Target = "SliderControl",    -- コンテキストメニューの追加先(コントロール(種類指定))
        After "アニメート" {        -- メニュー項目の追加位置(「アニメート」という項目の後へ追加)
            'Execute { Name = "SliderControlテスト", cmd = [[dump(obj)]]}',
        }
    },
}

基準となるメニュー項目はGUI上で表示されている通りでなければ駄目です。

例えば、上記のコードだとアプリの言語設定を英語に変更した場合、メニュー項目が追加されません。
英語の場合はAnimateという項目名になり、挿入先の基準として参照できなくなるからです。


日本語設定だと「アニメート」の下に「SliderControlテスト」を追加している

英語設定だと「アニメート」という表示ではないため、追加位置を見失ってしまう

簡単に言うと、別言語圏に メニュー追加用の fu ファイルを配布しようとした場合、そのままだと機能しないということです。配布先の言語に合わせて修正する必要があります。

まあ、別言語圏へ fu ファイルを配布することはほぼないとは思うんですけれど。
逆に英語圏の開発者が配布した fu ファイルをダウンロードして適用しても、何故か機能しない……という可能性はあります。

あとがき

メニュー項目の追加については以上となります。

色々な箇所に設定できると説明しましたが、正直なところ、ノードとコントロールに設定できれば充分だと思います。
特にコントロールに追加したメニュー項目は Edit ページのインスペクタでも実行できますので。

具体的にどんな機能を追加すれば良いかは……ノードだとモディファイアのベイク(キーフレームアニメーションへの変換)とか?
ちょっと思いつかないので各自でお考え下さい。

今回の記事もみなさんのお役に立てば幸いです。それでは。

脚注
  1. PRONEWS記事「ブラックマジックデザイン、Eyeonを買収。映像制作環境に新たな革命!」より ↩︎

Discussion