Python API 2.0 Reference: scripted/pyDrawFootPrintbyRenderUtilities.py

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