Python API 2.0 Reference
python/api2/py2PointOnMeshInfo.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
6 # license agreement provided at the time of installation or download,
7 # or which otherwise accompanies this software in either electronic
8 # or hard copy form.
9 # ==========================================================================
10 #
11 
12 from builtins import range
13 import sys
14 import maya.api.OpenMaya as om
15 
16 def maya_useNewAPI():
17  """
18  The presence of this function tells Maya that the plugin produces, and
19  expects to be passed, objects created using the Maya Python API 2.0.
20  """
21  pass
22 
23 # FUNCTION THAT FINDS THE POINT AND NORMAL OF A POLY AT A SPECIFIED FACE UV COORD ABOUT A SPECIFIED FACE:
24 def getPointAndNormal(meshDagPath, faceIndex, relative, parameterU, parameterV, point, normal, theMesh):
25  polyObj = meshDagPath
26  if not theMesh.isNull():
27  polyObj = theMesh
28  # CREATE FACE ITERATOR, AND SET ITS INDEX TO THAT OF THE SPECIFIED FACE:
29  faceIter = om.MItMeshPolygon(polyObj)
30  faceIter.setIndex(faceIndex)
31 
32  # WHEN "RELATIVE" MODE IS SPECIFIED, CALCULATE THE *ABSOLUTE* UV'S FROM THE SPECIFIED FACE AND "RELATIVE" UV'S:
33  # OTHERWISE, JUST TAKE THE ABSOLUTE UV'S TO BE THE ONES SPECIFIED:
34  u = parameterU
35  v = parameterV
36  if relative:
37  uvs = faceIter.getUVs()
38  uArray = uvs[0]
39  vArray = uvs[1]
40  minU=999999
41  minV=999999
42  maxU=0
43  maxV=0
44  for i in range(len(uArray)):
45  if uArray[i] < minU:
46  minU = uArray[i]
47  if vArray[i] < minV:
48  minV = vArray[i]
49  if uArray[i] > maxU:
50  maxU = uArray[i]
51  if vArray[i] > maxV:
52  maxV = vArray[i]
53 
54  u = minU + parameterU * (maxU - minU)
55  v = minV + parameterV * (maxV - minV)
56 
57  # FIND THE WORLDSPACE COORDINATE AT THE SPECIFIED UV:
58  UV = [u, v]
59  try:
60  newPoint = faceIter.getPointAtUV(UV, om.MSpace.kWorld)
61  point.x = newPoint.x
62  point.y = newPoint.y
63  point.z = newPoint.z
64  point.w = newPoint.w
65  except:
66  pass
67 
68  # FIND THE NORMAL AT THE SPECIFIED UV:
69  meshFn = om.MFnMesh(meshDagPath)
70  if not theMesh.isNull():
71  meshFn.setObject(theMesh)
72  newNormal = meshFn.getClosestNormal(point, om.MSpace.kWorld)
73  normal.x = newNormal[0].x
74  normal.y = newNormal[0].y
75  normal.z = newNormal[0].z
76 
77 #
78 # MAIN CLASS DECLARATION FOR THE MEL COMMAND:
79 #
80 class pointOnMeshCommand(om.MPxCommand):
81  nodeCreated = False
82  positionSpecified = False
83  normalSpecified = False
84  faceIndexSpecified = False
85  relativeSpecified = False
86  parameterUSpecified = False
87  parameterVSpecified = False
88  meshNodeName = ""
89  pointOnMeshInfoName = ""
90  faceIndex = -1
91  relative = False
92  parameterU = 0.0
93  parameterV = 0.0
94 
95  def __init__(self):
96  om.MPxCommand.__init__(self)
97 
98  # METHOD FOR CREATING AN INSTANCE OF THIS COMMAND:
99  @staticmethod
100  def cmdCreator():
101  return pointOnMeshCommand()
102 
103  # MAKE THIS COMMAND UNDOABLE:
104  def isUndoable(self):
105  return True
106 
107  # FIRST INVOKED WHEN COMMAND IS CALLED, PARSING THE COMMAND ARGUMENTS, INITIALIZING DEFAULT PARAMETERS, THEN CALLING redoIt():
108  def doIt(self, args):
109  # PARSE THE COMMAND'S ARGUMENTS:
110  for i in range(len(args)):
111  if ("-name" == args.asString(i)) or ("-na" == args.asString(i)):
112  i = i+1
113  self.pointOnMeshInfoName = args.asString(i)
114 
115  elif ("-position" == args.asString(i)) or ("-p" == args.asString(i)):
116  self.positionSpecified = True
117 
118  elif ("-normal" == args.asString(i)) or ("-nr" == args.asString(i)):
119  self.normalSpecified = True
120 
121  elif ("-faceIndex" == args.asString(i)) or ("-f" == args.asString(i)):
122  self.faceIndexSpecified = True
123  i = i+1
124  temp = args.asInt(i)
125  if temp < 0:
126  raise ValueError("Invalid faceIndex!")
127  faceIndex = temp
128 
129  elif ("-relative" == args.asString(i)) or ("-r" ==args.asString(i)):
130  self.relativeSpecified = True
131  i = i+1
132  self.relative = args.asBool(i)
133 
134  elif ("-parameterU" == args.asString(i)) or ("-u" == args.asString(i)):
135  self.parameterUSpecified = True
136  i = i+1
137  temp = args.asDouble(i)
138  if temp < 0 or temp > 1:
139  raise ValueError("Invalid parameterU!")
140  self.parameterU = temp
141 
142  elif ("-parameterV" == args.asString(i)) or ("-v" == args.asString(i)):
143  self.parameterVSpecified = True
144  i = i+1
145  temp = args.asDouble(i)
146  if temp < 0 or temp > 1:
147  raise ValueError("Invalid parameterV!")
148  self.parameterV = temp
149 
150  elif i == (len(args)-1):
151  self.meshNodeName = args.asString(i)
152 
153  else:
154  raise ValueError("Invalid flag:" + args.asString(i))
155 
156  # MAKE SURE UNSPECIFIED INPUT PARAMETER FLAGS GET DEFAULT VALUES:
157  if not self.faceIndexSpecified:
158  self.faceIndex = 0
159  if not self.relativeSpecified:
160  self.relative = True
161  if not self.parameterUSpecified:
162  parameterU = 0.5
163  if not self.parameterVSpecified:
164  self.parameterV = 0.5
165 
166  # DO THE WORK:
167  self.redoIt()
168 
169  # DOES MOST OF THE WORK IN COMPUTING THE POSITION, NORMAL, OR CREATING A "pointOnMeshInfo" NODE:
170  def redoIt(self):
171  # WHEN NO MESH IS SPECIFIED IN THE COMMAND, GET THE FIRST SELECTED MESH FROM THE SELECTION LIST:
172  sList = om.MSelectionList()
173  if self.meshNodeName == "":
174  sList = om.MGlobal.getActiveSelectionList()
175  if sList.length() == 0:
176  raise ValueError("No mesh or mesh transform specified!")
177 
178  # OTHERWISE, USE THE NODE NAME SPECIFIED IN THE LAST ARGUMENT OF THE COMMAND:
179  else:
180  sList.add(self.meshNodeName)
181 
182  # RETRIEVE THE FIRST ITEM FROM THE SELECTION LIST:
183  meshDagPath = sList.getDagPath(0)
184 
185  # CREATE AND CONNECT A "pointOnMeshInfo" NODE, OR GET THE POINT AND NORMAL ACCORDING TO
186  # WHETHER THE "-position/-p" AND/OR "-normal/-nr" FLAGS WERE SPECIFIED, AND WHETHER THE MESH
187  # "SHAPE" OR ITS "TRANSFORM" WAS SPECIFIED/SELECTED:
188  point = om.MPoint()
189  normal = om.MVector()
190  # WHEN THE SPECIFIED NODE IS THE MESH "SHAPE":
191  if meshDagPath.node().hasFn(om.MFn.kMesh):
192  # WHEN NEITHER "-position/-p" NOR "-normal/-nr" ARE SPECIFIED, CREATE AND CONNECT A "pointOnMeshInfo" NODE AND RETURN ITS NODE NAME:
193  if not self.positionSpecified and not self.normalSpecified:
194  # CREATE THE NODE:
195  self.nodeCreated = True
196  depNodeFn = om.MFnDependencyNode()
197 
198  if self.pointOnMeshInfoName == "":
199  depNodeFn.create("pointOnMeshInfo")
200  else:
201  depNodeFn.create("pointOnMeshInfo", self.pointOnMeshInfoName)
202  self.pointOnMeshInfoName = depNodeFn.name()
203 
204  # SET THE ".faceIndex" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
205  if self.faceIndexSpecified:
206  faceIndexPlug = depNodeFn.findPlug("faceIndex", True)
207  faceIndexPlug.setValue(self.faceIndex)
208 
209  # SET THE ".relative" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
210  if self.relativeSpecified:
211  relativePlug = depNodeFn.findPlug("relative", True)
212  relativePlug.setValue(self.relative)
213 
214  # SET THE ".parameterU" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
215  if self.parameterUSpecified:
216  parameterUPlug = depNodeFn.findPlug("parameterU", True)
217  parameterUPlug.setValue(self.parameterU)
218 
219  # SET THE ".parameterV" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
220  if self.parameterVSpecified:
221  parameterVPlug = depNodeFn.findPlug("parameterV", True)
222  parameterVPlug.setValue(self.parameterV)
223 
224  # CONNECT THE NODES:
225  inMeshPlug = depNodeFn.findPlug("inMesh", True)
226  depNodeFn.setObject(meshDagPath.node())
227  worldMeshPlug = depNodeFn.findPlug("worldMesh", True)
228  worldMeshPlug = worldMeshPlug.elementByLogicalIndex(0) # ASSUME THE *FIRST* INSTANCE OF THE MESH IS REQUESTED FOR MESH SHAPES.
229 
230  dgModifier = om.MDGModifier()
231  dgModifier.connect(worldMeshPlug, inMeshPlug)
232  dgModifier.doIt()
233 
234  # SET COMMAND RESULT AND RETURN:
235  om.MPxCommand.setResult(self.pointOnMeshInfoName)
236 
237  # OTHERWISE, COMPUTE THE POINT-POSITION AND NORMAL, USING THE *FIRST* INSTANCE'S TRANSFORM:
238  else:
239  getPointAndNormal(meshDagPath, self.faceIndex, self.relative, self.parameterU, self.parameterV, point, normal)
240 
241  # WHEN THE SPECIFIED NODE IS A "TRANSFORM" OF A MESH SHAPE:
242  elif meshDagPath.node().hasFn(om.MFn.kTransform) and meshDagPath.hasFn(om.MFn.kMesh):
243  # WHEN NEITHER "-position/-p" NOR "-normal/-nr" ARE SPECIFIED, CREATE AND CONNECT A "pointOnMeshInfo" NODE AND RETURN ITS NODE NAME:
244  if not self.positionSpecified and not self.normalSpecified:
245  # CREATE THE NODE:
246  self.nodeCreated = True
247  meshDagPath.extendToShape()
248  depNodeFn = om.MFnDependencyNode()
249 
250  if self.pointOnMeshInfoName == "":
251  depNodeFn.create("pointOnMeshInfo")
252  else:
253  depNodeFn.create("pointOnMeshInfo", self.pointOnMeshInfoName)
254  self.pointOnMeshInfoName = depNodeFn.name()
255 
256  # SET THE ".faceIndex" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
257  if self.faceIndexSpecified:
258  faceIndexPlug = depNodeFn.findPlug("faceIndex", True)
259  faceIndexPlug.setValue(self.faceIndex)
260 
261  # SET THE ".relative" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
262  if self.relativeSpecified:
263  relativePlug = depNodeFn.findPlug("relative", True)
264  relativePlug.setValue(self.relative)
265 
266  # SET THE ".parameterU" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
267  if self.parameterUSpecified:
268  parameterUPlug = depNodeFn.findPlug("parameterU", True)
269  parameterUPlug.setValue(self.parameterU)
270 
271  # SET THE ".parameterV" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:
272  if self.parameterVSpecified:
273  parameterVPlug = depNodeFn.findPlug("parameterV", True)
274  parameterVPlug.setValue(self.parameterV)
275 
276  # CONNECT THE NODES:
277  inMeshPlug = depNodeFn.findPlug("inMesh", True)
278  depNodeFn.setObject(meshDagPath.node())
279  worldMeshPlug = depNodeFn.findPlug("worldMesh", True)
280  worldMeshPlug = worldMeshPlug.elementByLogicalIndex(meshDagPath.instanceNumber())
281 
282  dgModifier = om.MDGModifier()
283  dgModifier.connect(worldMeshPlug, inMeshPlug)
284  dgModifier.doIt()
285 
286  # SET COMMAND RESULT AND RETURN:
287  om.MPxCommand.setResult(self.pointOnMeshInfoName)
288 
289  # OTHERWISE, COMPUTE THE POINT-POSITION AND NORMAL:
290  else:
291  getPointAndNormal(meshDagPath, self.faceIndex, self.relative, self.parameterU, self.parameterV, point, normal)
292 
293  # INVALID INPUT WHEN SPECIFIED/SELECTED NODE IS NOT A MESH NOR TRANSFORM:
294  else:
295  raise ValueError("Invalid type! Only a mesh or its transform can be specified!")
296 
297  # SET THE RETURN VALUES OF THE COMMAND'S RESULT TO BE AN ARRAY OF FLOATS OUTPUTTING THE POSITION AND/OR NORMAL:
298  result = om.MDoubleArray()
299  if self.positionSpecified:
300  result.append(point.x)
301  result.append(point.y)
302  result.append(point.z)
303  if self.normalSpecified:
304  result.append(normal.x)
305  result.append(normal.y)
306  result.append(normal.z)
307 
308  om.MPxCommand.setResult(result)
309 
310  # CALLED WHEN USER UNDOES THE COMMAND:
311  def undoIt(self):
312  # MERELY DELETE THE "pointOnMeshInfo" NODE THAT WAS CREATED, IF ONE WAS CREATED:
313  if self.nodeCreated:
314  deleteCmd = "delete " + self.pointOnMeshInfoName
315  om.MGlobal.executeCommand(deleteCmd)
316 
317 #
318 # MAIN CLASS DECLARATION FOR THE CUSTOM NODE:
319 #
320 class pointOnMeshInfoNode(om.MPxNode):
321  id = om.MTypeId(0x00105480)
322  aInMesh = None
323  aFaceIndex = None
324  aRelative = None
325  aParameterU = None
326  aParameterV = None
327  aPosition = None
328  aPositionX = None
329  aPositionY = None
330  aPositionZ = None
331  aNormal = None
332  aNormalX = None
333  aNormalY = None
334  aNormalZ = None
335 
336  aNurbsCurve = None
337 
338  def __init__(self):
339  om.MPxNode.__init__(self)
340 
341  # FOR CREATING AN INSTANCE OF THIS NODE:
342  @staticmethod
343  def cmdCreator():
344  return pointOnMeshInfoNode()
345 
346  # INITIALIZES THE NODE BY CREATING ITS ATTRIBUTES:
347  @staticmethod
348  def initialize():
349  # CREATE AND ADD ".inMesh" ATTRIBUTE:
350  inMeshAttrFn = om.MFnTypedAttribute()
351  pointOnMeshInfoNode.aInMesh = inMeshAttrFn.create("inMesh", "im", om.MFnData.kMesh)
352  inMeshAttrFn.storable = True
353  inMeshAttrFn.keyable = False
354  inMeshAttrFn.readable = True
355  inMeshAttrFn.writable = True
356  inMeshAttrFn.cached = False
357  om.MPxNode.addAttribute(pointOnMeshInfoNode.aInMesh)
358 
359  # CREATE AND ADD ".faceIndex" ATTRIBUTE:
360  faceIndexAttrFn = om.MFnNumericAttribute()
361  pointOnMeshInfoNode.aFaceIndex = faceIndexAttrFn.create("faceIndex", "f", om.MFnNumericData.kLong, 0)
362  faceIndexAttrFn.storable = True
363  faceIndexAttrFn.keyable = True
364  faceIndexAttrFn.readable = True
365  faceIndexAttrFn.writable = True
366  faceIndexAttrFn.setMin(0)
367  om.MPxNode.addAttribute(pointOnMeshInfoNode.aFaceIndex)
368 
369  # CREATE AND ADD ".relative" ATTRIBUTE:
370  relativeAttrFn = om.MFnNumericAttribute()
371  pointOnMeshInfoNode.aRelative = relativeAttrFn.create("relative", "r", om.MFnNumericData.kBoolean, 1)
372  relativeAttrFn.storable = True
373  relativeAttrFn.keyable = True
374  relativeAttrFn.readable = True
375  relativeAttrFn.writable = True
376  om.MPxNode.addAttribute(pointOnMeshInfoNode.aRelative)
377 
378  # CREATE AND ADD ".parameterU" ATTRIBUTE:
379  parameterUAttrFn = om.MFnNumericAttribute()
380  pointOnMeshInfoNode.aParameterU = parameterUAttrFn.create("parameterU", "u", om.MFnNumericData.kDouble, 0.5)
381  parameterUAttrFn.storable = True
382  parameterUAttrFn.keyable = True
383  parameterUAttrFn.readable = True
384  parameterUAttrFn.writable = True
385  om.MPxNode.addAttribute(pointOnMeshInfoNode.aParameterU)
386 
387  # CREATE AND ADD ".parameterV" ATTRIBUTE:
388  parameterVAttrFn = om.MFnNumericAttribute()
389  pointOnMeshInfoNode.aParameterV = parameterVAttrFn.create("parameterV", "v", om.MFnNumericData.kDouble, 0.5)
390  parameterVAttrFn.storable = True
391  parameterVAttrFn.keyable = True
392  parameterVAttrFn.readable = True
393  parameterVAttrFn.writable = True
394  om.MPxNode.addAttribute(pointOnMeshInfoNode.aParameterV)
395 
396  # CREATE AND ADD ".positionX" ATTRIBUTE:
397  pointXAttrFn = om.MFnNumericAttribute()
398  pointOnMeshInfoNode.aPositionX = pointXAttrFn.create("positionX", "px", om.MFnNumericData.kDouble, 0.0)
399  pointXAttrFn.storable = False
400  pointXAttrFn.keyable = False
401  pointXAttrFn.readable = True
402  pointXAttrFn.writable = False
403  om.MPxNode.addAttribute(pointOnMeshInfoNode.aPositionX)
404 
405  # CREATE AND ADD ".positionY" ATTRIBUTE:
406  pointYAttrFn = om.MFnNumericAttribute()
407  pointOnMeshInfoNode.aPositionY = pointYAttrFn.create("positionY", "py", om.MFnNumericData.kDouble, 0.0)
408  pointYAttrFn.storable = False
409  pointYAttrFn.keyable = False
410  pointYAttrFn.readable = True
411  pointYAttrFn.writable = False
412  om.MPxNode.addAttribute(pointOnMeshInfoNode.aPositionY)
413 
414  # CREATE AND ADD ".positionZ" ATTRIBUTE:
415  pointZAttrFn = om.MFnNumericAttribute()
416  pointOnMeshInfoNode.aPositionZ = pointZAttrFn.create("positionZ", "pz", om.MFnNumericData.kDouble, 0.0)
417  pointZAttrFn.storable = False
418  pointZAttrFn.keyable = False
419  pointZAttrFn.readable = True
420  pointZAttrFn.writable = False
421  om.MPxNode.addAttribute(pointOnMeshInfoNode.aPositionZ)
422 
423  # CREATE AND ADD ".position" ATTRIBUTE:
424  pointAttrFn = om.MFnNumericAttribute()
425  pointOnMeshInfoNode.aPosition = pointAttrFn.create("position", "p", pointOnMeshInfoNode.aPositionX, pointOnMeshInfoNode.aPositionY, pointOnMeshInfoNode.aPositionZ)
426  pointAttrFn.storable = False
427  pointAttrFn.keyable = False
428  pointAttrFn.readable = True
429  pointAttrFn.writable = False
430  om.MPxNode.addAttribute(pointOnMeshInfoNode.aPosition)
431 
432  # CREATE AND ADD ".normalX" ATTRIBUTE:
433  normalXAttrFn = om.MFnNumericAttribute()
434  pointOnMeshInfoNode.aNormalX = normalXAttrFn.create("normalX", "nx", om.MFnNumericData.kDouble, 0.0)
435  normalXAttrFn.storable = False
436  normalXAttrFn.keyable = False
437  normalXAttrFn.readable = True
438  normalXAttrFn.writable = False
439  om.MPxNode.addAttribute(pointOnMeshInfoNode.aNormalX)
440 
441  # CREATE AND ADD ".normalY" ATTRIBUTE:
442  normalYAttrFn = om.MFnNumericAttribute()
443  pointOnMeshInfoNode.aNormalY = normalYAttrFn.create("normalY", "ny", om.MFnNumericData.kDouble, 0.0)
444  normalYAttrFn.storable = False
445  normalYAttrFn.keyable = False
446  normalYAttrFn.readable = True
447  normalYAttrFn.writable = False
448  om.MPxNode.addAttribute(pointOnMeshInfoNode.aNormalY)
449 
450  # CREATE AND ADD ".normalZ" ATTRIBUTE:
451  normalZAttrFn = om.MFnNumericAttribute()
452  pointOnMeshInfoNode.aNormalZ = normalZAttrFn.create("normalZ", "nz", om.MFnNumericData.kDouble, 0.0)
453  normalZAttrFn.storable = False
454  normalZAttrFn.keyable = False
455  normalZAttrFn.readable = True
456  normalZAttrFn.writable = False
457  om.MPxNode.addAttribute(pointOnMeshInfoNode.aNormalZ)
458 
459  # CREATE AND ADD ".normal" ATTRIBUTE:
460  normalAttrFn = om.MFnNumericAttribute()
461  pointOnMeshInfoNode.aNormal = normalAttrFn.create("normal", "n", pointOnMeshInfoNode.aNormalX, pointOnMeshInfoNode.aNormalY, pointOnMeshInfoNode.aNormalZ)
462  normalAttrFn.storable = False
463  normalAttrFn.keyable = False
464  normalAttrFn.readable = True
465  normalAttrFn.writable = False
466  om.MPxNode.addAttribute(pointOnMeshInfoNode.aNormal)
467 
468  # DEPENDENCY RELATIONS FOR ".inMesh":
469  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aPosition)
470  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aPositionX)
471  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aPositionY)
472  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aPositionZ)
473  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aNormal)
474  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aNormalX)
475  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aNormalY)
476  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aInMesh, pointOnMeshInfoNode.aNormalZ)
477 
478  # DEPENDENCY RELATIONS FOR ".faceIndex":
479  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aPosition)
480  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aPositionX)
481  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aPositionY)
482  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aPositionZ)
483  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aNormal)
484  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aNormalX)
485  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aNormalY)
486  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aFaceIndex, pointOnMeshInfoNode.aNormalZ)
487 
488  # DEPENDENCY RELATIONS FOR ".relative":
489  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aPosition)
490  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aPositionX)
491  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aPositionY)
492  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aPositionZ)
493  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aNormal)
494  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aNormalX)
495  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aNormalY)
496  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aRelative, pointOnMeshInfoNode.aNormalZ)
497 
498  # DEPENDENCY RELATIONS FOR ".parameterU":
499  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aPosition)
500  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aPositionX)
501  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aPositionY)
502  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aPositionZ)
503  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aNormal)
504  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aNormalX)
505  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aNormalY)
506  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterU, pointOnMeshInfoNode.aNormalZ)
507 
508  # DEPENDENCY RELATIONS FOR ".parameterV":
509  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aPosition)
510  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aPositionX)
511  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aPositionY)
512  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aPositionZ)
513  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aNormal)
514  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aNormalX)
515  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aNormalY)
516  om.MPxNode.attributeAffects(pointOnMeshInfoNode.aParameterV, pointOnMeshInfoNode.aNormalZ)
517 
518  # COMPUTE METHOD'S DEFINITION:
519  def compute(self, plug, data):
520  assert(isinstance(data.context(), om.MDGContext))
521  assert(data.setContext(data.context()) == data)
522 
523  # DO THE COMPUTE ONLY FOR THE *OUTPUT* PLUGS THAT ARE DIRTIED:
524  if plug == pointOnMeshInfoNode.aPosition or plug == pointOnMeshInfoNode.aPositionX or plug == pointOnMeshInfoNode.aPositionY or plug == pointOnMeshInfoNode.aPositionZ or plug == pointOnMeshInfoNode.aNormal or plug == pointOnMeshInfoNode.aNormalX or plug == pointOnMeshInfoNode.aNormalY or plug == pointOnMeshInfoNode.aNormalZ:
525  # READ IN ".inMesh" DATA:
526  inMeshDataHandle = data.inputValue(pointOnMeshInfoNode.aInMesh)
527  inMesh = inMeshDataHandle.asMesh()
528 
529  # READ IN ".faceIndex" DATA:
530  faceIndexDataHandle = data.inputValue(pointOnMeshInfoNode.aFaceIndex)
531  faceIndex = faceIndexDataHandle.asInt()
532 
533  # READ IN ".relative" DATA:
534  relativeDataHandle = data.inputValue(pointOnMeshInfoNode.aRelative)
535  relative = relativeDataHandle.asBool()
536 
537  # READ IN ".parameterU" DATA:
538  parameterUDataHandle = data.inputValue(pointOnMeshInfoNode.aParameterU)
539  parameterU = parameterUDataHandle.asDouble()
540 
541  # READ IN ".parameterV" DATA:
542  parameterVDataHandle = data.inputValue(pointOnMeshInfoNode.aParameterV)
543  parameterV = parameterVDataHandle.asDouble()
544 
545  # GET THE POINT AND NORMAL:
546  point = om.MPoint()
547  normal = om.MVector()
548  dummyDagPath = om.MDagPath()
549  getPointAndNormal(dummyDagPath, faceIndex, relative, parameterU, parameterV, point, normal, inMesh)
550 
551  # WRITE OUT ".position" DATA:
552  pointDataHandle = data.outputValue(pointOnMeshInfoNode.aPosition)
553  pointDataHandle.set3Double(point.x, point.y, point.z)
554  data.setClean(plug)
555 
556  # WRITE OUT ".normal" DATA:
557  normalDataHandle = data.outputValue(pointOnMeshInfoNode.aNormal)
558  normalDataHandle.set3Double(normal.x, normal.y, normal.z)
559  data.setClean(plug)
560 
561  # The plug was successfully computed
562  return self
563 
564  # Let the Maya parent class compute the plug
565  return None
566 
567 # INITIALIZES THE PLUGIN BY REGISTERING THE COMMAND AND NODE:
568 #
569 def initializePlugin(obj):
570  plugin = om.MFnPlugin(obj)
571  try:
572  plugin.registerCommand("py2PointOnMesh", pointOnMeshCommand.cmdCreator)
573  except:
574  sys.stderr.write("Failed to register command\n")
575  raise
576 
577  try:
578  plugin.registerNode("pointOnMeshInfo", pointOnMeshInfoNode.id, pointOnMeshInfoNode.cmdCreator, pointOnMeshInfoNode.initialize)
579  except:
580  sys.stderr.write("Failed to register node\n")
581  raise
582 
583 #
584 # UNINITIALIZES THE PLUGIN BY DEREGISTERING THE COMMAND AND NODE:
585 #
586 def uninitializePlugin(obj):
587  plugin = om.MFnPlugin(obj)
588  try:
589  plugin.deregisterCommand("py2PointOnMesh")
590  except:
591  sys.stderr.write("Failed to deregister command\n")
592  raise
593 
594  try:
595  plugin.deregisterNode(pointOnMeshInfoNode.id)
596  except:
597  sys.stderr.write("Failed to deregister node\n")
598  raise
599