13 import maya.api.OpenMaya
as om
14 import maya.api.OpenMayaUI
as omui
15 import maya.api.OpenMayaAnim
as oma
16 import maya.api.OpenMayaRender
as omr
20 The presence of this function tells Maya that the plugin produces, and
21 expects to be passed, objects created using the Maya Python API 2.0.
25 def matrixAsArray(matrix):
28 array.append(matrix[i])
33 sole = [ [ 0.00, 0.0, -0.70 ],
45 [ -0.15, 0.0, -0.14 ],
46 [ -0.16, 0.0, -0.25 ],
47 [ -0.17, 0.0, -0.35 ],
48 [ -0.17, 0.0, -0.46 ],
49 [ -0.16, 0.0, -0.54 ],
50 [ -0.13, 0.0, -0.61 ],
51 [ -0.09, 0.0, -0.65 ],
52 [ -0.04, 0.0, -0.69 ],
53 [ -0.00, 0.0, -0.70 ] ]
54 heel = [ [ 0.00, 0.0, 0.06 ],
70 [ -0.00, 0.0, 0.06 ] ]
80 class footPrint(omui.MPxLocatorNode):
81 id = om.MTypeId( 0x80007 )
82 drawDbClassification =
"drawdb/geometry/footPrint"
83 drawRegistrantId =
"FootprintNodePlugin"
93 unitFn = om.MFnUnitAttribute()
95 footPrint.size = unitFn.create(
"size",
"sz", om.MFnUnitAttribute.kDistance )
96 unitFn.default = om.MDistance(1.0)
98 om.MPxNode.addAttribute( footPrint.size )
101 omui.MPxLocatorNode.__init__(self)
103 def compute(self, plug, data):
106 def draw(self, view, path, style, status):
109 thisNode = self.thisMObject()
110 plug = om.MPlug( thisNode, footPrint.size )
111 sizeVal = plug.asMDistance()
112 multiplier = sizeVal.asCentimeters()
114 global sole, soleCount
115 global heel, heelCount
120 import maya.OpenMayaRender
as v1omr
121 glRenderer = v1omr.MHardwareRenderer.theRenderer()
122 glFT = glRenderer.glFunctionTable()
124 if ( style == omui.M3dView.kFlatShaded )
or ( style == omui.M3dView.kGouraudShaded ):
127 glFT.glPushAttrib( v1omr.MGL_CURRENT_BIT )
130 glFT.glDisable( v1omr.MGL_CULL_FACE )
132 if status == omui.M3dView.kActive:
133 view.setDrawColor( 13, omui.M3dView.kActiveColors )
135 view.setDrawColor( 13, omui.M3dView.kDormantColors )
137 glFT.glBegin( v1omr.MGL_TRIANGLE_FAN )
138 for i
in range(soleCount-1):
139 glFT.glVertex3f( sole[i][0] * multiplier, sole[i][1] * multiplier, sole[i][2] * multiplier )
142 glFT.glBegin( v1omr.MGL_TRIANGLE_FAN )
143 for i
in range(heelCount-1):
144 glFT.glVertex3f( heel[i][0] * multiplier, heel[i][1] * multiplier, heel[i][2] * multiplier )
151 glFT.glBegin( v1omr.MGL_LINES )
152 for i
in range(soleCount-1):
153 glFT.glVertex3f( sole[i][0] * multiplier, sole[i][1] * multiplier, sole[i][2] * multiplier )
154 glFT.glVertex3f( sole[i+1][0] * multiplier, sole[i+1][1] * multiplier, sole[i+1][2] * multiplier )
156 for i
in range(heelCount-1):
157 glFT.glVertex3f( heel[i][0] * multiplier, heel[i][1] * multiplier, heel[i][2] * multiplier )
158 glFT.glVertex3f( heel[i+1][0] * multiplier, heel[i+1][1] * multiplier, heel[i+1][2] * multiplier )
164 view.setDrawColor( om.MColor( (0.1, 0.8, 0.8, 1.0) ) )
165 view.drawText(
"Footprint", om.MPoint( 0.0, 0.0, 0.0 ), omui.M3dView.kCenter )
170 def boundingBox(self):
173 thisNode = self.thisMObject()
174 plug = om.MPlug( thisNode, footPrint.size )
175 sizeVal = plug.asMDistance()
176 multiplier = sizeVal.asCentimeters()
178 corner1 = om.MPoint( -0.17, 0.0, -0.7 )
179 corner2 = om.MPoint( 0.17, 0.0, 0.3 )
181 corner1 *= multiplier
182 corner2 *= multiplier
184 return om.MBoundingBox( corner1, corner2 )
191 class footPrintData(om.MUserData):
193 om.MUserData.__init__(self,
False)
195 self.fMultiplier = 0.0
196 self.fColor = [0.0, 0.0, 0.0]
197 self.fCustomBoxDraw =
False
198 self.fDrawOV = om.MDAGDrawOverrideInfo()
201 class footPrintDrawAgent:
205 self.mBoundingboxVertexBuffer =
None
206 self.mBoundingboxIndexBuffer =
None
207 self.mSoleVertexBuffer =
None
208 self.mHeelVertexBuffer =
None
209 self.mSoleWireIndexBuffer =
None
210 self.mHeelWireIndexBuffer =
None
211 self.mSoleShadedIndexBuffer =
None
212 self.mHeelShadedIndexBuffer =
None
215 if self.mShader
is not None:
216 shaderMgr = omr.MRenderer.getShaderManager()
217 if shaderMgr
is not None:
218 shaderMgr.releaseShader(self.mShader)
221 self.mBoundingboxVertexBuffer =
None
222 self.mBoundingboxIndexBuffer =
None
223 self.mSoleVertexBuffer =
None
224 self.mHeelVertexBuffer =
None
225 self.mSoleWireIndexBuffer =
None
226 self.mHeelWireIndexBuffer =
None
227 self.mSoleShadedIndexBuffer =
None
228 self.mHeelShadedIndexBuffer =
None
230 def beginDraw(self, context, color, scale):
234 if self.mShader
is not None:
235 self.mShader.setParameter(
"matColor", color)
236 self.mShader.setParameter(
"scale", scale)
237 self.mShader.bind(context)
238 self.mShader.activatePass(context, 0)
240 def drawShaded(self, context):
241 global soleCount, heelCount
244 if self.mSoleVertexBuffer
is not None and self.mSoleShadedIndexBuffer
is not None:
245 omr.MRenderUtilities.drawSimpleMesh(context, self.mSoleVertexBuffer, self.mSoleShadedIndexBuffer, omr.MGeometry.kTriangles, 0, 3 * (soleCount-2))
248 if self.mHeelVertexBuffer
is not None and self.mHeelShadedIndexBuffer
is not None:
249 omr.MRenderUtilities.drawSimpleMesh(context, self.mHeelVertexBuffer, self.mHeelShadedIndexBuffer, omr.MGeometry.kTriangles, 0, 3 * (heelCount-2))
251 def drawBoundingBox(self, context):
252 if self.mBoundingboxVertexBuffer
is not None and self.mBoundingboxIndexBuffer
is not None:
253 omr.MRenderUtilities.drawSimpleMesh(context, self.mBoundingboxVertexBuffer, self.mBoundingboxIndexBuffer, omr.MGeometry.kLines, 0, 24)
255 def drawWireframe(self, context):
256 global soleCount, heelCount
259 if self.mSoleVertexBuffer
is not None and self.mSoleWireIndexBuffer
is not None:
260 omr.MRenderUtilities.drawSimpleMesh(context, self.mSoleVertexBuffer, self.mSoleWireIndexBuffer, omr.MGeometry.kLines, 0, 2 * (soleCount-1))
263 if self.mHeelVertexBuffer
is not None and self.mHeelWireIndexBuffer
is not None:
264 omr.MRenderUtilities.drawSimpleMesh(context, self.mHeelVertexBuffer, self.mHeelWireIndexBuffer, omr.MGeometry.kLines, 0, 2 * (heelCount-1))
266 def endDraw(self, context):
267 if self.mShader
is not None:
268 self.mShader.unbind(context)
270 def initShader(self):
271 if self.mShader
is None:
272 shaderMgr = omr.MRenderer.getShaderManager()
273 if shaderMgr
is not None:
274 shaderCode = self.getShaderCode()
275 self.mShader = shaderMgr.getEffectsBufferShader(shaderCode, len(shaderCode),
"")
277 return self.mShader
is not None
279 def shaderCode(self):
282 def initBuffers(self):
283 global soleCount, sole
284 global heelCount, heel
286 if self.mBoundingboxVertexBuffer
is None:
288 rawData = [ [ -0.5, -0.5, -0.5 ],
297 desc = omr.MVertexBufferDescriptor(
"", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
298 self.mBoundingboxVertexBuffer = omr.MVertexBuffer(desc)
300 dataAddress = self.mBoundingboxVertexBuffer.acquire(count,
True)
301 data = ((ctypes.c_float * 3)*count).from_address(dataAddress)
303 for i
in range(count):
304 data[i][0] = rawData[i][0]
305 data[i][1] = rawData[i][1]
306 data[i][2] = rawData[i][2]
308 self.mBoundingboxVertexBuffer.commit(dataAddress)
312 if self.mBoundingboxIndexBuffer
is None:
327 self.mBoundingboxIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
329 dataAddress = self.mBoundingboxIndexBuffer.acquire(count,
True)
330 data = (ctypes.c_uint * count).from_address(dataAddress)
332 for i
in range(count):
335 self.mBoundingboxIndexBuffer.commit(dataAddress)
339 if self.mSoleVertexBuffer
is None:
340 desc = omr.MVertexBufferDescriptor(
"", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
341 self.mSoleVertexBuffer = omr.MVertexBuffer(desc)
343 dataAddress = self.mSoleVertexBuffer.acquire(soleCount,
True)
344 data = ((ctypes.c_float * 3)*soleCount).from_address(dataAddress)
346 for i
in range(soleCount):
347 data[i][0] = sole[i][0]
348 data[i][1] = sole[i][1]
349 data[i][2] = sole[i][2]
351 self.mSoleVertexBuffer.commit(dataAddress)
355 if self.mHeelVertexBuffer
is None:
356 desc = omr.MVertexBufferDescriptor(
"", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
357 self.mHeelVertexBuffer = omr.MVertexBuffer(desc)
359 dataAddress = self.mHeelVertexBuffer.acquire(heelCount,
True)
360 data = ((ctypes.c_float * 3)*heelCount).from_address(dataAddress)
362 for i
in range(heelCount):
363 data[i][0] = heel[i][0]
364 data[i][1] = heel[i][1]
365 data[i][2] = heel[i][2]
367 self.mHeelVertexBuffer.commit(dataAddress)
371 if self.mSoleWireIndexBuffer
is None:
372 count = 2 * (soleCount-1)
394 self.mSoleWireIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
396 dataAddress = self.mSoleWireIndexBuffer.acquire(count,
True)
397 data = (ctypes.c_uint * count).from_address(dataAddress)
399 for i
in range(count):
402 self.mSoleWireIndexBuffer.commit(dataAddress)
406 if self.mHeelWireIndexBuffer
is None:
407 count = 2 * (heelCount-1)
425 self.mHeelWireIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
427 dataAddress = self.mHeelWireIndexBuffer.acquire(count,
True)
428 data = (ctypes.c_uint * count).from_address(dataAddress)
430 for i
in range(count):
433 self.mHeelWireIndexBuffer.commit(dataAddress)
437 if self.mSoleShadedIndexBuffer
is None:
438 count = 3 * (soleCount-2)
459 self.mSoleShadedIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
461 dataAddress = self.mSoleShadedIndexBuffer.acquire(count,
True)
462 data = (ctypes.c_uint * count).from_address(dataAddress)
464 for i
in range(count):
467 self.mSoleShadedIndexBuffer.commit(dataAddress)
471 if self.mHeelShadedIndexBuffer
is None:
472 count = 3 * (heelCount-2)
489 self.mHeelShadedIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
491 dataAddress = self.mHeelShadedIndexBuffer.acquire(count,
True)
492 data = (ctypes.c_uint * count).from_address(dataAddress)
494 for i
in range(count):
497 self.mHeelShadedIndexBuffer.commit(dataAddress)
504 class footPrintDrawAgentGL(footPrintDrawAgent):
506 footPrintDrawAgent.__init__(self)
508 def getShaderCode(self):
510 float4x4 gWVXf : WorldView;
511 float4x4 gPXf : Projection;
512 float4 matColor = float4(0.8, 0.2, 0.0, 1.0);
516 float3 position : POSITION;
520 float4 position : POSITION;
523 vsOutput footPrintVS(appdata IN)
525 float4x4 scaleMat = float4x4(scale, 0, 0, 0,
529 float4x4 transform = mul(gPXf, mul(gWVXf, scaleMat));
532 OUT.position = mul(transform, float4(IN.position, 1));
536 float4 footPrintPS(vsOutput IN) : COLOR
545 VertexShader = compile glslv footPrintVS();
546 PixelShader = compile glslf footPrintPS();
553 class footPrintDrawAgentDX(footPrintDrawAgent):
555 footPrintDrawAgent.__init__(self)
557 def getShaderCode(self):
559 extern float4x4 gWVXf : WorldView;
560 extern float4x4 gPXf : Projection;
561 extern float4 matColor = float4(0.8, 0.2, 0.0, 1.0);
562 extern float scale = 1.0;
565 float3 position : POSITION;
569 float4 position : SV_Position;
572 vsOutput footPrintVS(appdata IN)
574 float4x4 scaleMat = float4x4(scale, 0, 0, 0,
578 float4x4 transform = mul(mul(scaleMat, gWVXf), gPXf);
581 OUT.position = mul(float4(IN.position, 1), transform);
585 float4 footPrintPS(vsOutput IN) : SV_Target
594 SetVertexShader( CompileShader( vs_5_0, footPrintVS() ));
595 SetGeometryShader( NULL );
596 SetPixelShader( CompileShader( ps_5_0, footPrintPS() ));
606 class footPrintDrawOverride(omr.MPxDrawOverride):
609 return footPrintDrawOverride(obj)
612 def draw(context, data):
615 if not isinstance(footData, footPrintData):
619 objectOverrideInfo = footData.fDrawOV
622 debugDestination =
False
624 destination = context.renderingDestination()
625 destinationType =
"3d viewport"
626 if destination[0] == omr.MFrameContext.k2dViewport:
627 destinationType =
"2d viewport"
628 elif destination[0] == omr.MFrameContext.kImage:
629 destinationType =
"image"
631 print "footprint node render destination is " + destinationType +
". Destination name=" + str(destination[1])
634 if objectOverrideInfo.overrideEnabled
and not objectOverrideInfo.enableVisible:
638 displayStyle = context.getDisplayStyle()
639 drawAsBoundingbox = (displayStyle & omr.MFrameContext.kBoundingBox)
or (objectOverrideInfo.lod == om.MDAGDrawOverrideInfo.kLODBoundingBox)
645 if drawAsBoundingbox
and not footData.fCustomBoxDraw:
648 animPlay = oma.MAnimControl.isPlaying()
649 animScrub = oma.MAnimControl.isScrubbing()
651 if (animPlay
or animScrub)
and not objectOverrideInfo.playbackVisible:
656 if context.inUserInteraction()
or context.userChangingViewContext():
657 if not animPlay
and not animScrub:
658 drawAsBoundingbox =
True
666 passCtx = context.getPassContext()
667 passSemantics = passCtx.passSemantics()
668 castingShadows =
False
669 for semantic
in passSemantics:
670 if semantic == omr.MPassContext.kShadowPassSemantic:
671 castingShadows =
True
673 debugPassInformation =
False
674 if debugPassInformation:
675 passId = passCtx.passIdentifier()
676 print "footprint node drawing in pass[" + str(passId) +
"], semantic[" + str(passSemantics) +
"]"
679 multiplier = footData.fMultiplier
680 color = [ footData.fColor[0], footData.fColor[1], footData.fColor[2], 1.0 ]
682 requireBlending =
False
686 if not castingShadows:
689 if displayStyle & omr.MFrameContext.kDefaultMaterial:
690 color[0] = color[1] = color[2] = (color[0] + color[1] + color[2]) / 3.0
694 elif displayStyle & omr.MFrameContext.kXray:
695 requireBlending =
True
700 stateMgr = context.getStateManager()
702 oldRasterState =
None
703 rasterStateModified =
False
705 if stateMgr
is not None and (displayStyle & omr.MFrameContext.kGouraudShaded):
709 if blendState
is None:
710 desc = omr.MBlendStateDesc()
711 desc.targetBlends[0].blendEnable =
True
712 desc.targetBlends[0].destinationBlend = omr.MBlendStatekInvSourceAlpha
713 desc.targetBlends[0].alphaDestinationBlend = omr.MBlendStatekInvSourceAlpha
714 blendState = stateMgr.acquireBlendState(desc)
716 if blendState
is not None:
717 oldBlendState = stateMgr.getBlendState()
718 stateMgr.setBlendState(blendState)
722 oldRasterState = stateMgr.getRasterizerState()
724 desc = oldRasterState.desc()
727 cullMode = omr.MRasterizerState.kCullNone
728 if desc.cullMode != cullMode:
730 if rasterState
is None:
732 desc.cullMode = cullMode
733 rasterState = stateMgr.acquireRasterizerState(desc)
735 if rasterState
is not None:
736 rasterStateModified =
True
737 stateMgr.setRasterizerState(rasterState)
745 if drawAgent
is None:
746 if omr.MRenderer.drawAPIIsOpenGL():
747 drawAgent = footPrintDrawAgentGL()
749 drawAgent = footPrintDrawAgentDX()
751 if not drawAgent
is None:
753 drawAgent.beginDraw( context, color, multiplier )
755 if drawAsBoundingbox:
756 drawAgent.drawBoundingBox( context )
760 overideTemplated = objectOverrideInfo.overrideEnabled
and objectOverrideInfo.displayType == om.MDAGDrawOverrideInfo.kDisplayTypeTemplate
762 overrideNoShaded = objectOverrideInfo.overrideEnabled
and not objectOverrideInfo.enableShading
764 if overideTemplated
or overrideNoShaded:
765 drawAgent.drawWireframe( context )
768 if (displayStyle & omr.MFrameContext.kGouraudShaded)
or (displayStyle & omr.MFrameContext.kTextured):
769 drawAgent.drawShaded( context )
771 if (displayStyle & omr.MFrameContext.kWireFrame):
772 drawAgent.drawWireframe( context )
774 drawAgent.endDraw( context )
781 if stateMgr
is not None and (displayStyle & omr.MFrameContext.kGouraudShaded):
782 if oldBlendState
is not None:
783 stateMgr.setBlendState(oldBlendState)
785 if rasterStateModified
and oldRasterState
is not None:
786 stateMgr.setRasterizerState(oldRasterState)
788 def __init__(self, obj):
789 omr.MPxDrawOverride.__init__(self, obj, footPrintDrawOverride.draw)
794 self.mCustomBoxDraw =
True
795 self.mCurrentBoundingBox = om.MBoundingBox()
797 def supportedDrawAPIs(self):
799 return omr.MRenderer.kOpenGL | omr.MRenderer.kDirectX11
801 def isBounded(self, objPath, cameraPath):
804 def boundingBox(self, objPath, cameraPath):
805 corner1 = om.MPoint( -0.17, 0.0, -0.7 )
806 corner2 = om.MPoint( 0.17, 0.0, 0.3 )
808 multiplier = self.getMultiplier(objPath)
809 corner1 *= multiplier
810 corner2 *= multiplier
812 self.mCurrentBoundingBox.clear()
813 self.mCurrentBoundingBox.expand( corner1 )
814 self.mCurrentBoundingBox.expand( corner2 )
816 return self.mCurrentBoundingBox
818 def disableInternalBoundingBoxDraw(self):
819 return self.mCustomBoxDraw
821 def prepareForDraw(self, objPath, cameraPath, frameContext, oldData):
824 if not isinstance(data, footPrintData):
825 data = footPrintData()
828 data.fMultiplier = self.getMultiplier(objPath)
829 color = omr.MGeometryUtilities.wireframeColor(objPath)
830 data.fColor = [ color.r, color.g, color.b ]
831 data.fCustomBoxDraw = self.mCustomBoxDraw
834 data.fDrawOV = objPath.getDrawOverrideInfo()
838 def hasUIDrawables(self):
841 def addUIDrawables(self, objPath, drawManager, frameContext, data):
843 pos = om.MPoint( 0.0, 0.0, 0.0 )
844 textColor = om.MColor( (0.1, 0.8, 0.8, 1.0) )
846 drawManager.beginDrawable()
848 drawManager.setColor( textColor )
849 drawManager.setFontSize( omr.MUIDrawManager.kSmallFontSize )
850 drawManager.text(pos,
"Footprint", omr.MUIDrawManager.kCenter )
852 drawManager.endDrawable()
854 def getMultiplier(self, objPath):
856 footprintNode = objPath.node()
857 plug = om.MPlug(footprintNode, footPrint.size)
859 sizeVal = plug.asMDistance()
860 return sizeVal.asCentimeters()
864 def initializePlugin(obj):
865 plugin = om.MFnPlugin(obj,
"Autodesk",
"3.0",
"Any")
868 plugin.registerNode(
"footPrint", footPrint.id, footPrint.creator, footPrint.initialize, om.MPxNode.kLocatorNode, footPrint.drawDbClassification)
870 sys.stderr.write(
"Failed to register node\n")
874 omr.MDrawRegistry.registerDrawOverrideCreator(footPrint.drawDbClassification, footPrint.drawRegistrantId, footPrintDrawOverride.creator)
876 sys.stderr.write(
"Failed to register override\n")
879 def uninitializePlugin(obj):
880 plugin = om.MFnPlugin(obj)
883 plugin.deregisterNode(footPrint.id)
885 sys.stderr.write(
"Failed to deregister node\n")
889 omr.MDrawRegistry.deregisterDrawOverrideCreator(footPrint.drawDbClassification, footPrint.drawRegistrantId)
891 sys.stderr.write(
"Failed to deregister override\n")