[Cinema4D] CycleIDの変更と連動してパラメータを変更する

CycleIDを変更した時に，連動してパラメータを同時に変更したい時，どのようにすればよいか考えてみました．

この例ではCycleに設定したアイテムとパラメータには特に意味があるわけではないですが，Matrix Typeを変更すると連動してMatrix Rootというユーザデータを変更させることにトライしました．

Cycle用のアイテムについてはBaseContainerとしたMatrixTypeItemsにSetStringを使用してIDとともに以下のように定義しています．

[BaseContainer.SetString(id, s)](https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d/BaseContainer/index.html?highlight=setstring#BaseContainer.SetString "BaseContainer.SetString(id, s)")

```
# Matrix Type Cycle Data
MatrixTypeItems = c4d.BaseContainer()
MatrixTypeItems.SetString( 0, "CINEMA 4D" )
MatrixTypeItems.SetString( 1, "3ds MAX" )
MatrixTypeItems.SetString( 2, "MAYA" )
MatrixTypeItems.SetString( 3, "Redqueen" )
```

Cycleはc4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)で作成します．さらにbcのDESC_CUSTOMGUIにDESC_CUSTOMGUI_CYCLEを代入します．SetContainerを使って，DESC_CYCLEにdata(先のCycle dataです)をセットし，それをAddUserData(bc)として追加しています．

```
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
bc[c4d.DESC_NAME] = cycleText
bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_CYCLE
bc[c4d.DESC_PARENTGROUP] = parentGroup
bc.SetContainer(c4d.DESC_CYCLE, data)
self.Cycle[cycleId] = self.obj.AddUserData(bc)
```

プラグインを最初にメニューから呼び出したときにはInit関数により初期値が設定されているので，次に何かパラメータを変更した時（ここではCycleアイテムを変更した場合），連動してパラメータを変更するには，まずプラグインのパラメータが変更されたことを伝える必要があります．それがMessageという関数です．これらはNodeDataクラスに属しており，派生クラスのTagDataやObjectDataでも使うことができます．

[NodeData.Message(self, node, type, data)](https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d.plugins/BaseData/NodeData/index.html?highlight=msg_description_checkupdate#NodeData.Message "NodeData.Message(self, node, type, data)")

沢山のメッセージがあり，ノードにそれぞれのアクションメッセージを伝える役割があります．例えばオブジェクトデータが変更された時，ユーザが要素をダブルクリックした時，などがあります．今回はMSG_DESCRIPTION_CHECKUPDATEを使って，何かデータが変更されたことをノードに渡し，キューとして使います．

```
if type == c4d.MSG_DESCRIPTION_CHECKUPDATE:
    CurrentCycleID = CurrentData
    if OldCycleID != CurrentCycleID
        # do something
        self.ud.SetRootMatrix( Const.UI_MATRIX_DISPLAY_ROOT, cycleId )
```

として，何かデータが変更され，かつそれがCycleIDであれば，do somethingを実行するという流れです．ここでset_root_matrix関数を呼び出し，プラグインの初期化の際に作成したマトリックスのIDと新しいCycleIDを渡して，CycleIDに応じたマトリックスを代入します．

```
self.ud.SetRootMatrix( Const.UI_MATRIX_DISPLAY_ROOT, cycleId )

class UD ()
    MatC4D    = c4d.Matrix ( c4d.Vector(0, 0, 0),
                             c4d.Vector(1, 0, 0),
                             c4d.Vector(0, 1, 0),
                             c4d.Vector(0, 0, 1) )
    Mat3dsMax...


    def SetRootMatrix ( self, matrixId, cycleId ):
        if (self.Matrix[matrixId]) is None:
            print("matrixId is None")
        else:
            if cycleId   == [0]: # If Cycle is Cinema4D
                self.obj[self.Matrix[matrixId]] = UD.MatC4D
            elif cycleId == [1]: # If Cycle is 3ds Max
                self.obj[self.Matrix[matrixId]] = UD.Mat3dsMax
            elif cycleId == [2]: # If Cycle is MAYA
                self.obj[self.Matrix[matrixId]] = UD.MatMaya
            elif cycleId == [3]: # If Cycle is Redqueen
                self.obj[self.Matrix[matrixId]] = UD.MatRq

        return self.Matrix
```

![20180106.jpg](https://qiita-image-store.s3.amazonaws.com/0/195698/c441b466-ab0a-88e6-fedf-113137bdd481.jpeg)

これで，CycleIDを変えることで連動してマトリックスを変更できました．（数値は適当です）