1 from __future__
import division
12 from builtins
import object
13 from builtins
import range
16 import maya.api.OpenMaya
as om
17 import maya.api.OpenMayaUI
as omui
18 import maya.api.OpenMayaAnim
as oma
19 import maya.api.OpenMayaRender
as omr
23 The presence of this function tells Maya that the plugin produces, and
24 expects to be passed, objects created using the Maya Python API 2.0.
28 def matrixAsArray(matrix):
31 array.append(matrix[i])
36 sole = [ [ 0.00, 0.0, -0.70 ],
48 [ -0.15, 0.0, -0.14 ],
49 [ -0.16, 0.0, -0.25 ],
50 [ -0.17, 0.0, -0.35 ],
51 [ -0.17, 0.0, -0.46 ],
52 [ -0.16, 0.0, -0.54 ],
53 [ -0.13, 0.0, -0.61 ],
54 [ -0.09, 0.0, -0.65 ],
55 [ -0.04, 0.0, -0.69 ],
56 [ -0.00, 0.0, -0.70 ] ]
57 heel = [ [ 0.00, 0.0, 0.06 ],
73 [ -0.00, 0.0, 0.06 ] ]
77 def convertString(str):
79 if sys.version_info.major
is 3:
80 return str.encode(
'utf-8')
89 class footPrint(omui.MPxLocatorNode):
90 id = om.MTypeId( 0x0008004b )
91 drawDbClassification =
"drawdb/geometry/footPrint_RenderUtilities_py"
92 drawRegistrantId =
"FootprintNode_RenderUtilities_py"
102 unitFn = om.MFnUnitAttribute()
104 footPrint.size = unitFn.create(
"size",
"sz", om.MFnUnitAttribute.kDistance )
105 unitFn.default = om.MDistance(1.0)
107 om.MPxNode.addAttribute( footPrint.size )
110 omui.MPxLocatorNode.__init__(self)
112 def compute(self, plug, data):
115 def draw(self, view, path, style, status):
118 thisNode = self.thisMObject()
119 plug = om.MPlug( thisNode, footPrint.size )
120 sizeVal = plug.asMDistance()
121 multiplier = sizeVal.asCentimeters()
123 global sole, soleCount
124 global heel, heelCount
129 import maya.OpenMayaRender
as v1omr
130 glRenderer = v1omr.MHardwareRenderer.theRenderer()
131 glFT = glRenderer.glFunctionTable()
133 if ( style == omui.M3dView.kFlatShaded )
or ( style == omui.M3dView.kGouraudShaded ):
136 glFT.glPushAttrib( v1omr.MGL_CURRENT_BIT )
139 glFT.glDisable( v1omr.MGL_CULL_FACE )
141 if status == omui.M3dView.kActive:
142 view.setDrawColor( 13, omui.M3dView.kActiveColors )
144 view.setDrawColor( 13, omui.M3dView.kDormantColors )
146 glFT.glBegin( v1omr.MGL_TRIANGLE_FAN )
147 for i
in range(soleCount-1):
148 glFT.glVertex3f( sole[i][0] * multiplier, sole[i][1] * multiplier, sole[i][2] * multiplier )
151 glFT.glBegin( v1omr.MGL_TRIANGLE_FAN )
152 for i
in range(heelCount-1):
153 glFT.glVertex3f( heel[i][0] * multiplier, heel[i][1] * multiplier, heel[i][2] * multiplier )
160 glFT.glBegin( v1omr.MGL_LINES )
161 for i
in range(soleCount-1):
162 glFT.glVertex3f( sole[i][0] * multiplier, sole[i][1] * multiplier, sole[i][2] * multiplier )
163 glFT.glVertex3f( sole[i+1][0] * multiplier, sole[i+1][1] * multiplier, sole[i+1][2] * multiplier )
165 for i
in range(heelCount-1):
166 glFT.glVertex3f( heel[i][0] * multiplier, heel[i][1] * multiplier, heel[i][2] * multiplier )
167 glFT.glVertex3f( heel[i+1][0] * multiplier, heel[i+1][1] * multiplier, heel[i+1][2] * multiplier )
173 view.setDrawColor( om.MColor( (0.1, 0.8, 0.8, 1.0) ) )
174 view.drawText(
"Footprint", om.MPoint( 0.0, 0.0, 0.0 ), omui.M3dView.kCenter )
179 def boundingBox(self):
182 thisNode = self.thisMObject()
183 plug = om.MPlug( thisNode, footPrint.size )
184 sizeVal = plug.asMDistance()
185 multiplier = sizeVal.asCentimeters()
187 corner1 = om.MPoint( -0.17, 0.0, -0.7 )
188 corner2 = om.MPoint( 0.17, 0.0, 0.3 )
190 corner1 *= multiplier
191 corner2 *= multiplier
193 return om.MBoundingBox( corner1, corner2 )
200 class footPrintData(om.MUserData):
202 om.MUserData.__init__(self,
False)
204 self.fMultiplier = 0.0
205 self.fColor = [0.0, 0.0, 0.0]
206 self.fCustomBoxDraw =
False
207 self.fDrawOV = om.MDAGDrawOverrideInfo()
210 class footPrintDrawAgent(object):
214 self.mBoundingboxVertexBuffer =
None
215 self.mBoundingboxIndexBuffer =
None
216 self.mSoleVertexBuffer =
None
217 self.mHeelVertexBuffer =
None
218 self.mSoleWireIndexBuffer =
None
219 self.mHeelWireIndexBuffer =
None
220 self.mSoleShadedIndexBuffer =
None
221 self.mHeelShadedIndexBuffer =
None
224 if self.mShader
is not None:
225 shaderMgr = omr.MRenderer.getShaderManager()
226 if shaderMgr
is not None:
227 shaderMgr.releaseShader(self.mShader)
230 self.mBoundingboxVertexBuffer =
None
231 self.mBoundingboxIndexBuffer =
None
232 self.mSoleVertexBuffer =
None
233 self.mHeelVertexBuffer =
None
234 self.mSoleWireIndexBuffer =
None
235 self.mHeelWireIndexBuffer =
None
236 self.mSoleShadedIndexBuffer =
None
237 self.mHeelShadedIndexBuffer =
None
239 def beginDraw(self, context, color, scale):
243 if self.mShader
is not None:
244 self.mShader.setParameter(
"matColor", color)
245 self.mShader.setParameter(
"scale", scale)
246 self.mShader.bind(context)
247 self.mShader.activatePass(context, 0)
249 def drawShaded(self, context):
250 global soleCount, heelCount
253 if self.mSoleVertexBuffer
is not None and self.mSoleShadedIndexBuffer
is not None:
254 omr.MRenderUtilities.drawSimpleMesh(context, self.mSoleVertexBuffer, self.mSoleShadedIndexBuffer, omr.MGeometry.kTriangles, 0, 3 * (soleCount-2))
257 if self.mHeelVertexBuffer
is not None and self.mHeelShadedIndexBuffer
is not None:
258 omr.MRenderUtilities.drawSimpleMesh(context, self.mHeelVertexBuffer, self.mHeelShadedIndexBuffer, omr.MGeometry.kTriangles, 0, 3 * (heelCount-2))
260 def drawBoundingBox(self, context):
261 if self.mBoundingboxVertexBuffer
is not None and self.mBoundingboxIndexBuffer
is not None:
262 omr.MRenderUtilities.drawSimpleMesh(context, self.mBoundingboxVertexBuffer, self.mBoundingboxIndexBuffer, omr.MGeometry.kLines, 0, 24)
264 def drawWireframe(self, context):
265 global soleCount, heelCount
268 if self.mSoleVertexBuffer
is not None and self.mSoleWireIndexBuffer
is not None:
269 omr.MRenderUtilities.drawSimpleMesh(context, self.mSoleVertexBuffer, self.mSoleWireIndexBuffer, omr.MGeometry.kLines, 0, 2 * (soleCount-1))
272 if self.mHeelVertexBuffer
is not None and self.mHeelWireIndexBuffer
is not None:
273 omr.MRenderUtilities.drawSimpleMesh(context, self.mHeelVertexBuffer, self.mHeelWireIndexBuffer, omr.MGeometry.kLines, 0, 2 * (heelCount-1))
275 def endDraw(self, context):
276 if self.mShader
is not None:
277 self.mShader.unbind(context)
279 def initShader(self):
280 if self.mShader
is None:
281 shaderMgr = omr.MRenderer.getShaderManager()
282 if shaderMgr
is not None:
283 shaderCode = self.getShaderCode()
284 self.mShader = shaderMgr.getEffectsBufferShader(shaderCode, len(shaderCode),
"")
286 return self.mShader
is not None
288 def getShaderCode(self):
289 return convertString(
"")
291 def initBuffers(self):
292 global soleCount, sole
293 global heelCount, heel
295 if self.mBoundingboxVertexBuffer
is None:
297 rawData = [ [ -0.5, -0.5, -0.5 ],
306 desc = omr.MVertexBufferDescriptor(
"", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
307 self.mBoundingboxVertexBuffer = omr.MVertexBuffer(desc)
309 dataAddress = self.mBoundingboxVertexBuffer.acquire(count,
True)
310 data = ((ctypes.c_float * 3)*count).from_address(dataAddress)
312 for i
in range(count):
313 data[i][0] = rawData[i][0]
314 data[i][1] = rawData[i][1]
315 data[i][2] = rawData[i][2]
317 self.mBoundingboxVertexBuffer.commit(dataAddress)
321 if self.mBoundingboxIndexBuffer
is None:
336 self.mBoundingboxIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
338 dataAddress = self.mBoundingboxIndexBuffer.acquire(count,
True)
339 data = (ctypes.c_uint * count).from_address(dataAddress)
341 for i
in range(count):
344 self.mBoundingboxIndexBuffer.commit(dataAddress)
348 if self.mSoleVertexBuffer
is None:
349 desc = omr.MVertexBufferDescriptor(
"", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
350 self.mSoleVertexBuffer = omr.MVertexBuffer(desc)
352 dataAddress = self.mSoleVertexBuffer.acquire(soleCount,
True)
353 data = ((ctypes.c_float * 3)*soleCount).from_address(dataAddress)
355 for i
in range(soleCount):
356 data[i][0] = sole[i][0]
357 data[i][1] = sole[i][1]
358 data[i][2] = sole[i][2]
360 self.mSoleVertexBuffer.commit(dataAddress)
364 if self.mHeelVertexBuffer
is None:
365 desc = omr.MVertexBufferDescriptor(
"", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
366 self.mHeelVertexBuffer = omr.MVertexBuffer(desc)
368 dataAddress = self.mHeelVertexBuffer.acquire(heelCount,
True)
369 data = ((ctypes.c_float * 3)*heelCount).from_address(dataAddress)
371 for i
in range(heelCount):
372 data[i][0] = heel[i][0]
373 data[i][1] = heel[i][1]
374 data[i][2] = heel[i][2]
376 self.mHeelVertexBuffer.commit(dataAddress)
380 if self.mSoleWireIndexBuffer
is None:
381 count = 2 * (soleCount-1)
403 self.mSoleWireIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
405 dataAddress = self.mSoleWireIndexBuffer.acquire(count,
True)
406 data = (ctypes.c_uint * count).from_address(dataAddress)
408 for i
in range(count):
411 self.mSoleWireIndexBuffer.commit(dataAddress)
415 if self.mHeelWireIndexBuffer
is None:
416 count = 2 * (heelCount-1)
434 self.mHeelWireIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
436 dataAddress = self.mHeelWireIndexBuffer.acquire(count,
True)
437 data = (ctypes.c_uint * count).from_address(dataAddress)
439 for i
in range(count):
442 self.mHeelWireIndexBuffer.commit(dataAddress)
446 if self.mSoleShadedIndexBuffer
is None:
447 count = 3 * (soleCount-2)
468 self.mSoleShadedIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
470 dataAddress = self.mSoleShadedIndexBuffer.acquire(count,
True)
471 data = (ctypes.c_uint * count).from_address(dataAddress)
473 for i
in range(count):
476 self.mSoleShadedIndexBuffer.commit(dataAddress)
480 if self.mHeelShadedIndexBuffer
is None:
481 count = 3 * (heelCount-2)
498 self.mHeelShadedIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
500 dataAddress = self.mHeelShadedIndexBuffer.acquire(count,
True)
501 data = (ctypes.c_uint * count).from_address(dataAddress)
503 for i
in range(count):
506 self.mHeelShadedIndexBuffer.commit(dataAddress)
513 class footPrintDrawAgentGL(footPrintDrawAgent):
515 footPrintDrawAgent.__init__(self)
517 def getShaderCode(self):
519 float4x4 gWVXf : WorldView;
520 float4x4 gPXf : Projection;
521 float4 matColor = float4(0.8, 0.2, 0.0, 1.0);
525 float3 position : POSITION;
529 float4 position : POSITION;
532 vsOutput footPrintVS(appdata IN)
534 float4x4 scaleMat = float4x4(scale, 0, 0, 0,
538 float4x4 transform = mul(gPXf, mul(gWVXf, scaleMat));
541 OUT.position = mul(transform, float4(IN.position, 1));
545 float4 footPrintPS(vsOutput IN) : COLOR
554 VertexShader = compile glslv footPrintVS();
555 PixelShader = compile glslf footPrintPS();
559 return convertString(shaderCode)
562 class footPrintDrawAgentDX(footPrintDrawAgent):
564 footPrintDrawAgent.__init__(self)
566 def getShaderCode(self):
568 extern float4x4 gWVXf : WorldView;
569 extern float4x4 gPXf : Projection;
570 extern float4 matColor = float4(0.8, 0.2, 0.0, 1.0);
571 extern float scale = 1.0;
574 float3 position : POSITION;
578 float4 position : SV_Position;
581 vsOutput footPrintVS(appdata IN)
583 float4x4 scaleMat = float4x4(scale, 0, 0, 0,
587 float4x4 transform = mul(mul(scaleMat, gWVXf), gPXf);
590 OUT.position = mul(float4(IN.position, 1), transform);
594 float4 footPrintPS(vsOutput IN) : SV_Target
603 SetVertexShader( CompileShader( vs_5_0, footPrintVS() ));
604 SetGeometryShader( NULL );
605 SetPixelShader( CompileShader( ps_5_0, footPrintPS() ));
609 return convertString(shaderCode)
615 class footPrintDrawOverride(omr.MPxDrawOverride):
618 return footPrintDrawOverride(obj)
621 def draw(context, data):
624 if not isinstance(footData, footPrintData):
628 objectOverrideInfo = footData.fDrawOV
631 debugDestination =
False
633 destination = context.renderingDestination()
634 destinationType =
"3d viewport"
635 if destination[0] == omr.MFrameContext.k2dViewport:
636 destinationType =
"2d viewport"
637 elif destination[0] == omr.MFrameContext.kImage:
638 destinationType =
"image"
640 print(
"footprint node render destination is " + destinationType +
". Destination name=" + str(destination[1]))
643 if objectOverrideInfo.overrideEnabled
and not objectOverrideInfo.enableVisible:
647 displayStyle = context.getDisplayStyle()
648 drawAsBoundingbox = (displayStyle & omr.MFrameContext.kBoundingBox)
or (objectOverrideInfo.lod == om.MDAGDrawOverrideInfo.kLODBoundingBox)
654 if drawAsBoundingbox
and not footData.fCustomBoxDraw:
657 animPlay = oma.MAnimControl.isPlaying()
658 animScrub = oma.MAnimControl.isScrubbing()
660 if (animPlay
or animScrub)
and not objectOverrideInfo.playbackVisible:
665 if context.inUserInteraction()
or context.userChangingViewContext():
666 if not animPlay
and not animScrub:
667 drawAsBoundingbox =
True
675 passCtx = context.getPassContext()
676 passSemantics = passCtx.passSemantics()
677 castingShadows =
False
678 for semantic
in passSemantics:
679 if semantic == omr.MPassContext.kShadowPassSemantic:
680 castingShadows =
True
682 debugPassInformation =
False
683 if debugPassInformation:
684 passId = passCtx.passIdentifier()
685 print(
"footprint node drawing in pass[" + str(passId) +
"], semantic[" + str(passSemantics) +
"]")
688 multiplier = footData.fMultiplier
689 color = [ footData.fColor[0], footData.fColor[1], footData.fColor[2], 1.0 ]
691 requireBlending =
False
695 if not castingShadows:
698 if displayStyle & omr.MFrameContext.kDefaultMaterial:
699 color[0] = color[1] = color[2] = (color[0] + color[1] + color[2]) / 3.0
703 elif displayStyle & omr.MFrameContext.kXray:
704 requireBlending =
True
709 stateMgr = context.getStateManager()
711 oldRasterState =
None
712 rasterStateModified =
False
714 if stateMgr
is not None and (displayStyle & omr.MFrameContext.kGouraudShaded):
718 if blendState
is None:
719 desc = omr.MBlendStateDesc()
720 desc.targetBlends[0].blendEnable =
True
721 desc.targetBlends[0].destinationBlend = omr.MBlendStatekInvSourceAlpha
722 desc.targetBlends[0].alphaDestinationBlend = omr.MBlendStatekInvSourceAlpha
723 blendState = stateMgr.acquireBlendState(desc)
725 if blendState
is not None:
726 oldBlendState = stateMgr.getBlendState()
727 stateMgr.setBlendState(blendState)
731 oldRasterState = stateMgr.getRasterizerState()
733 desc = oldRasterState.desc()
736 cullMode = omr.MRasterizerState.kCullNone
737 if desc.cullMode != cullMode:
739 if rasterState
is None:
741 desc.cullMode = cullMode
742 rasterState = stateMgr.acquireRasterizerState(desc)
744 if rasterState
is not None:
745 rasterStateModified =
True
746 stateMgr.setRasterizerState(rasterState)
754 if drawAgent
is None:
755 if omr.MRenderer.drawAPIIsOpenGL():
756 drawAgent = footPrintDrawAgentGL()
758 drawAgent = footPrintDrawAgentDX()
760 if not drawAgent
is None:
762 drawAgent.beginDraw( context, color, multiplier )
764 if drawAsBoundingbox:
765 drawAgent.drawBoundingBox( context )
769 overideTemplated = objectOverrideInfo.overrideEnabled
and objectOverrideInfo.displayType == om.MDAGDrawOverrideInfo.kDisplayTypeTemplate
771 overrideNoShaded = objectOverrideInfo.overrideEnabled
and not objectOverrideInfo.enableShading
773 if overideTemplated
or overrideNoShaded:
774 drawAgent.drawWireframe( context )
777 if (displayStyle & omr.MFrameContext.kGouraudShaded)
or (displayStyle & omr.MFrameContext.kTextured):
778 drawAgent.drawShaded( context )
780 if (displayStyle & omr.MFrameContext.kWireFrame):
781 drawAgent.drawWireframe( context )
783 drawAgent.endDraw( context )
790 if stateMgr
is not None and (displayStyle & omr.MFrameContext.kGouraudShaded):
791 if oldBlendState
is not None:
792 stateMgr.setBlendState(oldBlendState)
794 if rasterStateModified
and oldRasterState
is not None:
795 stateMgr.setRasterizerState(oldRasterState)
797 def __init__(self, obj):
798 omr.MPxDrawOverride.__init__(self, obj, footPrintDrawOverride.draw)
803 self.mCustomBoxDraw =
True
804 self.mCurrentBoundingBox = om.MBoundingBox()
806 def supportedDrawAPIs(self):
808 return omr.MRenderer.kOpenGL | omr.MRenderer.kDirectX11
810 def isBounded(self, objPath, cameraPath):
813 def boundingBox(self, objPath, cameraPath):
814 corner1 = om.MPoint( -0.17, 0.0, -0.7 )
815 corner2 = om.MPoint( 0.17, 0.0, 0.3 )
817 multiplier = self.getMultiplier(objPath)
818 corner1 *= multiplier
819 corner2 *= multiplier
821 self.mCurrentBoundingBox.clear()
822 self.mCurrentBoundingBox.expand( corner1 )
823 self.mCurrentBoundingBox.expand( corner2 )
825 return self.mCurrentBoundingBox
827 def disableInternalBoundingBoxDraw(self):
828 return self.mCustomBoxDraw
830 def prepareForDraw(self, objPath, cameraPath, frameContext, oldData):
833 if not isinstance(data, footPrintData):
834 data = footPrintData()
837 data.fMultiplier = self.getMultiplier(objPath)
838 color = omr.MGeometryUtilities.wireframeColor(objPath)
839 data.fColor = [ color.r, color.g, color.b ]
840 data.fCustomBoxDraw = self.mCustomBoxDraw
843 data.fDrawOV = objPath.getDrawOverrideInfo()
847 def hasUIDrawables(self):
850 def addUIDrawables(self, objPath, drawManager, frameContext, data):
852 pos = om.MPoint( 0.0, 0.0, 0.0 )
853 textColor = om.MColor( (0.1, 0.8, 0.8, 1.0) )
855 drawManager.beginDrawable()
857 drawManager.setColor( textColor )
858 drawManager.setFontSize( omr.MUIDrawManager.kSmallFontSize )
859 drawManager.text(pos,
"Footprint", omr.MUIDrawManager.kCenter )
861 drawManager.endDrawable()
863 def getMultiplier(self, objPath):
865 footprintNode = objPath.node()
866 plug = om.MPlug(footprintNode, footPrint.size)
868 sizeVal = plug.asMDistance()
869 return sizeVal.asCentimeters()
873 def initializePlugin(obj):
874 plugin = om.MFnPlugin(obj,
"Autodesk",
"3.0",
"Any")
877 plugin.registerNode(
"py2FootPrint", footPrint.id, footPrint.creator, footPrint.initialize, om.MPxNode.kLocatorNode, footPrint.drawDbClassification)
879 sys.stderr.write(
"Failed to register node\n")
883 omr.MDrawRegistry.registerDrawOverrideCreator(footPrint.drawDbClassification, footPrint.drawRegistrantId, footPrintDrawOverride.creator)
885 sys.stderr.write(
"Failed to register override\n")
888 def uninitializePlugin(obj):
889 plugin = om.MFnPlugin(obj)
892 plugin.deregisterNode(footPrint.id)
894 sys.stderr.write(
"Failed to deregister node\n")
898 omr.MDrawRegistry.deregisterDrawOverrideCreator(footPrint.drawDbClassification, footPrint.drawRegistrantId)
900 sys.stderr.write(
"Failed to deregister override\n")