ノード・プラグイン

ノード・プラグインとは

ノード・プラグインによって、Maya のノードを作成することができます。

ノード・プラグインに必要なクラス・関数

ノードを作成するためのクラス
クラス名は自由ですが、maya.OpenMayaMPx.MPxNode クラスを継承する必要があります。
クラス内には、以下の関数が必要です。
__init__(self)
クラスの初期化関数では、 最低限 maya.OpenMayaMPx.MPxNode.__init__() を実行します。
compute(self, plug, dataBlock)
ノードが実行する処理を記述します。
クラスのインスタンスを作成する関数
上の、ノードを作成するためのクラスの、インスタンスを作成する関数です。
名前は自由に決められますが、ここでは nodeCreator() という名前に統一しておきます。
ノードのアトリビュートを初期化する関数
ノードで定義されるアトリビュートを、初期化する関数です。
名前は自由に決められますが、ここでは nodeInitializer() という名前に統一しておきます。
initializePlugin(mobject)
プラグインがロードされるときに実行される関数です。
ノードの登録などを行います。
引数 mobject は、MObject クラスのインスタンスです。
関数名は、initializePlugin 以外使えません。
uninitializePlugin(mobject)
プラグインがアンロードされるときに実行される関数です。
ノードの登録取り消しなどを行います。
引数 mobject は、MObject クラスのインスタンスです。
関数名は、uninitializePlugin 以外使えません。

ノード・プラグインの例

入力データを sin() 関数によって計算し、出力するノードを作ってみましょう。

  1. 以下の Python スクリプトを sineNode1.py という名前で作ります。
    import sys
    import math
    import maya.OpenMaya
    import maya.OpenMayaMPx
    
    kPluginNodeName = 'sineNode1'
    
    sineNodeId = maya.OpenMaya.MTypeId(0x87001)
    
    class sineNode1(maya.OpenMayaMPx.MPxNode):
        input = maya.OpenMaya.MObject()
        output = maya.OpenMaya.MObject()
        def __init__(self):
            maya.OpenMayaMPx.MPxNode.__init__(self)
        def compute(self, plug, dataBlock):
            if(plug == sineNode1.output):
                dataHandle = dataBlock.inputValue(sineNode1.input)
                inputFloat = dataHandle.asFloat()
                result = math.sin(inputFloat)
                outputHandle = dataBlock.outputValue(sineNode1.output)
                outputHandle.setFloat(result)
                dataBlock.setClean(plug)
                return maya.OpenMaya.MStatus.kSuccess
            else:
                return maya.OpenMaya.MStatus.kUnknownParameter
    
    def nodeCreator():
        return maya.OpenMayaMPx.asMPxPtr(sineNode1())
    
    def nodeInitializer():
        nAttr = maya.OpenMaya.MFnNumericAttribute()
        sineNode1.input = nAttr.create('input', 'i', maya.OpenMaya.MFnNumericData.kFloat, 0.0)
        nAttr.setStorable(1)
    
        nAttr = maya.OpenMaya.MFnNumericAttribute()
        sineNode1.output = nAttr.create('output', 'o', maya.OpenMaya.MFnNumericData.kFloat, 0.0)
        nAttr.setStorable(1)
        nAttr.setWritable(1)
    
        sineNode1.addAttribute(sineNode1.input)
        sineNode1.addAttribute(sineNode1.output)
        sineNode1.attributeAffects(sineNode1.input, sineNode1.output)
        
    def initializePlugin(mobject):
        mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
        try:
            mplugin.registerNode(kPluginNodeName, sineNodeId, nodeCreator, nodeInitializer)
        except:
            sys.stderr.write('Failed to register node: %s' % kPluginNodeName)
            raise
    
    def uninitializePlugin(mobject):
        mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
        try:
            mplugin.deregisterNode(sineNodeId)
        except:
            sys.stderr.write('Failed to deregister node: %s' % kPluginNodeName)
            raise
    
  2. sineNode1.py をロードします。
    以下の、どちらかの方法でロードします。
  3. スクリプト エディタ のインプットウインドウの Python タブで、以下のように実行します。
    import maya.cmds
    sin = maya.cmds.createNode('sineNode1')
    sname = maya.cmds.sphere()
    maya.cmds.connectAttr(sin + '.output', sname[0] + '.tx')
    maya.cmds.connectAttr('time1.outTime', sin + '.input')
  4. アニメーションを実行すると、NURBS 球体の 移動X が -1.0 と 1.0 の間でアニメーションされます。

