Maya MPxNode多输出

时间:2018-05-16 08:32:18

标签: python maya maya-api

我尝试创建一个包含多个输出的MPxNode,但我只能让一个正常工作。在连接节点之后和撤消期间,其他输出没有正确设置。

是否可以在compute中同时设置两个输出,就像我尝试的那样?如果我将计算中的第一行更改为if plug != self.output1 and plug != self.output2,它确实有效,但这意味着它会计算两次,这会浪费内存。而且你可以想象如果有更多的产出会有多糟糕。

我设法将这个简单示例的代码最小化。我在Maya 2018上用Python编写脚本:

import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMaya as OpenMaya


class MyAwesomeNode(OpenMayaMPx.MPxNode):

    # Define node properties.
    kname = "myAwesomeNode"
    kplugin_id = OpenMaya.MTypeId(0x90000005)

    # Define node attributes.
    in_val = OpenMaya.MObject()
    output1 = OpenMaya.MObject()
    output2 = OpenMaya.MObject()

    def __init__(self):
        OpenMayaMPx.MPxNode.__init__(self)

    def compute(self, plug, data):
        # Only operate on output1 attribute.
        if plug != self.output1:
            return OpenMaya.kUnknownParameter

        # Get input value.
        val = data.inputValue(MyAwesomeNode.in_val).asFloat()

        # Set output 2.
        # This fails when setting up the node and during undos.
        out_plug_2 = data.outputValue(self.output2)
        if val > 0:
            out_plug_2.setFloat(1)
        else:
            out_plug_2.setFloat(0)
        out_plug_2.setClean()

        # Set output 1.
        # This works as expected.
        out_plug_1 = data.outputValue(self.output1)
        out_plug_1.setFloat(val)
        out_plug_1.setClean()

        data.setClean(plug)

        return True


def creator():
    return OpenMayaMPx.asMPxPtr(MyAwesomeNode())


def initialize():
    nattr = OpenMaya.MFnNumericAttribute()

    MyAwesomeNode.output2 = nattr.create("output2", "output2", OpenMaya.MFnNumericData.kFloat)
    nattr.setWritable(False)
    nattr.setStorable(False)
    MyAwesomeNode.addAttribute(MyAwesomeNode.output2)

    MyAwesomeNode.output1 = nattr.create("output1", "output1", OpenMaya.MFnNumericData.kFloat)
    nattr.setWritable(False)
    nattr.setStorable(False)
    MyAwesomeNode.addAttribute(MyAwesomeNode.output1)

    MyAwesomeNode.in_val = nattr.create("input", "input", OpenMaya.MFnNumericData.kFloat, 1)
    nattr.setKeyable(True)
    MyAwesomeNode.addAttribute(MyAwesomeNode.in_val)
    MyAwesomeNode.attributeAffects(MyAwesomeNode.in_val, MyAwesomeNode.output2)
    MyAwesomeNode.attributeAffects(MyAwesomeNode.in_val, MyAwesomeNode.output1)


def initializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj, "Me", "1.0", "Any")
    try:
        plugin.registerNode(MyAwesomeNode.kname, MyAwesomeNode.kplugin_id, creator, initialize)
    except:
        raise RuntimeError, "Failed to register node: '{}'".format(MyAwesomeNode.kname)


def uninitializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj)
    try:
        plugin.deregisterNode(MyAwesomeNode.kplugin_id)
    except:
        raise RuntimeError, "Failed to register node: '{}'".format(MyAwesomeNode.kname)


# Example usage of node
if __name__ == "__main__":
    import maya.cmds as cmds

    cmds.createNode("transform", name="result")
    cmds.setAttr("result.displayLocalAxis", True)

    cmds.createNode("myAwesomeNode", name="myAwesomeNode")
    cmds.connectAttr("myAwesomeNode.output1", "result.translateX")

    # This output fails.
    cmds.polyCube(name="cube")
    cmds.setAttr("cube.translate", 0, 3, 0)
    cmds.connectAttr("myAwesomeNode.output2", "cube.scaleX")
    cmds.connectAttr("myAwesomeNode.output2", "cube.scaleY")
    cmds.connectAttr("myAwesomeNode.output2", "cube.scaleZ")

1 个答案:

答案 0 :(得分:0)

我有一个按预期工作的解决方案。所有输出仍然必须经过compute(),但只有一个输出将进行实际繁重的计算。

