【MotionBuilder2024】Python Script Tips



# 1)公式ドキュメント
[Python Reference GuideSearch](https://help.autodesk.com/view/MOBPRO/2024/ENU/?guid=MotionBuilder_SDK_py_ref_index_html "Python Reference GuideSearch")


# 2)Python Editor
Window -> Python Editor
![pythoneditor.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717510/c1076e65-7d36-4b5d-d78a-a50b8982660b.png)




# 3)簡単なスクリプト例
### Cubeの作成と操作
初めにモジュールをインポート
```py
from pyfbsdk import *
```
Cubeを作成して表示させ、大きくする
```py
cube = FBModelCube("Cube")
cube.Show = True
cube.Scaling = FBVector3d(10, 10, 10)
```
Cubeを選択
```py
cube.Selected = True
```
Cubeを消す
```py
cube.FBDelete()
```



### 位置と大きさを指定してCubeを作成する関数を実行
```py
from pyfbsdk import *

def CreateCube(xPos, yPos, scaleFactor):
    name = 'testCube_%d_%d' % (xPos, yPos)
    cube = FBModelCube(name)
    cube.Show = True
   
    cube.Translation = FBVector3d(xPos, yPos, 0.0)
    cube.Scaling = FBVector3d(scaleFactor, scaleFactor, scaleFactor)
   
    return Cube
cube = CreateCube(100, 200, 50)
```

<br>

# 4)名前について
###### Full Name
Model::testNamespace:someCube
###### Long Name / Label Name
testNamespace:someCube
###### Group Name
Model
###### Namespace(s)
testNamespace
###### Name("Short Name")
someCube

（[Python Scripting in MotionBuilder - 03 - Components and the Scene](https://youtu.be/vbrqiCdp0vw?si=cy2_y7YtMI0bRBHy "Python Scripting in MotionBuilder - 03 - Components and the Scene")　より）

<br>

# 5)オブジェクト等の取得
## 【pyfbsdk】
### 名前に一致するモデルやコンポーネントの検索
FBFindModelByLabelName --- return 0 or 1 FBModel
FBFindObjectByFullName --- return 0 or 1 FBComponent
```py
from pyfbsdk import *

cube1 = FBFindModelByLabelName("Test:TestCube")
cube2 = FBFindObjectByFullName("Model::Test:TestCube")

#shortname
print(cube1.Name) #実行結果→TestCube
#longname
print(cube1.LongName) #実行結果→Test:TestCube

#Fullname
print(cube2.FullName) #実行結果→Model::Test:TestCube
```


### "Cube"から始まる名前のコンポーネントの検索
FBFindObjectsByName --- return 0 to n FBComponent or FBModel
```py
from pyfbsdk import *

SEARCH_INCLUDE_NAMESPACE = True
SEARCH_ALL_OBJECTS = False
foundComponents = FBComponentList()

FBFindObjectsByName("Cube*", foundComponents, SEARCH_INCLUDE_NAMESPACE, SEARCH_ALL_OBJECTS)

for comp in foundComponents:
    print(comp.FullName)
```
▶実行結果例
```
Cube 1_1
Cube 2_1
Cube 3_1
Cube 4_1
Model::Cube
Geometry::Cube
Model::Cube 1
Geometry::Cube 1
Model::Cube 2
Geometry::Cube 2
```



### 選択したモデルの名前を表示
```py
FBGetSelectedModels --- 0 to n FBModel
from pyfbsdk import *

selectedModels = FBModelList()

FBGetSelectedModels(selectedModels, None, True, True)

for model in selectedModels:
    print(model.FullName)
```
▶実行結果例
```
Model::Aragor:Root
```
<br>

## 【FBSystem】
### すべてのコンポーネントの表示（名前）
すべてのコンポーネントは FBSystem().Scene.Components で取得できる
```py
from pyfbsdk import *

for comp in FBSystem().Scene.Components:
    print(comp.Name)
```
▶実行結果例
```
Scene
Core
Thread Manager
Evaluation Manager
Timing Manager
Command Manager
KTimeWarpManager
Profiler
Evaluation
Transport
Timer
Audio
Video
DefaultMaterial
Producer Perspective
Producer Front
Producer Back
Producer Right
Producer Left
Producer Top
Producer Bottom
Camera Switcher
Constraints
...
```
<br>

### すべてのコンポーネントの表示（名前、属性、クラスの中身）
```py
from pyfbsdk import *

for comp in FBSystem().Scene.Components:
    print(comp.Name)
    print(type(comp))
    print(dir(comp))
    print("\n")
```
▶実行結果例
![compo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717510/514bb5d0-3443-75f4-f6aa-085188d074b3.png)



上記に加えてプロパティ一覧を表示する場合、for文内に以下を追記。
```py
for property in comp.PropertyList:
    print("Property:" + property.Name)
```
▶実行結果例
```
Property:Show
Property:Pickable
...
```
（※プロパティの値を取得するには、コンポーネントがそのプロパティを持っていることを確認した上でcomp.PropertyList.Find("Show").Data等。）

<br>

### 選択しているすべてのコンポーネントを選択解除
```py
from pyfbsdk import *
for comp in FBSystem().Scene.Components:
    comp.Selected = False
```


### シーン上の全てのモデルを取得
"RootModel"は"Scene"を指す
```py
from pyfbsdk import *
for model in FBSystem().Scene.RootModel.Children:
    print(model.LongName)
```
▶実行結果例
```
Aragor:Root
Cube
Cube 1
Cube 2
```
活用例：ジョイントのリネーム（"_L"→"_MoCap_L"等）
[Qiita - python motionbuilder rename joints](https://qiita.com/aizwellenstan/items/31fcd5d8ebac6e862da7 "Qiita - python motionbuilder rename joints")

### "Position"が含まれるコンストレイントを取得
```py
from pyfbsdk import *
import re

ptn = re.compile("Position")
for constraint in FBSystem().Scene.Constraints:
    if ptn.search(constraint.Name):
        print(constraint.Name)
```
▶実行結果例
```
SwordPosition
ShieldPosition
```

### "Position"が含まれるコンストレイントの参照元、参照先を取得する
ReferenceGet(GroupIndex, ModelIndex)を使用する
```py
from pyfbsdk import *
import re

def get_registered_models(constraint):
    result = []
    for grp_i in range(constraint.ReferenceGroupGetCount()): #参照元と参照先の2グループ分
        for model_i in range(constraint.ReferenceGetCount(grp_i)): #参照元？Sourceの数分
            result.append(constraint.ReferenceGet(grp_i, model_i))
    return result

ptn = re.compile("Position")

for constraint in FBSystem().Scene.Constraints:
    if ptn.search(constraint.Name):
        print(constraint.Name)
        for i in get_registered_models(constraint):
            print (i.FullName)
        print("\n")
```
▶実行結果例
```
SwordPosition
Model::Cube 1
Model::Aragor:Head
Model::TestCube

ShieldPosition
Model::Cube 2
Model::Aragor:RightHand
```
<br>

## 6)UIの作成
・モジュールを読み込み、windowを表示
```py
from pyfbsdk import*
from pyfbsdk_additions import*
TestWindow = FBCreateUniqueTool("TestWindow")
ShowTool(TestWindow)
```
▶実行結果
![testwindw.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717510/ace37ca9-89aa-9ca7-5c0d-509044a6274a.png)



## 7)メモ
・できることを探すためにdir()を使うと便利



## 8)参考リンク
公式ドキュメント　[Python Reference GuideSearch](https://help.autodesk.com/view/MOBPRO/2024/ENU/?guid=MotionBuilder_SDK_py_ref_index_html "Python Reference GuideSearch")
デジタルフロンティアのブログ（2012年の記事）　[モーションビルダースクリプトTips](https://dftalk.jp/cp-bin/wordpress/?p=4700#1 "モーションビルダースクリプトTips")
クリーク・アンド・リバー社のブログ（2021年の記事）　[【MotionBuilder】2020 Script Tips](https://3d.crdg.jp/tech/archives/1363 "【MotionBuilder】2020 Script Tips")
【★分かりやすい！】Alex ForsytheさんのMotion BuilderでのPython scriptingの動画（10年前）　[Python Scripting in MotionBuilder - 01 - pyfbsdk and Hello, Cubes](https://youtu.be/WlK_jRrsA5k?si=pB8qOJPCEXLd7bcm "Python Scripting in MotionBuilder - 01 - pyfbsdk and Hello, Cubes")