前回の記事で、PyMELからMELプロシージャを定義するメソッドを探したけど見つからなかった、と書きましたが、折角なので自分で作ってみました。

追記: やっぱりありました。

実装の中身はPythonで、ガワ(proc)だけMELという構成を自動で作る関数です。

ライセンス等は特に設定しませんので、自由に使って頂いて結構です。
(コメント欄等で「使ったよー」等、一言報告頂けると管理人が喜びます。)
import pymel.core as pm

def makeMelProc(func, procName, retType=None, argTypes=[]):
    u"""グローバルMELプロシージャを定義します。

    注意: 引数にfloatまたはfloat[]を指定した場合、値がちょうど整数だった時にint型に
          強制変換される問題があります。

    :param function func: Pythonファンクションオブジェクト。
    :param str procName: MELプロシージャの名前。
    :param str retType: MELプロシージャの戻り値の型。指定出来る型はargTypesと同じ。
    :param list argTypes: MELプロシージャの引数の型のリスト。
                          使用可能な型は string, int, float, string[], int[], float[]。
    """
    modName = func.__module__
    funcName = func.__name__

    # MEL変数をPython引数に変換する
    pyArgs = []
    append = pyArgs.append
    for i, t in enumerate(argTypes):
        if t == "string":
            append('"\\"" + $arg%d + "\\""' % i)
        elif t == "string[]":
            append('"(\\"" + stringArrayToString($arg%d, "\\",\\"") + "\\")"' % i)
        elif t == "int[]":
            append('"(" + intArrayToString($arg%d, ",") + ")"' % i)
        elif t == "float[]":
            append('"(" + floatArrayToString($arg%d, ",") + ")"' % i)
        else:
            append("$arg%d" % i)
    pyArgStr = ' + "," + '.join(pyArgs)

    # MELプロシージャが呼び出すPythonコマンド
    pyCmd = '"import %s; %s.%s(" + %s + ")"' % (modName, modName, funcName, pyArgStr)

    # MELプロシージャの引数
    melArgs = []
    append = melArgs.append
    for i, t in enumerate(argTypes):
        if t == "string[]":
            append("string $arg%d[]" % i)
        elif t == "int[]":
            append("int $arg%d[]" % i)
        elif t == "float[]":
            append("float $arg%d[]" % i)
        else:
            append("%s $arg%d" % (t, i))
    melArgStr = ', '.join(melArgs)

    # MELプロシージャ定義
    if retType:
        melCmd = ('global proc %s %s(%s) { return `python(%s)`; }' %
                  (retType, procName, melArgStr, pyCmd))
    else:
        melCmd = 'global proc %s(%s) { python(%s); }' % (procName, melArgStr, pyCmd)

    pm.mel.eval(melCmd)  # @UndefinedVariable

自分で作っていて、何か途中からよく分からなくなってきましたが、多分動きます。

使い方
import pymel.core as pm

def myFunc(baseName, values):
    return [baseName + str(v) for v in values]

makeMelProc(myFunc, "testMelProc", retType="string[]", argTypes=("string", "int[]"))

これで、グローバルプロシージャ "testMelProc" が定義されます。
各引数の意味は、makeMelProcのdocstringを参照してください。


後は、通常のMELプロシージャと同じように、MELコマンドとして呼び出してやれば、登録されたPython関数 "myFunc" が呼び出され、戻り値もMELプロシージャへと返されます。

// MELコマンドとして実行
testMelProc("test", {1, 2, 3});

// Result: test1 test2 test3 // 

現状では使用出来る型に制限がありますが、それなりに実用出来る範囲かなとは思います。
というか、MEL自体複雑な戻り値とか返せませんしね。