Python API 2.0 Reference
python/api2/py2DrawFootPrintbyRenderUtilities.py
1 from __future__ import division
2 #-
3 # ===========================================================================
4 # Copyright 2015 Autodesk, Inc. All rights reserved.
5 #
6 # Use of this software is subject to the terms of the Autodesk license
7 # agreement provided at the time of installation or download, or which
8 # otherwise accompanies this software in either electronic or hard copy form.
9 # ===========================================================================
10 #+
11 
12 from builtins import object
13 from builtins import range
14 import sys
15 import ctypes
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
20 
21 def maya_useNewAPI():
22  """
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.
25  """
26  pass
27 
28 def matrixAsArray(matrix):
29  array = []
30  for i in range(16):
31  array.append(matrix[i])
32  return array
33 
34 ## Foot Data
35 ##
36 sole = [ [ 0.00, 0.0, -0.70 ],
37  [ 0.04, 0.0, -0.69 ],
38  [ 0.09, 0.0, -0.65 ],
39  [ 0.13, 0.0, -0.61 ],
40  [ 0.16, 0.0, -0.54 ],
41  [ 0.17, 0.0, -0.46 ],
42  [ 0.17, 0.0, -0.35 ],
43  [ 0.16, 0.0, -0.25 ],
44  [ 0.15, 0.0, -0.14 ],
45  [ 0.13, 0.0, 0.00 ],
46  [ 0.00, 0.0, 0.00 ],
47  [ -0.13, 0.0, 0.00 ],
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 ],
58  [ 0.13, 0.0, 0.06 ],
59  [ 0.14, 0.0, 0.15 ],
60  [ 0.14, 0.0, 0.21 ],
61  [ 0.13, 0.0, 0.25 ],
62  [ 0.11, 0.0, 0.28 ],
63  [ 0.09, 0.0, 0.29 ],
64  [ 0.04, 0.0, 0.30 ],
65  [ 0.00, 0.0, 0.30 ],
66  [ -0.04, 0.0, 0.30 ],
67  [ -0.09, 0.0, 0.29 ],
68  [ -0.11, 0.0, 0.28 ],
69  [ -0.13, 0.0, 0.25 ],
70  [ -0.14, 0.0, 0.21 ],
71  [ -0.14, 0.0, 0.15 ],
72  [ -0.13, 0.0, 0.06 ],
73  [ -0.00, 0.0, 0.06 ] ]
74 soleCount = 21
75 heelCount = 17
76 
77 def convertString(str):
78  import sys
79  if sys.version_info.major is 3:
80  return str.encode('utf-8')
81  else:
82  return str
83 
84 #############################################################################
85 ##
86 ## Node implementation with standard viewport draw
87 ##
88 #############################################################################
89 class footPrint(omui.MPxLocatorNode):
90  id = om.MTypeId( 0x0008004b )
91  drawDbClassification = "drawdb/geometry/footPrint_RenderUtilities_py"
92  drawRegistrantId = "FootprintNode_RenderUtilities_py"
93 
94  size = None ## The size of the foot
95 
96  @staticmethod
97  def creator():
98  return footPrint()
99 
100  @staticmethod
101  def initialize():
102  unitFn = om.MFnUnitAttribute()
103 
104  footPrint.size = unitFn.create( "size", "sz", om.MFnUnitAttribute.kDistance )
105  unitFn.default = om.MDistance(1.0)
106 
107  om.MPxNode.addAttribute( footPrint.size )
108 
109  def __init__(self):
110  omui.MPxLocatorNode.__init__(self)
111 
112  def compute(self, plug, data):
113  return None
114 
115  def draw(self, view, path, style, status):
116  ## Get the size
117  ##
118  thisNode = self.thisMObject()
119  plug = om.MPlug( thisNode, footPrint.size )
120  sizeVal = plug.asMDistance()
121  multiplier = sizeVal.asCentimeters()
122 
123  global sole, soleCount
124  global heel, heelCount
125 
126  view.beginGL()
127 
128  ## drawing in VP1 views will be done using V1 Python APIs:
129  import maya.OpenMayaRender as v1omr
130  glRenderer = v1omr.MHardwareRenderer.theRenderer()
131  glFT = glRenderer.glFunctionTable()
132 
133  if ( style == omui.M3dView.kFlatShaded ) or ( style == omui.M3dView.kGouraudShaded ):
134  ## Push the color settings
135  ##
136  glFT.glPushAttrib( v1omr.MGL_CURRENT_BIT )
137 
138  # Show both faces
139  glFT.glDisable( v1omr.MGL_CULL_FACE )
140 
141  if status == omui.M3dView.kActive:
142  view.setDrawColor( 13, omui.M3dView.kActiveColors )
143  else:
144  view.setDrawColor( 13, omui.M3dView.kDormantColors )
145 
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 )
149  glFT.glEnd()
150 
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 )
154  glFT.glEnd()
155 
156  glFT.glPopAttrib()
157 
158  ## Draw the outline of the foot
159  ##
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 )
164 
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 )
168  glFT.glEnd()
169 
170  view.endGL()
171 
172  ## Draw the name of the footPrint
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 )
175 
176  def isBounded(self):
177  return True
178 
179  def boundingBox(self):
180  ## Get the size
181  ##
182  thisNode = self.thisMObject()
183  plug = om.MPlug( thisNode, footPrint.size )
184  sizeVal = plug.asMDistance()
185  multiplier = sizeVal.asCentimeters()
186 
187  corner1 = om.MPoint( -0.17, 0.0, -0.7 )
188  corner2 = om.MPoint( 0.17, 0.0, 0.3 )
189 
190  corner1 *= multiplier
191  corner2 *= multiplier
192 
193  return om.MBoundingBox( corner1, corner2 )
194 
195 #############################################################################
196 ##
197 ## Viewport 2.0 override implementation
198 ##
199 #############################################################################
200 class footPrintData(om.MUserData):
201  def __init__(self):
202  om.MUserData.__init__(self, False) ## don't delete after draw
203 
204  self.fMultiplier = 0.0
205  self.fColor = [0.0, 0.0, 0.0]
206  self.fCustomBoxDraw = False
207  self.fDrawOV = om.MDAGDrawOverrideInfo()
208 
209 ## Helper class declaration for the object drawing
210 class footPrintDrawAgent(object):
211  def __init__(self):
212  self.mShader = None
213 
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
222 
223  def __del__(self):
224  if self.mShader is not None:
225  shaderMgr = omr.MRenderer.getShaderManager()
226  if shaderMgr is not None:
227  shaderMgr.releaseShader(self.mShader)
228  self.mShader = None
229 
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
238 
239  def beginDraw(self, context, color, scale):
240  self.initShader()
241  self.initBuffers()
242 
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)
248 
249  def drawShaded(self, context):
250  global soleCount, heelCount
251 
252  ## Draw the sole
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))
255 
256  ## Draw the heel
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))
259 
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)
263 
264  def drawWireframe(self, context):
265  global soleCount, heelCount
266 
267  ## Draw the sole
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))
270 
271  ## Draw the heel
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))
274 
275  def endDraw(self, context):
276  if self.mShader is not None:
277  self.mShader.unbind(context)
278 
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), "")
285 
286  return self.mShader is not None
287 
288  def getShaderCode(self):
289  return convertString("")
290 
291  def initBuffers(self):
292  global soleCount, sole
293  global heelCount, heel
294 
295  if self.mBoundingboxVertexBuffer is None:
296  count = 8
297  rawData = [ [ -0.5, -0.5, -0.5 ],
298  [ 0.5, -0.5, -0.5 ],
299  [ 0.5, -0.5, 0.5 ],
300  [ -0.5, -0.5, 0.5 ],
301  [ -0.5, 0.5, -0.5 ],
302  [ 0.5, 0.5, -0.5 ],
303  [ 0.5, 0.5, 0.5 ],
304  [ -0.5, 0.5, 0.5 ] ]
305 
306  desc = omr.MVertexBufferDescriptor("", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
307  self.mBoundingboxVertexBuffer = omr.MVertexBuffer(desc)
308 
309  dataAddress = self.mBoundingboxVertexBuffer.acquire(count, True)
310  data = ((ctypes.c_float * 3)*count).from_address(dataAddress)
311 
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]
316 
317  self.mBoundingboxVertexBuffer.commit(dataAddress)
318  dataAddress = None
319  data = None
320 
321  if self.mBoundingboxIndexBuffer is None:
322  count = 24
323  rawData = [ 0,1,
324  1,2,
325  2,3,
326  3,0,
327  4,5,
328  5,6,
329  6,7,
330  7,4,
331  0,4,
332  1,5,
333  2,6,
334  3,7 ]
335 
336  self.mBoundingboxIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
337 
338  dataAddress = self.mBoundingboxIndexBuffer.acquire(count, True)
339  data = (ctypes.c_uint * count).from_address(dataAddress)
340 
341  for i in range(count):
342  data[i] = rawData[i]
343 
344  self.mBoundingboxIndexBuffer.commit(dataAddress)
345  dataAddress = None
346  data = None
347 
348  if self.mSoleVertexBuffer is None:
349  desc = omr.MVertexBufferDescriptor("", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
350  self.mSoleVertexBuffer = omr.MVertexBuffer(desc)
351 
352  dataAddress = self.mSoleVertexBuffer.acquire(soleCount, True)
353  data = ((ctypes.c_float * 3)*soleCount).from_address(dataAddress)
354 
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]
359 
360  self.mSoleVertexBuffer.commit(dataAddress)
361  dataAddress = None
362  data = None
363 
364  if self.mHeelVertexBuffer is None:
365  desc = omr.MVertexBufferDescriptor("", omr.MGeometry.kPosition, omr.MGeometry.kFloat, 3)
366  self.mHeelVertexBuffer = omr.MVertexBuffer(desc)
367 
368  dataAddress = self.mHeelVertexBuffer.acquire(heelCount, True)
369  data = ((ctypes.c_float * 3)*heelCount).from_address(dataAddress)
370 
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]
375 
376  self.mHeelVertexBuffer.commit(dataAddress)
377  dataAddress = None
378  data = None
379 
380  if self.mSoleWireIndexBuffer is None:
381  count = 2 * (soleCount-1)
382  rawData = [ 0, 1,
383  1, 2,
384  2, 3,
385  3, 4,
386  4, 5,
387  5, 6,
388  6, 7,
389  7, 8,
390  8, 9,
391  9, 10,
392  10, 11,
393  11, 12,
394  12, 13,
395  13, 14,
396  14, 15,
397  15, 16,
398  16, 17,
399  17, 18,
400  18, 19,
401  19, 20 ]
402 
403  self.mSoleWireIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
404 
405  dataAddress = self.mSoleWireIndexBuffer.acquire(count, True)
406  data = (ctypes.c_uint * count).from_address(dataAddress)
407 
408  for i in range(count):
409  data[i] = rawData[i]
410 
411  self.mSoleWireIndexBuffer.commit(dataAddress)
412  dataAddress = None
413  data = None
414 
415  if self.mHeelWireIndexBuffer is None:
416  count = 2 * (heelCount-1)
417  rawData = [ 0, 1,
418  1, 2,
419  2, 3,
420  3, 4,
421  4, 5,
422  5, 6,
423  6, 7,
424  7, 8,
425  8, 9,
426  9, 10,
427  10, 11,
428  11, 12,
429  12, 13,
430  13, 14,
431  14, 15,
432  15, 16 ]
433 
434  self.mHeelWireIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
435 
436  dataAddress = self.mHeelWireIndexBuffer.acquire(count, True)
437  data = (ctypes.c_uint * count).from_address(dataAddress)
438 
439  for i in range(count):
440  data[i] = rawData[i]
441 
442  self.mHeelWireIndexBuffer.commit(dataAddress)
443  dataAddress = None
444  data = None
445 
446  if self.mSoleShadedIndexBuffer is None:
447  count = 3 * (soleCount-2)
448  rawData = [ 0, 1, 2,
449  0, 2, 3,
450  0, 3, 4,
451  0, 4, 5,
452  0, 5, 6,
453  0, 6, 7,
454  0, 7, 8,
455  0, 8, 9,
456  0, 9, 10,
457  0, 10, 11,
458  0, 11, 12,
459  0, 12, 13,
460  0, 13, 14,
461  0, 14, 15,
462  0, 15, 16,
463  0, 16, 17,
464  0, 17, 18,
465  0, 18, 19,
466  0, 19, 20 ]
467 
468  self.mSoleShadedIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
469 
470  dataAddress = self.mSoleShadedIndexBuffer.acquire(count, True)
471  data = (ctypes.c_uint * count).from_address(dataAddress)
472 
473  for i in range(count):
474  data[i] = rawData[i]
475 
476  self.mSoleShadedIndexBuffer.commit(dataAddress)
477  dataAddress = None
478  data = None
479 
480  if self.mHeelShadedIndexBuffer is None:
481  count = 3 * (heelCount-2)
482  rawData = [ 0, 1, 2,
483  0, 2, 3,
484  0, 3, 4,
485  0, 4, 5,
486  0, 5, 6,
487  0, 6, 7,
488  0, 7, 8,
489  0, 8, 9,
490  0, 9, 10,
491  0, 10, 11,
492  0, 11, 12,
493  0, 12, 13,
494  0, 13, 14,
495  0, 14, 15,
496  0, 15, 16 ]
497 
498  self.mHeelShadedIndexBuffer = omr.MIndexBuffer(omr.MGeometry.kUnsignedInt32)
499 
500  dataAddress = self.mHeelShadedIndexBuffer.acquire(count, True)
501  data = (ctypes.c_uint * count).from_address(dataAddress)
502 
503  for i in range(count):
504  data[i] = rawData[i]
505 
506  self.mHeelShadedIndexBuffer.commit(dataAddress)
507  dataAddress = None
508  data = None
509 
510  return True
511 
512 ## GL draw agent declaration
513 class footPrintDrawAgentGL(footPrintDrawAgent):
514  def __init__(self):
515  footPrintDrawAgent.__init__(self)
516 
517  def getShaderCode(self):
518  shaderCode = """
519 float4x4 gWVXf : WorldView;
520 float4x4 gPXf : Projection;
521 float4 matColor = float4(0.8, 0.2, 0.0, 1.0);
522 float scale = 1.0;
523 
524 struct appdata {
525  float3 position : POSITION;
526 };
527 
528 struct vsOutput {
529  float4 position : POSITION;
530 };
531 
532 vsOutput footPrintVS(appdata IN)
533 {
534  float4x4 scaleMat = float4x4(scale, 0, 0, 0,
535  0, scale, 0, 0,
536  0, 0, scale, 0,
537  0, 0, 0, 1);
538  float4x4 transform = mul(gPXf, mul(gWVXf, scaleMat));
539 
540  vsOutput OUT;
541  OUT.position = mul(transform, float4(IN.position, 1));
542  return OUT;
543 }
544 
545 float4 footPrintPS(vsOutput IN) : COLOR
546 {
547  return matColor;
548 }
549 
550 technique Main
551 {
552  pass p0
553  {
554  VertexShader = compile glslv footPrintVS();
555  PixelShader = compile glslf footPrintPS();
556  }
557 }
558 """
559  return convertString(shaderCode)
560 
561 ## DX draw agent declaration
562 class footPrintDrawAgentDX(footPrintDrawAgent):
563  def __init__(self):
564  footPrintDrawAgent.__init__(self)
565 
566  def getShaderCode(self):
567  shaderCode = """
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;
572 
573 struct appdata {
574  float3 position : POSITION;
575 };
576 
577 struct vsOutput {
578  float4 position : SV_Position;
579 };
580 
581 vsOutput footPrintVS(appdata IN)
582 {
583  float4x4 scaleMat = float4x4(scale, 0, 0, 0,
584  0, scale, 0, 0,
585  0, 0, scale, 0,
586  0, 0, 0, 1);
587  float4x4 transform = mul(mul(scaleMat, gWVXf), gPXf);
588 
589  vsOutput OUT;
590  OUT.position = mul(float4(IN.position, 1), transform);
591  return OUT;
592 }
593 
594 float4 footPrintPS(vsOutput IN) : SV_Target
595 {
596  return matColor;
597 }
598 
599 technique10 Main
600 {
601  pass p0
602  {
603  SetVertexShader( CompileShader( vs_5_0, footPrintVS() ));
604  SetGeometryShader( NULL );
605  SetPixelShader( CompileShader( ps_5_0, footPrintPS() ));
606  }
607 }
608 """
609  return convertString(shaderCode)
610 
611 blendState = None
612 rasterState = None
613 drawAgent = None
614 
615 class footPrintDrawOverride(omr.MPxDrawOverride):
616  @staticmethod
617  def creator(obj):
618  return footPrintDrawOverride(obj)
619 
620  @staticmethod
621  def draw(context, data):
622  ## Get user draw data
623  footData = data
624  if not isinstance(footData, footPrintData):
625  return
626 
627  ## Get DAG object draw override
628  objectOverrideInfo = footData.fDrawOV
629 
630  ## Sample code to determine the rendering destination
631  debugDestination = False
632  if debugDestination:
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"
639 
640  print("footprint node render destination is " + destinationType + ". Destination name=" + str(destination[1]))
641 
642  ## Just return and draw nothing, if it is overridden invisible
643  if objectOverrideInfo.overrideEnabled and not objectOverrideInfo.enableVisible:
644  return
645 
646  ## Get display status
647  displayStyle = context.getDisplayStyle()
648  drawAsBoundingbox = (displayStyle & omr.MFrameContext.kBoundingBox) or (objectOverrideInfo.lod == om.MDAGDrawOverrideInfo.kLODBoundingBox)
649  ## If we don't want to draw the bounds within this plugin
650  ## manually, then skip drawing altogether in bounding box mode
651  ## since the bounds draw is handled by the renderer and
652  ## doesn't need to be drawn here.
653  ##
654  if drawAsBoundingbox and not footData.fCustomBoxDraw:
655  return
656 
657  animPlay = oma.MAnimControl.isPlaying()
658  animScrub = oma.MAnimControl.isScrubbing()
659  ## If in playback but hidden in playback, skip drawing
660  if (animPlay or animScrub) and not objectOverrideInfo.playbackVisible:
661  return
662 
663  ## For any viewport interactions switch to bounding box mode,
664  ## except when we are in playback.
665  if context.inUserInteraction() or context.userChangingViewContext():
666  if not animPlay and not animScrub:
667  drawAsBoundingbox = True
668 
669  ## Now, something gonna draw...
670 
671  ## Check to see if we are drawing in a shadow pass.
672  ## If so then we keep the shading simple which in this
673  ## example means to disable any extra blending state changes
674  ##
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
681 
682  debugPassInformation = False
683  if debugPassInformation:
684  passId = passCtx.passIdentifier()
685  print("footprint node drawing in pass[" + str(passId) + "], semantic[" + str(passSemantics) + "]")
686 
687  ## get cached data
688  multiplier = footData.fMultiplier
689  color = [ footData.fColor[0], footData.fColor[1], footData.fColor[2], 1.0 ]
690 
691  requireBlending = False
692 
693  ## If we're not casting shadows then do extra work
694  ## for display styles
695  if not castingShadows:
696  ## Use some monotone version of color to show "default material mode"
697  ##
698  if displayStyle & omr.MFrameContext.kDefaultMaterial:
699  color[0] = color[1] = color[2] = (color[0] + color[1] + color[2]) / 3.0
700 
701  ## Do some alpha blending if in x-ray mode
702  ##
703  elif displayStyle & omr.MFrameContext.kXray:
704  requireBlending = True
705  color[3] = 0.3
706 
707  ## Set blend and raster state
708  ##
709  stateMgr = context.getStateManager()
710  oldBlendState = None
711  oldRasterState = None
712  rasterStateModified = False
713 
714  if stateMgr is not None and (displayStyle & omr.MFrameContext.kGouraudShaded):
715  ## draw filled, and with blending if required
716  if requireBlending:
717  global blendState
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)
724 
725  if blendState is not None:
726  oldBlendState = stateMgr.getBlendState()
727  stateMgr.setBlendState(blendState)
728 
729  ## Override culling mode since we always want double-sided
730  ##
731  oldRasterState = stateMgr.getRasterizerState()
732  if oldRasterState:
733  desc = oldRasterState.desc()
734  ## It's also possible to change this to kCullFront or kCullBack if we
735  ## wanted to set it to that.
736  cullMode = omr.MRasterizerState.kCullNone
737  if desc.cullMode != cullMode:
738  global rasterState
739  if rasterState is None:
740  ## Just override the cullmode
741  desc.cullMode = cullMode
742  rasterState = stateMgr.acquireRasterizerState(desc)
743 
744  if rasterState is not None:
745  rasterStateModified = True
746  stateMgr.setRasterizerState(rasterState)
747 
748  ##========================
749  ## Start the draw work
750  ##========================
751 
752  ## Prepare draw agent, default using OpenGL
753  global drawAgent
754  if drawAgent is None:
755  if omr.MRenderer.drawAPIIsOpenGL():
756  drawAgent = footPrintDrawAgentGL()
757  else:
758  drawAgent = footPrintDrawAgentDX()
759 
760  if not drawAgent is None:
761 
762  drawAgent.beginDraw( context, color, multiplier )
763 
764  if drawAsBoundingbox:
765  drawAgent.drawBoundingBox( context )
766 
767  else:
768  ## Templated, only draw wirefame and it is not selectale
769  overideTemplated = objectOverrideInfo.overrideEnabled and objectOverrideInfo.displayType == om.MDAGDrawOverrideInfo.kDisplayTypeTemplate
770  ## Override no shaded, only show wireframe
771  overrideNoShaded = objectOverrideInfo.overrideEnabled and not objectOverrideInfo.enableShading
772 
773  if overideTemplated or overrideNoShaded:
774  drawAgent.drawWireframe( context )
775 
776  else:
777  if (displayStyle & omr.MFrameContext.kGouraudShaded) or (displayStyle & omr.MFrameContext.kTextured):
778  drawAgent.drawShaded( context )
779 
780  if (displayStyle & omr.MFrameContext.kWireFrame):
781  drawAgent.drawWireframe( context )
782 
783  drawAgent.endDraw( context )
784 
785  ##========================
786  ## End the draw work
787  ##========================
788 
789  ## Restore old blend state and old raster state
790  if stateMgr is not None and (displayStyle & omr.MFrameContext.kGouraudShaded):
791  if oldBlendState is not None:
792  stateMgr.setBlendState(oldBlendState)
793 
794  if rasterStateModified and oldRasterState is not None:
795  stateMgr.setRasterizerState(oldRasterState)
796 
797  def __init__(self, obj):
798  omr.MPxDrawOverride.__init__(self, obj, footPrintDrawOverride.draw)
799 
800  ## We want to perform custom bounding box drawing
801  ## so return True so that the internal rendering code
802  ## will not draw it for us.
803  self.mCustomBoxDraw = True
804  self.mCurrentBoundingBox = om.MBoundingBox()
805 
806  def supportedDrawAPIs(self):
807  ## this plugin supports both GL and DX
808  return omr.MRenderer.kOpenGL | omr.MRenderer.kDirectX11
809 
810  def isBounded(self, objPath, cameraPath):
811  return True
812 
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 )
816 
817  multiplier = self.getMultiplier(objPath)
818  corner1 *= multiplier
819  corner2 *= multiplier
820 
821  self.mCurrentBoundingBox.clear()
822  self.mCurrentBoundingBox.expand( corner1 )
823  self.mCurrentBoundingBox.expand( corner2 )
824 
825  return self.mCurrentBoundingBox
826 
827  def disableInternalBoundingBoxDraw(self):
828  return self.mCustomBoxDraw
829 
830  def prepareForDraw(self, objPath, cameraPath, frameContext, oldData):
831  ## Retrieve data cache (create if does not exist)
832  data = oldData
833  if not isinstance(data, footPrintData):
834  data = footPrintData()
835 
836  ## compute data and cache it
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
841 
842  ## Get the draw override information
843  data.fDrawOV = objPath.getDrawOverrideInfo()
844 
845  return data
846 
847  def hasUIDrawables(self):
848  return True
849 
850  def addUIDrawables(self, objPath, drawManager, frameContext, data):
851  ## Draw a text "Foot"
852  pos = om.MPoint( 0.0, 0.0, 0.0 ) ## Position of the text
853  textColor = om.MColor( (0.1, 0.8, 0.8, 1.0) ) ## Text color
854 
855  drawManager.beginDrawable()
856 
857  drawManager.setColor( textColor )
858  drawManager.setFontSize( omr.MUIDrawManager.kSmallFontSize )
859  drawManager.text(pos, "Footprint", omr.MUIDrawManager.kCenter )
860 
861  drawManager.endDrawable()
862 
863  def getMultiplier(self, objPath):
864  ## Retrieve value of the size attribute from the node
865  footprintNode = objPath.node()
866  plug = om.MPlug(footprintNode, footPrint.size)
867  if not plug.isNull:
868  sizeVal = plug.asMDistance()
869  return sizeVal.asCentimeters()
870 
871  return 1.0
872 
873 def initializePlugin(obj):
874  plugin = om.MFnPlugin(obj, "Autodesk", "3.0", "Any")
875 
876  try:
877  plugin.registerNode("py2FootPrint", footPrint.id, footPrint.creator, footPrint.initialize, om.MPxNode.kLocatorNode, footPrint.drawDbClassification)
878  except:
879  sys.stderr.write("Failed to register node\n")
880  raise
881 
882  try:
883  omr.MDrawRegistry.registerDrawOverrideCreator(footPrint.drawDbClassification, footPrint.drawRegistrantId, footPrintDrawOverride.creator)
884  except:
885  sys.stderr.write("Failed to register override\n")
886  raise
887 
888 def uninitializePlugin(obj):
889  plugin = om.MFnPlugin(obj)
890 
891  try:
892  plugin.deregisterNode(footPrint.id)
893  except:
894  sys.stderr.write("Failed to deregister node\n")
895  pass
896 
897  try:
898  omr.MDrawRegistry.deregisterDrawOverrideCreator(footPrint.drawDbClassification, footPrint.drawRegistrantId)
899  except:
900  sys.stderr.write("Failed to deregister override\n")
901  pass
902 
903 # =======================================================================
904 # Copyright 2020 Autodesk, Inc. All rights reserved.
905 #
906 # This computer source code and related instructions and comments are the
907 # unpublished confidential and proprietary information of Autodesk, Inc.
908 # and are protected under applicable copyright and trade secret law. They
909 # may not be disclosed to, copied or used by any third party without the
910 # prior written consent of Autodesk, Inc.
911 # =======================================================================