import maya.OpenMaya as OpenMaya
import maya.OpenMayaUI as OpenMayaUI
import maya.OpenMayaMPx as OpenMayaMPx
import math, sys
kSlopeShaderBehaviourName = "slopeShaderBehaviour"
kSlopeNodeName = "spSlopeShader"
kSlopeNodeClassify = "utility/color"
kSlopeNodeId = OpenMaya.MTypeId(0x87001)
class slopeShader(OpenMayaMPx.MPxNode):
aAngle = OpenMaya.MObject()
aColor1 = OpenMaya.MObject()
aColor2 = OpenMaya.MObject()
aTriangleNormalCamera = OpenMaya.MObject()
aOutColor = OpenMaya.MObject()
aMatrixEyeToWorld = OpenMaya.MObject()
aDirtyShaderAttr = OpenMaya.MObject()
def __init__(self):
OpenMayaMPx.MPxNode.__init__(self)
def compute(self, plug, dataBlock):
if plug == slopeShader.aOutColor or plug.parent() == slopeShader.aOutColor:
resultColor = OpenMaya.MFloatVector(0.0,0.0,0.0)
try:
dataHandle = dataBlock.inputValue( slopeShader.aColor1 )
except:
sys.stderr.write( "Failed to get inputValue aColor1" )
raise
walkable = dataHandle.asFloatVector()
try:
dataHandle = dataBlock.inputValue( slopeShader.aColor2 )
except:
sys.stderr.write( "Failed to get inputValue aColor2" )
raise
nonWalkable = dataHandle.asFloatVector()
try:
dataHandle = dataBlock.inputValue( slopeShader.aTriangleNormalCamera )
except:
sys.stderr.write( "Failed to get inputValue aTriangleNormalCamera" )
raise
surfaceNormal = dataHandle.asFloatVector()
try:
dataHandle = dataBlock.inputValue( slopeShader.aMatrixEyeToWorld )
except:
sys.stderr.write( "Failed to get inputValue aMatrixEyeToWorld" )
raise
viewMatrix = dataHandle.asFloatMatrix()
try:
dataHandle = dataBlock.inputValue( slopeShader.aAngle )
except:
sys.stderr.write( "Failed to get inputValue aAngle" )
raise
angle = dataHandle.asFloat()
yVector = OpenMaya.MFloatVector(0, 1, 0)
surfaceNormal.normalize()
WSVector = surfaceNormal * viewMatrix
scalarNormal = WSVector * yVector
if scalarNormal < 0.0:
scalarNormal *= -1.0
radianAngle = math.radians(angle)
cosOfAngle = math.cos(radianAngle)
if cosOfAngle < scalarNormal:
resultColor = walkable
else:
resultColor = nonWalkable
try:
outColorHandle = dataBlock.outputValue( slopeShader.aOutColor )
except:
sys.stderr.write( "Failed to get outputValue aOutColor" )
raise
outColorHandle.setMFloatVector(resultColor)
outColorHandle.setClean()
else:
return OpenMaya.kUnknownParameter
def postConstructor(self):
print "In slopeShader.postConstructor"
class slopeShaderBehavior(OpenMayaMPx.MPxDragAndDropBehavior):
def __init__(self):
OpenMayaMPx.MPxDragAndDropBehavior.__init__(self)
def shouldBeUsedFor(self, sourceNode, destinationNode, sourcePlug, destinationPlug):
"""
Overloaded function from MPxDragAndDropBehavior
this method will return True if it is going to handle the connection
between the two nodes given.
"""
result = False
if sourceNode.hasFn(OpenMaya.MFn.kLambert):
shaderNode = None
src = OpenMaya.MFnDependencyNode(sourceNode)
connections = OpenMaya.MPlugArray()
src.getConnections(connections)
for i in range(connections.length()):
connectedPlugs = OpenMaya.MPlugArray()
connections[i].connectedTo(connectedPlugs, True, False)
for j in range(connectedPlugs.length()):
testNode = OpenMaya.MFnDependencyNode(connectedPlugs[j].node())
if testNode.typeName() == kSlopeNodeName:
shaderNode = connectedPlugs[j].node()
break
if shaderNode is not None:
if destinationNode.hasFn(OpenMaya.MFn.kMesh):
result = True
break
node = OpenMaya.MFnDependencyNode(sourceNode)
if node.typeName() == kSlopeNodeName:
if destinationNode.hasFn(OpenMaya.MFn.kLambert):
result = True
elif destinationNode.hasFn(OpenMaya.MFn.kMesh):
result = True
return result
def connectNodeToNode(self, sourceNode, destinationNode, force):
"""
Overloaded function from MPxDragAndDropBehavior
this method will handle the connection between the slopeShader and the shader it is
assigned to as well as any meshes that it is assigned to.
"""
src = OpenMaya.MFnDependencyNode(sourceNode)
if sourceNode.hasFn(OpenMaya.MFn.kLambert):
shaderNode = OpenMaya.MObject()
connections = OpenMaya.MPlugArray()
shaderNodes = OpenMaya.MObjectArray()
shaderNodes.clear()
src.getConnections(connections)
for i in range(connections.length()):
connectedPlugs = OpenMaya.MPlugArray()
connections[i].connectedTo(connectedPlugs, True, False)
for j in range(connectedPlugs.length()):
currentnode = connectedPlugs[j].node()
if OpenMaya.MFnDependencyNode(currentnode).typeName() == kSlopeNodeName:
shaderNodes.append(currentnode)
if shaderNodes.length() > 0:
dest = OpenMaya.MFnDependencyNode(destinationNode)
if destinationNode.hasFn(OpenMaya.MFn.kMesh):
for i in range(shaderNodes.length()):
srcPlug = dest.findPlug("worldMesh")
destPlug = OpenMaya.MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug")
if (not srcPlug.isNull()) and (not destPlug.isNull()):
cmd = "connectAttr -na %s %s" % (srcPlug.name(), destPlug.name())
OpenMaya.MGlobal.executeCommand(cmd)
shadingEngine = self._findShadingEngine(sourceNode)
if not shadingEngine.isNull():
cmd = "sets -edit -forceElement %s %s" % (
OpenMaya.MFnDependencyNode(shadingEngine).name(),
OpenMaya.MFnDagNode(destinationNode).partialPathName()
)
OpenMaya.MGlobal.executeCommand(cmd)
elif src.typeName() == kSlopeNodeName:
if destinationNode.hasFn(OpenMaya.MFn.kMesh):
dest = OpenMaya.MFnDependencyNode(destinationNode)
srcPlug = dest.findPlug("worldMesh")
destPlug = src.findPlug("dirtyShaderPlug")
if (not srcPlug.isNull()) and (not destPlug.isNull()):
cmd = "connectAttr -na %s %s" % (srcPlug.name(), destPlug.name())
OpenMaya.MGlobal.executeCommand(cmd)
elif destinationNode.hasFn(OpenMaya.MFn.kLambert):
dest = OpenMaya.MFnDependencyNode(destinationNode)
srcPlug = src.findPlug("outColor")
destPlug = dest.findPlug("color")
if (not srcPlug.isNull()) and (not destPlug.isNull()):
if force:
cmd = "connectAttr -f %s %s" % (srcPlug.name(), destPlug.name())
else:
cmd = "connectAttr %s %s" % (srcPlug.name(), destPlug.name())
OpenMaya.MGlobal.executeCommand(cmd)
def connectNodeToAttr(self, sourceNode, destinationPlug, force):
"""
Overloaded function from MPxDragAndDropBehavior
this method will assign the correct output from the slope shader
onto the given attribute.
"""
src = OpenMaya.MFnDependencyNode(sourceNode)
if destinationPlug.node().hasFn(OpenMaya.MFn.kLambert):
if src.typeName() == kSlopeNodeName:
srcPlug = src.findPlug("outColor")
if (not srcPlug.isNull()) and (not destinationPlug.isNull()):
cmd = "connectAttr %s %s" % (srcPlug.name(), destinationPlug.name())
OpenMaya.MGlobal.executeCommand(cmd)
else:
destinationNode = destinationPlug.node()
self.connectNodeToNode(sourceNode, destinationNode, force)
def _findShadingEngine(self, node):
"""
Given the material MObject this method will
return the shading group that it is assigned to.
if there is no shading group associated with
the material than a null MObject is passed back.
"""
nodeFn = OpenMaya.MFnDependencyNode (node)
srcPlug = nodeFn.findPlug("outColor")
nodeConnections = OpenMaya.MPlugArray()
srcPlug.connectedTo(nodeConnections, False, True)
for i in range(nodeConnections.length()):
theNode = nodeConnections[i].node()
if theNode.hasFn(OpenMaya.MFn.kShadingEngine):
return theNode
return OpenMaya.MObject()
def nodeCreator():
return OpenMayaMPx.asMPxPtr(slopeShader())
def behaviourCreator():
return OpenMayaMPx.asMPxPtr(slopeShaderBehavior())
def nodeInitializer():
nAttr = OpenMaya.MFnNumericAttribute()
nMAttr = OpenMaya.MFnMatrixAttribute()
nTAttr = OpenMaya.MFnTypedAttribute()
nGAttr = OpenMaya.MFnGenericAttribute()
slopeShader.aAngle = nAttr.create( "angle", "ang", OpenMaya.MFnNumericData.kFloat )
nAttr.setDefault(30.0)
nAttr.setMin(0.0)
nAttr.setMax(100.0)
nAttr.setKeyable(1)
nAttr.setStorable(1)
nAttr.setReadable(1)
nAttr.setWritable(1)
slopeShader.aColor1 = nAttr.createColor("walkableColor", "w")
nAttr.setDefault(0.0, 1.0, 0.0)
nAttr.setKeyable(1)
nAttr.setStorable(1)
nAttr.setUsedAsColor(1)
nAttr.setReadable(1)
nAttr.setWritable(1)
slopeShader.aColor2 = nAttr.createColor( "nonWalkableColor", "nw" )
nAttr.setDefault(1.0, 0.0, 0.0)
nAttr.setKeyable(1)
nAttr.setStorable(1)
nAttr.setUsedAsColor(1)
nAttr.setReadable(1)
nAttr.setWritable(1)
slopeShader.aTriangleNormalCamera = nAttr.createPoint( "triangleNormalCamera", "n" )
nAttr.setStorable(0)
nAttr.setHidden(1)
nAttr.setReadable(1)
nAttr.setWritable(1)
slopeShader.aMatrixEyeToWorld = nMAttr.create( "matrixEyeToWorld", "mew", OpenMaya.MFnMatrixAttribute.kFloat )
nAttr.setHidden(1)
nMAttr.setWritable(1)
slopeShader.aOutColor = nAttr.createColor( "outColor", "oc" )
nAttr.setStorable(0)
nAttr.setHidden(0)
nAttr.setReadable(1)
nAttr.setWritable(0)
meshTypeId = OpenMaya.MTypeId(OpenMaya.MFnData.kMesh)
slopeShader.aDirtyShaderAttr = nGAttr.create( "dirtyShaderPlug", "dsp")
nGAttr.setArray(1)
nGAttr.setHidden(0)
nGAttr.setUsesArrayDataBuilder(1)
nGAttr.setReadable(0)
nGAttr.setStorable(1)
nGAttr.setIndexMatters(0)
slopeShader.addAttribute(slopeShader.aAngle)
slopeShader.addAttribute(slopeShader.aColor1)
slopeShader.addAttribute(slopeShader.aColor2)
slopeShader.addAttribute(slopeShader.aTriangleNormalCamera)
slopeShader.addAttribute(slopeShader.aOutColor)
slopeShader.addAttribute(slopeShader.aMatrixEyeToWorld)
slopeShader.addAttribute(slopeShader.aDirtyShaderAttr)
slopeShader.attributeAffects (slopeShader.aAngle, slopeShader.aOutColor)
slopeShader.attributeAffects (slopeShader.aColor1, slopeShader.aOutColor)
slopeShader.attributeAffects (slopeShader.aColor2, slopeShader.aOutColor)
slopeShader.attributeAffects (slopeShader.aTriangleNormalCamera, slopeShader.aOutColor)
slopeShader.attributeAffects (slopeShader.aDirtyShaderAttr, slopeShader.aOutColor)
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.registerNode(kSlopeNodeName, kSlopeNodeId, nodeCreator, nodeInitializer, OpenMayaMPx.MPxNode.kDependNode, kSlopeNodeClassify)
except:
sys.stderr.write("Failed to register node: %s" % kSlopeNodeName )
raise
try:
mplugin.registerDragAndDropBehavior(kSlopeShaderBehaviourName, behaviourCreator)
except:
sys.stderr.write("Failed to register behaviour: %s" % kSlopeShaderBehaviourName)
postCmd = "if( `window -exists createRenderNodeWindow` ) {refreshCreateRenderNodeWindow(\"%s\");}\n" % kSlopeNodeClassify
OpenMaya.MGlobal.executeCommand(postCmd)
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")
try:
mplugin.deregisterNode(kSlopeNodeId)
except:
sys.stderr.write( "Failed to unregister node: %s" % kSlopeNodeName )
raise
try:
plugin.deregisterDragAndDropBehavior(kSlopeShaderBehaviourName)
except:
sys.stderr.write("Failed to deregister behaviour: %s" % kSlopeShaderBehaviourName)
postCmd = "if( `window -exists createRenderNodeWindow` ) {refreshCreateRenderNodeWindow(\"%s\");}\n" % kSlopeNodeClassify
OpenMaya.MGlobal.executeCommand(postCmd)