[Cinema 4D] ユーザデータをPythonで作成する

以前の記事ではresファイルを用いてデータを作成したが，今回は[AddUserData](https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d/C4DAtom/GeListNode/BaseList2D/index.html?highlight=adduserdata#BaseList2D.AddUserData "AddUserData")を使って関数に直接記述してユーザデータの作成にトライしました．

やりたいこととしては，ユーザデータは関数化し，外部ファイルから呼び出して追加できるようにしておきたい．そこでまずは，最も基本的なところとなる外部ファイルのインポートについて練習したところ，いきなり躓きました...

サブディレクトリに置いたモジュールをインポートできない...環境変数などの設定をすればよいのかもしれないが，Githubにローカルインポート用のパッケージが配布されていたので，有難くつかわせていただくことにします．

https://github.com/NiklasRosenstein/py-localimport

Thanks!!

ちなみにCinema 4DのPythonプラグインはメインプログラムを.pypという拡張子で保存する必要があるようで，.pyだとプラグインとして認識されないです．Pythonでプラグインを作るときもC++と同じで，RegisterXXXXPlugin(XXXはプラグインタイプを指定)をCinema 4D本体が読み込むことでプラグインとして認識されます．

さらに，ユーザデータの雛形プログラムもすでにpluguincafe.comで見つけたので，有難く参考にさせていただくことにして，これを紐解きながら自作ユーザデータを作っていくことにしました．

https://github.com/gr4ph0s/RefractiveIndex-Importer

Thanks!!

一通りパッケージを眺めてみたところ，Const.pyにClass ConstでIDを，UserData.pyにはユーザデータを作成するためのclass UDと関数が記載されていたので，私も例に習えでこれを使って試しにマトリックス型のユーザデータを作成するための関数を作成した．

```
class UD():
    def create_matrix ( self, matrixId, parentGroup=None, matrixText=""):
        if (self.idMatrix[matrixId]) is None:
            print("create_matrix")
            off = c4d.Vector(0, 0, 0)
            v1 = c4d.Vector(1, 0, 0)
            v2 = c4d.Vector(0, 1, 0)
            v3 = c4d.Vector(0, 0, 1)
            mat = c4d.Matrix(off, v1, v2, v3)  
            bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_MATRIX)
            bc[c4d.DESC_NAME] = matrixText  # Rename the entry
            bc[c4d.DESC_PARENTGROUP] = parentGroup
            self.idMatrix[matrixId] = self.obj.AddUserData(bc)
            self.obj[self.idMatrix[matrixId]] = mat
            return self.idMatrix
```

後々，デフォルト引数でマトリックスを渡せるようにする予定です．

```
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_MATRIX)
```

ここが，マトリックス型のカスタムデータタイプのベースコンテナを作成しているところで，そのコンテナに名前や親グループ，マトリックスの代入などを行っています．

呼び出し側で，
```
self.ud.create_matrix ( Const.UI_MATRIX_DISPLAY_ROOT, "Matrix Root" )
```
とすると，マトリックスのユーザデータが作成されます．

![20171227-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/195698/51ded258-6bea-1ee8-2fce-d7ce63482fe7.jpeg)

数値が0なんですが，printすると数値は代入されているようです．マトリックスのoffを(0, 0, 0)にすると，全部0で表示されてしまう．ここは解決策を調べ中．

使わせてもらったユーザデータサンプルは，GROUP，SEPARATOR，CYCLE，BUTTON，などが関数としてすでにあるので，引数や関数内の処理を拡張してもいいですね．

例えば次のユーザデータセクションはClass ConstでIDを定義し，以下のようなコードで関数を呼び出すだけで作成できます．

![20171227-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/195698/b50ec178-7be2-762d-a4a8-bcb1cee1b682.jpeg)

```
# Create Root Matrix selection section
self.ud.create_group  ( Const.UI_GROUP_MATRIX_TYPE, "Matrix Type", self.ud.idGroups[Const.UI_GROUP_MATRIX], 3, None, False)
self.ud.create_cycle  ( Const.UI_CYCLE, matrixTypeitems, self.ud.idGroups[Const.UI_GROUP_MATRIX_TYPE], "Marix Type")
self.ud.create_button ( Const.UI_BUTTON_REFRESH, self.ud.idGroups[Const.UI_GROUP_MATRIX_TYPE], "Refresh")
self.ud.create_button ( Const.UI_BUTTON_DELETE,  self.ud.idGroups[Const.UI_GROUP_MATRIX_TYPE], "Delete")
self.ud.create_group  ( Const.UI_GROUP_MATRIX_DISPLAY_ROOT, "", self.ud.idGroups[Const.UI_GROUP_MATRIX_TYPE], 1, None, False)
self.ud.create_matrix ( Const.UI_MATRIX_DISPLAY_ROOT, self.ud.idGroups[Const.UI_GROUP_MATRIX_DISPLAY_ROOT], "Matrix Root" )

```
グループをうまく作成すれば，見た目も整理できます．

このように，ユーザデータを作るための関数を用意しておけば，関数に必要な引数を渡して呼び出すだけでユーザデータを追加していけるようになるので，コードもすっきりしてきますし，使いやすいようにモジュール化しておけば雛形として他のプラグインでも使えるので効率もよくなるはず．

カラー選択，スプライン，グラデーションなどのインターフェイスも同様に関数として定義しておけば，同様に追加していけます．

ユーザデータのモジュール化も少し理解できたところで，いよいよ実際の動作の部分へ入っていくわけですが...どうなることやら．