【MotionBuilder】Python SDK 入門 第7回 『UI・ツール開発-基礎編』

2024/07/31に公開

この記事は、Python SDK 入門の第7回目の記事です。
今回から、MotionBuilderでのUI・ツール開発について解説していきます。第1回でも書いた通り、今回から3回に分けて『UI・ツール開発』をテーマに、SDKのみで完結する方法、Qt(PySide)を利用する方法、PySideの使用例の3つを解説します。

UIの概説

MotionBuilderのUIがどんな構成で、各部がどんな名称をもつのか解説します。

MainWindow

パソコンで開く一つ一つのアプリケーションの”窓”としてのウィンドウと同じ。

MainWindow。赤枠で囲った部分

Window

MainWindowの次に大きい、別々の働きをもったUIの要素。

Window。カラーの枠で囲ったそれぞれの部分

一つ一つに固有の名前が付いており、Viewer Window, Navigator Window, Resources Windowなどがあります。これらの名前は各Windowの中央上部に記載されて、また、ウィンドウと同じようなアイコンが右上に表示されています。

Windowの名称とホバー・削除ボタン

Layout

WindowにおいてUIの要素を整列させる働きをするもの。
視覚的にその存在を認識できるわけではありません。画面左上Layoutから選択できるそれぞれの”Layout”とはまた別物です(そのLayoutとはWindowの配置を指します)。

Region

Layoutの中にUIの要素を埋め込むために確保される領域のようなもの。
これもまた視覚的にその存在を認識できるわけではありません。

Component

MotionBuilderのUIの最小の構成単位。

1. ラベル、2. 入力、3. ボタン

FBVisualComponentクラス

Visual Component base class.
All of the user interface elements available in the SDK derive from this class.
- FBVisualComponent Class Reference

上記のUIの要素は、SDKにおいてFBVisualComponentクラスおよびその継承クラスで利用できます。

FBToolクラスとTool Manager

A tool in MotionBuilder is a new user interface layout adding to the current functionality of the software. Extensive user interface elements are available.
The FBTool class (found in the fbtool.h file) is manipulated as a layout, with all of the functionality that comes with a traditional layout. Regions can be added, moved, and controlled.
- Tools - Help

ツール(Tool)というのは新たにUIを追加するもので、片仮名の”ツール”のイメージとは少々異なりUIの要素の一つというイメージが近いです。FBToolクラスも、FBVisualComponentクラスを継承したFBLayoutクラスをさらに継承したクラスであるため、Layoutと似た扱いをされます。

Pythonで作成し特定の操作で登録したToolはPython Tool Managerにまとめられます。

Scripting Layoutで表示されたPython Tool Manager Window

もちろんスクリプトでも確認できます。pyfbsdk_additions.FBGetTools()はPython Tool Managerに登録されているToolの名前とそのインスタンスの辞書を返します。

from pyfbsdk_additions import*
for toolName in FBGetTools().keys():
    print(toolName)
>>>
Batch Tool (scripted)
Character Selection/Key Controls
FBX Export
Keyboard Shortcuts Editor
Tool Window


基本的なツールと関数等の解説

サンプルでよく見られる構成を用いたテンプレートで、UI・ツール作成に用いる基本的な関数等の解説をします。

基本のテンプレート

BasicTool.py
# -*- coding: utf-8 -*-
# ラベル・リスト・ボタンから成る基本的なツール

from pyfbsdk import *
from pyfbsdk_additions import *


def PopulateLayout(tool:FBTool):
    x = FBAddRegionParam(0,FBAttachType.kFBAttachLeft,"")
    y = FBAddRegionParam(0,FBAttachType.kFBAttachTop,"")
    w = FBAddRegionParam(0,FBAttachType.kFBAttachRight,"")
    h = FBAddRegionParam(0,FBAttachType.kFBAttachBottom,"")
    tool.AddRegion("MainRegion","RegionName", x, y, w, h)
    
    vbox = FBVBoxLayout( FBAttachType.kFBAttachTop )
    tool.SetControl("MainRegion",vbox)
    
    Label1 = FBLabel()
    Label1.Caption = "Label1"
    vbox.Add(Label1, 30)

    List1 = FBList()
    List1.style = FBListStyle.kFBDropDownList
    for i in range(5):
        # list item must be string
        List1.Items.append(str(i))
    vbox.Add(List1, 30, space = 10)

    Button1 = FBButton()
    Button1.Caption = "Button1"
    vbox.Add(Button1, 30, space = 10)


def CreateTool():
    t = FBCreateUniqueTool("BasicTool")
    t.StartSizeX = 400
    t.StartSizeY = 400
    PopulateLayout(t)    
    ShowTool(t)

CreateTool()

from pyfbsdk_additions import*

This module improves pyfbsdk UI building.
It provides Layout classes similar to classes found in Qt/GTK/Tcl/Tk that helps to manage region handling and UI control positioning.
It also gives functions to create/destroy and manage Tools created in Python.
- pyfbsdk_additions Namespace Reference