スクリプトの解説

import sys
sys モジュールをインポートします。
エラーの表示をするために必要です。
import math
math モジュールをインポートします。
sin() 関数を使用するために必要です。
import maya.OpenMaya
maya.OpenMaya モジュールをインポートします。
import maya.OpenMayaMPx
maya.OpenMayaMPx モジュールをインポートします。
kPluginNodeName = 'sineNode1'
このプラグインの名前を sineNode1 として、変数 kPluginNodeName に代入します。
sineNodeId = maya.OpenMaya.MTypeId(0x87001)
プラグインごとにユニークな識別番号を決めます。
プラグインは、この番号によって Maya の中で登録・識別・登録取り消しなどが行われます。
ローカルだけで使用する場合などは0x00000000以上、0x0007ffff以下の番号を、 プラグインを公表する場合は Autodesk からユニークな番号を取得します。
class sineNode1(maya.OpenMayaMPx.MPxNode):
maya.OpenMayaMPx.MPxNode を継承して、 ノード作成のためのクラスを定義します。
input = maya.OpenMaya.MObject()
入力データのために、MObject インスタンスを作成して、クラス変数 input に代入します。
output = maya.OpenMaya.MObject()
出力データのために、MObject インスタンスを作成して、クラス変数 output に代入します。
def __init__(self):
sineNode1 クラス初期化のためのメソッドです。
maya.OpenMayaMPx.MPxNode.__init__(self)
sineNode1 クラスを初期化するために、 親クラス MPxNode の __init__() を実行します。
def compute(self, plug, dataBlock):
ノードが実行する処理を記述しておく関数です。
引数の意味は、以下のとおりです。
plug
他のノードにコネクトされているプラグを表します。
dataBlock
このノードに関するデータを保存しているオブジェクトです。
if(plug == sineNode1.output):
プラグが出力 output かどうか調べます。
dataHandle = dataBlock.inputValue(sineNode1.input)
データブロックから、入力データ input のデータハンドルを得て、 dataHandle に代入します。
inputFloat = dataHandle.asFloat()
入力データをデータハンドルから float のデータとして取り出し、 inputFloat に代入します。
result = math.sin(inputFloat)
math モジュールの sin() 関数によって計算した結果を result に代入します。
outputHandle = dataBlock.outputValue(sineNode1.output)
データブロックから出力データ output のデータハンドルを得て、 outputHandle に代入します。
outputHandle.setFloat(result)
出力データのデータハンドルに出力データ result を float のデータとして与えます。
dataBlock.setClean(plug)
プラグをクリーンにします。 これをしないとノードの計算が終わっているとみなされません。
return maya.OpenMaya.MStatus.kSuccess
計算が成功したときはkSuccessを返しておきます。
return maya.OpenMaya.MStatus.kUnknownParameter
プラグが output 以外の場合は、kUnknownParameter を返して Maya に処理を任せます。
計算する必要の無いプラグは、kUnknownParameter を返しておきます。
def nodeCreator():
Maya がノードのインスタンスを作成するための関数です。
return maya.OpenMayaMPx.asMPxPtr(sineNode1())
sineNode1 クラスのインスタンスを作成し、asMPxPtr() 関数に与えます。
asMPxPtr() 関数を使わないと、インスタンスを Maya に渡すことができません。
def nodeInitializer():
ノードの初期化関数です。
nAttr = maya.OpenMaya.MFnNumericAttribute()
MFnNumericAttribute のインスタンスを作成します。
sineNode1.input = nAttr.create('input', 'i', maya.OpenMaya.MFnNumericData.kFloat, 0.0)
input アトリビュートを作成し、短縮名は i 、型は float 、デフォールト値は 0.0 にします。
nAttr.setStorable(1)
シーンの保存時に input アトリビュートの値を保存する設定です。
nAttr = maya.OpenMaya.MFnNumericAttribute()
MFnNumericAttribute のインスタンスを作成します。
sineNode1.output = nAttr.create('output', 'o', maya.OpenMaya.MFnNumericData.kFloat, 0.0)
output アトリビュートを作成し、短縮名は o 、型は float 、デフォールト値は 0.0 にします。
nAttr.setStorable(1)
シーンの保存時に output アトリビュートの値を保存する設定です。
nAttr.setWritable(1)
output アトリビュートが出力可能であるという設定です。
sineNode1.addAttribute(sineNode1.input)
input アトリビュートを sineNode1 ノードのアトリビュートとして設定します。
sineNode1.addAttribute(sineNode1.output)
output アトリビュートを sineNode1 ノードのアトリビュートとして設定します。
sineNode1.attributeAffects(sineNode1.input, sineNode1.output)
input アトリビュートが変化したとき、 プラグを output として sineNode1 の compute メソッドを実行するように設定します。
def initializePlugin(mobject):
プラグインがロードされたときに実行される初期化関数です。
mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
MFnPlugin クラスのインスタンスを作成します。
mobjectMObject のインスタンスです。
try:
  mplugin.registerNode(kPluginNodeName, sineNodeId, nodeCreator, nodeInitializer)
