scripted/pyDrawFootPrintbyRenderUtilities.py

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