【问题标题】:Maya MPxNode multiple outputsMaya MPxNode 多个输出
【发布时间】:2018-05-16 08:32:17
【问题描述】:

我正在尝试创建一个具有多个输出的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")

【问题讨论】:

  • 在计算方法中,您可以尝试检查两个输出:if plug != self.output1 and plug != self.output2:
  • 嘿哈吉,检查我的问题,因为我提到过。这样做可行,问题是它重新计算了两次计算。我真的只需要计算一次然后设置所有输出,所以我正在尝试优化。
  • 哦,对不起,我没有正确阅读。您可以缓存第一次计算的结果,直到必须重新计算。您可以检查脏属性或仅检查输入是否已更改,如果没有更改,则使用缓存的值。
  • 我想我有东西试图缓存结果!只需要确保它在打开/导入/引用等方面稳定。如果我设法解决,我会发布答案。

标签: python maya maya-api


【解决方案1】:

我有一个按预期工作的解决方案。所有输出仍然必须经过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++ 中,它就会变成金色。

【讨论】:

  • 快速更新:这个想法似乎在 c++ 中运行良好。米尔豪斯的一切都即将到来!
  • 作为后续,这在 api 2.0 (Maya 2018 sp3) 中不起作用。在计算中查询一个插件是不行的,至少在 python 绑定中是这样。
  • @Klaudikus 很高兴知道。在 api 2.0 更成熟之前,我并没有费心开发太多东西。我仍然在 2018 ext 4 中使用它,到目前为止它似乎运行顺利。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多