我尝试创建一个包含多个输出的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")
答案 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 ++然后它就是金色的。