except:
  sys.stderr.write('Failed to register node: %s' % kPluginNodeName)
  raise
MFnPlugin のインスタンスに、sineNode1 に関する設定を与えています。
もし設定に失敗した場合は、メッセージを出力して例外を送出します。
def uninitializePlugin(mobject):
プラグインをアンロードするときに実行される関数です。
mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
MFnPlugin クラスのインスタンスを作成します。
mobjectMObject のインスタンスです。
try:
  mplugin.deregisterNode(sineNodeId)
except:
  sys.stderr.write('Failed to deregister node: %s' % kPluginNodeName)
  raise
プラグインをアンロードします。
もしアンロードに失敗した場合は、メッセージを出力して例外を送出します。

練習

  1. 上の sineNode1.py を参考にして sineNode2.py という Python スクリプトを作り、 sineNode1 のクラスに scale というアトリビュートを追加したクラス sineNode2 を作成して、 出力データの範囲を変更できるようにしてみましょう。
    sineNode1 クラスの result の計算部分を、以下のように変更します。
    math.sin(input) * scale
    (実行例)
    sin2 = maya.cmds.createNode('sineNode2')
    sname = maya.cmds.sphere()
    maya.cmds.connectAttr(sin2 + '.output', sname[0] + '.tx')
    maya.cmds.connectAttr('time1.outTime', sin2 + '.input')
    maya.cmds.setAttr(sin2 + '.scale', 5.0)
  2. 上の sineNode2.py を参考にして sineNode3.py という Python スクリプトを作り、 sineNode2 のクラスに speed と center というアトリビュートを追加したクラス sineNode3 を作成して、 出力データの周期・範囲を変更できるようにしてみましょう。
    sineNode2 クラスの result の計算部分を、以下のように変更します。
    math.sin(input * speed) * scale + center
    (実行例)
    sin3 = maya.cmds.createNode('sineNode3')
    sname = maya.cmds.sphere()
    maya.cmds.connectAttr(sin3 + '.output', sname[0] + '.tx')
    maya.cmds.connectAttr('time1.outTime', sin3 + '.input')
    maya.cmds.setAttr(sin3 + '.scale', 7.0)
    maya.cmds.setAttr(sin3 + '.speed', 0.1)
    maya.cmds.setAttr(sin3 + '.center', 3.0)

参考


Prev | Next
Home | Contents
Mail