pyfbsdk_additionsモジュールは、主にUIやToolに関わる機能を提供するモジュールです。具体的には後述するFBCreateUniqueTool()FBVBoxLayoutなどを定義しています。

FBCreateUniqueTool()

FBCreateUniqueTool(toolName:str) -> FBTool

この関数はToolの名前を引数に取ってToolを作成し、Python Tool Managerに登録します。FBTool()コンストラクタで作成したToolはTool Managerには登録されません。似た名前の関数でFBCreateTool()があるのですが、この関数は同名のToolを作成した場合下図のように接尾辞がついて作成されます。

FBCreateTool()でToolを作成した場合

FBCreateUniqueTool()の場合は、同名のToolが既に作成されている場合はそのToolは削除され、新たにToolが作成されます。

ドキュメントより

また、この関数はFBTool型インスタンスを返します。FBLayout型は返しません

FBLayout().AddRegion() / FBAddRegionParam()

FBLayout().AddRegion()関数はLayoutに対して「位置・幅・高さ」を指定してUI構成要素の存在領域(Region)を確保する働きをします。この時「位置・幅・高さ」はただの数字で指定するのではなく特殊なパラメータを用いるのですが、そのパラメータを作成するのがFBAddRegionParam()関数です。


FBAddRegionParam Class Reference

FBAttachTypeは直接的には「UIのどこに沿わせるのか」を指定するのですが、これはUIを拡張・収縮させたときに構成要素がどう伴って動くか、を指定するのと同義です。

AddRegion()関数をドキュメントを調べるとその引数の多さに面食らいますが、下記のようにまとまりで考えると上記のFBAddRegionParam()の引数と一致することが分かるでしょう。

FBLayout Class Reference

FBAddRegionParam()関数を用いることで、AddRegion()関数について記述が簡潔になります。

tool = FBTool()
# x,y,w,h はそれぞれFBAddRegionParam()で定義
tool.AddRegion("MainRegion","RegionName", x, y, w, h)

次節で述べますが、AddRegion()関数の第1引数は重要です。というのも、AddRegion()関数でUI構成要素のための領域を確保したのはいものの、肝心の構成要素をその領域に据え置く操作が残っていて、その際にこの第1引数が必要だからです。

ちなみに、前節でFBCreateUniqueTool()はFBLayoutではなくFBTool型インスタンスを返すと書きましたが、FBToolクラスはFBLayoutクラスを継承しているため、FBLayoutクラスのAddRegion()メンバ関数が使用できます。

FBLayout().SetControl()

FBLayout().SetControl()関数は、引数のVisual Componentに対してそのLayout内のRegionに対して制御を与える、といった働きをします。


ドキュメントより

FBLayoutクラスや、UIの構成要素(FBLabel, FBButton, FBListなど)も全てこのFBVisualComponentsクラスを継承しています。SetControl関数は、第1引数でRegion名(前節で触れた、AddRegion()関数の第1引数) を、第2引数でFBVisualComponents型インスタンスを指定します。

tool = FBTool()
label = FBLabel()
tool.SetControl("MainRegion", label) # AddRegionで指定したRegion名を使う

こうして予め確保した領域に対して各種UIの構成要素を据え置くことができます。第6回の最後でMotionBuilderが落ちる原因を説明した際に触れたのは、これらの関数の引数が一致していないためにSetControlが存在しないRegionに対してvisual componentの制御を許可しようとしたからです。
もちろん、SetControlの第2引数にはFBLayout型インスタンスを指定することも可能です。

FBBoxLayout.Add()

上で紹介したFBAddRegion()を用いることなく、簡単にLayoutに対してボタンやラベルなどを配置できる関数です。ドキュメントでは一見引数が3つ、サンプルでは引数が2つのように見えますが、実際は通常の引数「size」とキーワード引数の「customparams」を引数に取ります。

FBVBoxLayoutのAdd()メンバ関数

FBVBoxLayout.Add()ではspace,width,heightの3つが指定できるようです。下記のように使います。

Button1 = FBButton()
vbox = FBVboxLayout()
vbox.Add(Button1, 30, space = 10, width = 100, height = 50)

キーワード引数の指定とその個数は任意です。

ShowTool()

この関数はOpenRealityドキュメントにもPythonドキュメントにも登場しません。他の関数と同様に、help()関数を用いて詳細を調べてみます。

この関数はFBTool型インスタンスを引数に取り、そのToolを画面に表示するために専ら用います。似た関数にShowToolByName()関数がありますが、これはTool名を指定してToolを表示させることができます。もちろん、その名前をもつToolが事前に作成されていることが前提ですが。

ShowToolByName("Tool Name")


次回

今回は『UI・ツール開発』のテーマの初回として、SDKの基本の関数のみで完結するツールのテンプレートを示しました。次回はPySideの利用方法とツール開発の流れを説明します。

それでは、今回はここまで。最後までお読みくださりありがとうございました。

Discussion