68 import maya.OpenMaya
as OpenMaya
69 import maya.OpenMayaMPx
as OpenMayaMPx
70 import maya.OpenMayaRender
as OpenMayaRender
71 import maya.OpenMayaUI
as OpenMayaUI
77 kPluginNodeTypeName =
"spBasicShape"
78 spBasicShapeNodeId = OpenMaya.MTypeId(0x87018)
80 glRenderer = OpenMayaRender.MHardwareRenderer.theRenderer()
81 glFT = glRenderer.glFunctionTable()
85 kActiveAffectedColor = 8
100 radius = kDefaultRadius
101 height = kDefaultHeight
102 width = kDefaultWidth
103 shapeType = kDefaultShapeType
110 class basicShape(OpenMayaMPx.MPxSurfaceShape):
112 OpenMayaMPx.MPxSurfaceShape.__init__(self)
115 aShapeType = OpenMaya.MObject()
116 aRadius = OpenMaya.MObject()
117 aHeight = OpenMaya.MObject()
118 aWidth = OpenMaya.MObject()
121 self.__myGeometry = basicGeom()
125 def postConstructor(self):
127 When instances of this node are created internally, the MObject associated
128 with the instance is not created until after the constructor of this class
129 is called. This means that no member functions of MPxSurfaceShape can
130 be called in the constructor.
131 The postConstructor solves this problem. Maya will call this function
132 after the internal object has been created.
133 As a general rule do all of your initialization in the postConstructor.
135 self.setRenderable(
True)
139 def compute(self, plug, dataBlock):
141 Since there are no output attributes this is not necessary but
142 if we wanted to compute an output mesh for rendering it would
143 be done here base on the inputs.
145 return OpenMaya.kUnknownParameter
149 def getInternalValue(self, plug, datahandle):
151 Handle internal attributes.
152 In order to impose limits on our attribute values we
153 mark them internal and use the values in fGeometry intead.
155 if (plug == basicShape.aRadius):
156 datahandle.setDouble(self.__myGeometry.radius)
158 elif (plug == basicShape.aHeight):
159 datahandle.setDouble(self.__myGeometry.height)
161 elif (plug == basicShape.aWidth):
162 datahandle.setDouble(self.__myGeometry.width)
165 return OpenMayaMPx.MPxSurfaceShape.getInternalValue(self, plug, datahandle)
171 def setInternalValue(self, plug, datahandle):
173 Handle internal attributes.
174 In order to impose limits on our attribute values we
175 mark them internal and use the values in fGeometry intead.
180 if (plug == basicShape.aRadius):
181 radius = datahandle.asDouble()
186 self.__myGeometry.radius = radius
188 elif (plug == basicShape.aHeight):
189 val = datahandle.asDouble()
192 self.__myGeometry.height = val
194 elif (plug == basicShape.aWidth):
195 val = datahandle.asDouble()
198 self.__myGeometry.width = val
201 return OpenMayaMPx.MPxSurfaceShape.setInternalValue(self, plug, datahandle)
212 def boundingBox(self):
214 Returns the bounding box for the shape.
215 In this case just use the radius and height attributes
216 to determine the bounding box.
218 result = OpenMaya.MBoundingBox()
220 geom = self.geometry()
223 result.expand(OpenMaya.MPoint(r,r,r))
224 result.expand(OpenMaya.MPoint(-r,-r,-r))
227 result.expand(OpenMaya.MPoint(r,r,r))
228 result.expand(OpenMaya.MPoint(-r,-r,-r))
231 result.expand(OpenMaya.MPoint(r,r,r))
232 result.expand(OpenMaya.MPoint(-r,-r,-r))
239 This function gets the values of all the attributes and
240 assigns them to the fGeometry. Calling MPlug::getValue
241 will ensure that the values are up-to-date.
245 this_object = self.thisMObject()
247 plug = OpenMaya.MPlug(this_object, basicShape.aRadius)
248 self.__myGeometry.radius = plug.asDouble()
250 plug.setAttribute(basicShape.aHeight)
251 self.__myGeometry.height = plug.asDouble()
253 plug.setAttribute(basicShape.aWidth)
254 self.__myGeometry.width = plug.asDouble()
256 plug.setAttribute(basicShape.aShapeType)
257 self.__myGeometry.shapeType = plug.asShort()
259 return self.__myGeometry
263 stream=OpenMaya.MStreamUtils.stdOutStream()
264 OpenMaya.MStreamUtils.writeCharBuffer(stream,msg)
270 class basicShapeUI(OpenMayaMPx.MPxSurfaceShapeUI):
272 __kDrawRectangle, __kDrawCircle, __kDrawTriangle = range(3)
273 __kDrawWireframe, __kDrawWireframeOnShaded, __kDrawSmoothShaded, __kDrawFlatShaded, __kLastToken = range(5)
276 OpenMayaMPx.MPxSurfaceShapeUI.__init__(self)
280 def getDrawRequests(self, info, objectAndActiveOnly, queue):
282 The draw data is used to pass geometry through the
283 draw queue. The data should hold all the information
284 needed to draw the shape.
286 data = OpenMayaUI.MDrawData()
288 request = info.getPrototype(self)
290 shapeNode = self.surfaceShape()
291 geom = shapeNode.geometry()
292 self.getDrawData(geom, data)
293 request.setDrawData(data)
296 if (
not info.objectDisplayStatus(OpenMayaUI.M3dView.kDisplayMeshes)):
300 if (info.displayStyle() == OpenMayaUI.M3dView.kWireFrame):
301 self.getDrawRequestsWireframe(request, info)
304 elif (info.displayStyle() == OpenMayaUI.M3dView.kGouraudShaded):
305 request.setToken(basicShapeUI.__kDrawSmoothShaded)
306 self.getDrawRequestsShaded(request, info, queue, data)
309 elif (info.displayStyle() == OpenMayaUI.M3dView.kFlatShaded):
310 request.setToken(basicShapeUI.__kDrawFlatShaded)
311 self.getDrawRequestsShaded(request, info, queue, data)
317 def draw(self, request, view):
319 From the given draw request, get the draw data and determine
320 which basic to draw and with what values.
323 data = request.drawData()
324 shapeNode = self.surfaceShape()
325 geom = shapeNode.geometry()
326 token = request.token()
330 if ((token == basicShapeUI.__kDrawSmoothShaded)
or
331 (token == basicShapeUI.__kDrawFlatShaded)):
333 material = request.material()
334 material.setMaterial(request.multiPath(), request.isTransparent())
342 drawTexture = material.materialIsTextured()
and not view.usingDefaultMaterial()
346 material.applyTexture(view, data)
348 glFT.glPushAttrib( OpenMayaRender.MGL_ALL_ATTRIB_BITS )
350 if ((token == basicShapeUI.__kDrawSmoothShaded)
or
351 (token == basicShapeUI.__kDrawFlatShaded)):
352 glFT.glEnable(OpenMayaRender.MGL_POLYGON_OFFSET_FILL)
353 glFT.glPolygonMode(OpenMayaRender.MGL_FRONT_AND_BACK, OpenMayaRender.MGL_FILL)
355 glFT.glEnable(OpenMayaRender.MGL_TEXTURE_2D)
357 glFT.glPolygonMode(OpenMayaRender.MGL_FRONT_AND_BACK, OpenMayaRender.MGL_LINE)
360 if (geom.shapeType == basicShapeUI.__kDrawCircle):
362 glFT.glBegin(OpenMayaRender.MGL_POLYGON)
363 for i
in range(0,360):
364 rad = (i*2*math.pi)/360;
365 glFT.glNormal3f(0.0, 0.0, 1.0)
367 glFT.glTexCoord3f(geom.radius*math.cos(0), geom.radius*math.sin(0), 0.0)
368 glFT.glVertex3f(geom.radius*math.cos(0), geom.radius*math.sin(0), 0.0)
370 glFT.glTexCoord3f(geom.radius*math.cos(rad), geom.radius*math.sin(rad), 0.0)
371 glFT.glVertex3f(geom.radius*math.cos(rad), geom.radius*math.sin(rad), 0.0)
374 elif (geom.shapeType == basicShapeUI.__kDrawRectangle):
376 glFT.glBegin(OpenMayaRender.MGL_QUADS)
378 glFT.glTexCoord2f(-1*(geom.width/2), -1*(geom.height/2))
379 glFT.glVertex3f(-1*(geom.width/2), -1*(geom.height/2), 0.0)
380 glFT.glNormal3f(0, 0, 1.0)
382 glFT.glTexCoord2f(-1*(geom.width/2), (geom.height/2))
383 glFT.glVertex3f(-1*(geom.width/2), (geom.height/2), 0.0)
384 glFT.glNormal3f(0, 0, 1.0)
386 glFT.glTexCoord2f((geom.width/2), (geom.height/2))
387 glFT.glVertex3f((geom.width/2), (geom.height/2), 0.0)
388 glFT.glNormal3f(0, 0, 1.0)
390 glFT.glTexCoord2f((geom.width/2), -1*(geom.height/2))
391 glFT.glVertex3f((geom.width/2), -1*(geom.height/2), 0.0)
392 glFT.glNormal3f(0, 0, 1.0)
397 glFT.glBegin(OpenMayaRender.MGL_TRIANGLES)
398 glFT.glTexCoord2f(-1*(geom.width/2), -1*(geom.height/2))
399 glFT.glVertex3f(-1*(geom.width/2), -1*(geom.height/2), 0.0)
400 glFT.glNormal3f(0.0, 0.0, 1.0)
402 glFT.glTexCoord2f(0.0, (geom.height/2))
403 glFT.glVertex3f(0.0, (geom.height/2), 0.0)
404 glFT.glNormal3f(0.0, 0.0, 1.0)
406 glFT.glTexCoord2f((geom.width/2), -1*(geom.height/2))
407 glFT.glVertex3f((geom.width/2), -1*(geom.height/2), 0.0)
408 glFT.glNormal3f(0.0, 0.0, 1.0)
411 if ((token == basicShapeUI.__kDrawSmoothShaded)
or
412 (token == basicShapeUI.__kDrawFlatShaded)):
413 glFT.glDisable(OpenMayaRender.MGL_POLYGON_OFFSET_FILL)
416 glFT.glDisable(OpenMayaRender.MGL_TEXTURE_2D)
423 def select(self, selectInfo, selectionList, worldSpaceSelectPts):
425 Select function. Gets called when the bbox for the object is selected.
426 This function just selects the object without doing any intersection tests.
429 priorityMask = OpenMaya.MSelectionMask(OpenMaya.MSelectionMask.kSelectObjectsMask)
430 item = OpenMaya.MSelectionList()
431 item.add(selectInfo.selectPath())
432 xformedPt = OpenMaya.MPoint()
433 selectInfo.addSelection(item, xformedPt, selectionList,
434 worldSpaceSelectPts, priorityMask,
False)
438 def getDrawRequestsWireframe(self, request, info):
440 request.setToken(basicShapeUI.__kDrawWireframe)
442 displayStatus = info.displayStatus()
443 activeColorTable = OpenMayaUI.M3dView.kActiveColors
444 dormantColorTable = OpenMayaUI.M3dView.kDormantColors
446 if (displayStatus == OpenMayaUI.M3dView.kLead):
447 request.setColor(kLeadColor, activeColorTable)
449 elif (displayStatus == OpenMayaUI.M3dView.kActive):
450 request.setColor(kActiveColor, activeColorTable)
452 elif (displayStatus == OpenMayaUI.M3dView.kActiveAffected):
453 request.setColor(kActiveAffectedColor, activeColorTable)
455 elif (displayStatus == OpenMayaUI.M3dView.kDormant):
456 request.setColor(kDormantColor, dormantColorTable)
458 elif (displayStatus == OpenMayaUI.M3dView.kHilite):
459 request.setColor(kHiliteColor, activeColorTable)
463 def getDrawRequestsShaded(self, request, info, queue, data):
465 path = info.multiPath()
467 material = OpenMayaMPx.MPxSurfaceShapeUI.material(self, path)
468 usingDefaultMat = view.usingDefaultMaterial()
470 material = OpenMayaUI.MMaterial.defaultMaterial()
472 displayStatus = info.displayStatus()
476 material.evaluateMaterial(view, path)
478 print "Couldn't evaluate material"
481 drawTexture =
not usingDefaultMat
482 if (drawTexture
and material.materialIsTextured()):
483 material.evaluateTexture(data)
485 request.setMaterial(material)
493 if ((displayStatus == OpenMayaUI.M3dView.kActive)
or
494 (displayStatus == OpenMayaUI.M3dView.kLead)
or
495 (displayStatus == OpenMayaUI.M3dView.kHilite)):
496 wireRequest = info.getPrototype(self)
497 wireRequest.setDrawData(data)
498 self.getDrawRequestsWireframe(wireRequest, info)
499 wireRequest.setToken(basicShapeUI.__kDrawWireframeOnShaded)
500 wireRequest.setDisplayStyle(OpenMayaUI.M3dView.kWireFrame)
501 queue.add(wireRequest)
506 return OpenMayaMPx.asMPxPtr( basicShape() )
510 return OpenMayaMPx.asMPxPtr( basicShapeUI() )
513 def nodeInitializer():
515 enumAttr = OpenMaya.MFnEnumAttribute()
516 basicShape.aShapeType = enumAttr.create(
"shapeType",
"st", kDefaultShapeType)
517 enumAttr.addField(
"rectangle", 0)
518 enumAttr.addField(
"circle", 1)
519 enumAttr.addField(
"triangle", 2)
520 enumAttr.setHidden(
False)
521 enumAttr.setKeyable(
True)
522 basicShape.addAttribute(basicShape.aShapeType)
526 def setOptions(attr):
527 attr.setHidden(
False)
528 attr.setKeyable(
True)
529 attr.setInternal(
True)
531 numericAttr = OpenMaya.MFnNumericAttribute()
533 basicShape.aRadius = numericAttr.create(
"radius",
"r", OpenMaya.MFnNumericData.kDouble, kDefaultRadius)
534 setOptions(numericAttr)
535 basicShape.addAttribute(basicShape.aRadius)
537 basicShape.aHeight = numericAttr.create("height",
"ht", OpenMaya.MFnNumericData.kDouble, kDefaultHeight)
538 setOptions(numericAttr)
539 basicShape.addAttribute(basicShape.aHeight)
541 basicShape.aWidth = numericAttr.create(
"width2",
"wt2", OpenMaya.MFnNumericData.kDouble, kDefaultWidth)
542 setOptions(numericAttr)
543 basicShape.addAttribute(basicShape.aWidth)
546 def initializePlugin(mobject):
547 mplugin = OpenMayaMPx.MFnPlugin(mobject,
"Autodesk",
"8.5",
"Any")
549 mplugin.registerShape( kPluginNodeTypeName, spBasicShapeNodeId,
550 nodeCreator, nodeInitializer, uiCreator )
552 sys.stderr.write(
"Failed to register node: %s" % kPluginNodeTypeName )
557 def uninitializePlugin(mobject):
558 mplugin = OpenMayaMPx.MFnPlugin(mobject)
560 mplugin.deregisterNode( spBasicShapeNodeId )
562 sys.stderr.write(
"Failed to deregister node: %s" % kPluginNodeTypeName )