当通过compute时,它会检查所有输出插头是否清洁。如果所有都是脏的,那么我们需要重新计算,否则如果我们找到一个干净的插件,我们就可以使用我们之前保存的缓存值。

以下是一个例子:

import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMaya as OpenMaya


class MyAwesomeNode(OpenMayaMPx.MPxNode):

    # Define node properties.
    kname = "myAwesomeNode"
    kplugin_id = OpenMaya.MTypeId(0x90000005)

    # Define node attributes.
    in_val = OpenMaya.MObject()
    output1 = OpenMaya.MObject()
    output2 = OpenMaya.MObject()

    def __init__(self):
        OpenMayaMPx.MPxNode.__init__(self)

        # Store value here.
        self.cached_value = 0

    def compute(self, plug, data):
        # Include all outputs here.
        if plug != self.output1 and plug != self.output2:
            return OpenMaya.kUnknownParameter

        # Get plugs.
        val = data.inputValue(MyAwesomeNode.in_val).asFloat()
        out_plug_1 = data.outputValue(self.output1)
        out_plug_2 = data.outputValue(self.output2)

        dep_node = OpenMaya.MFnDependencyNode(self.thisMObject())

        # Determine if this output needs to recalculate or simply use cached values.
        use_cache_values = False

        for name in ["output1", "output2"]:
            mplug = dep_node.findPlug(name)
            if data.isClean(mplug):
                # If we find a clean plug then just use cached values.
                use_cache_values = True
                break

        if use_cache_values:
            # Use cached value.
            value = self.cached_value
        else:
            # Calculate value.
            # We potentially can make big computations here.
            self.cached_value = val
            value = val

        # Set output 1.
        if plug == self.output1:
            out_plug_1.setFloat(value)
            out_plug_1.setClean()

        # Set output 2.
        if plug == self.output2:
            if value > 0:
                out_plug_2.setFloat(1)
            else:
                out_plug_2.setFloat(0)
            out_plug_2.setClean()

        data.setClean(plug)

        return True


def creator():
    return OpenMayaMPx.asMPxPtr(MyAwesomeNode())


def initialize():
    nattr = OpenMaya.MFnNumericAttribute()

    MyAwesomeNode.output2 = nattr.create("output2", "output2", OpenMaya.MFnNumericData.kFloat)
    nattr.setWritable(False)
    nattr.setStorable(False)
    MyAwesomeNode.addAttribute(MyAwesomeNode.output2)

    MyAwesomeNode.output1 = nattr.create("output1", "output1", OpenMaya.MFnNumericData.kFloat)
    nattr.setWritable(False)
    nattr.setStorable(False)
    MyAwesomeNode.addAttribute(MyAwesomeNode.output1)

    MyAwesomeNode.in_val = nattr.create("input", "input", OpenMaya.MFnNumericData.kFloat, -1)
    nattr.setKeyable(True)
    MyAwesomeNode.addAttribute(MyAwesomeNode.in_val)

    # Include both outputs.
    MyAwesomeNode.attributeAffects(MyAwesomeNode.in_val, MyAwesomeNode.output1)
    MyAwesomeNode.attributeAffects(MyAwesomeNode.in_val, MyAwesomeNode.output2)


def initializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj, "Me", "1.0", "Any")
    try:
        plugin.registerNode(MyAwesomeNode.kname, MyAwesomeNode.kplugin_id, creator, initialize)
    except:
        raise RuntimeError, "Failed to register node: '{}'".format(MyAwesomeNode.kname)


def uninitializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj)
    try:
        plugin.deregisterNode(MyAwesomeNode.kplugin_id)
    except:
        raise RuntimeError, "Failed to register node: '{}'".format(MyAwesomeNode.kname)


# Example usage of node
if __name__ == "__main__":
    import maya.cmds as cmds

    cmds.createNode("transform", name="result")
    cmds.setAttr("result.displayLocalAxis", True)

    cmds.createNode("myAwesomeNode", name="myAwesomeNode")
    cmds.connectAttr("myAwesomeNode.output1", "result.translateX")

    # This output fails.
    cmds.polyCube(name="cube")
    cmds.setAttr("cube.translate", 0, 3, 0)
    cmds.connectAttr("myAwesomeNode.output2", "cube.scaleX")
    cmds.connectAttr("myAwesomeNode.output2", "cube.scaleY")
    cmds.connectAttr("myAwesomeNode.output2", "cube.scaleZ")

当重新打开文件,将其导入新场景并引用它时,输出似乎正在做出反应。我只需要将相同的想法转移到c ++然后它就是金色的。