1 from __future__
import division
67 from builtins
import object
68 from builtins
import range
69 import maya.OpenMaya
as OpenMaya
70 import maya.OpenMayaMPx
as OpenMayaMPx
71 import maya.OpenMayaRender
as OpenMayaRender
72 import maya.OpenMayaUI
as OpenMayaUI
78 kPluginNodeTypeName =
"spBasicShape"
81 glRenderer = OpenMayaRender.MHardwareRenderer.theRenderer()
82 glFT = glRenderer.glFunctionTable()
86 kActiveAffectedColor = 8
100 class basicGeom(object):
101 radius = kDefaultRadius
102 height = kDefaultHeight
103 width = kDefaultWidth
104 shapeType = kDefaultShapeType
111 class basicShape(OpenMayaMPx.MPxSurfaceShape):
113 OpenMayaMPx.MPxSurfaceShape.__init__(self)
122 self.__myGeometry = basicGeom()
126 def postConstructor(self):
128 When instances of this node are created internally, the MObject associated
129 with the instance is not created until after the constructor of this class
130 is called. This means that no member functions of MPxSurfaceShape can
131 be called in the constructor.
132 The postConstructor solves this problem. Maya will call this function
133 after the internal object has been created.
134 As a general rule do all of your initialization in the postConstructor.
136 self.setRenderable(
True)
140 def compute(self, plug, dataBlock):
142 Since there are no output attributes this is not necessary but
143 if we wanted to compute an output mesh for rendering it would
144 be done here base on the inputs.
146 return OpenMaya.kUnknownParameter
150 def getInternalValue(self, plug, datahandle):
152 Handle internal attributes.
153 In order to impose limits on our attribute values we
154 mark them internal and use the values in fGeometry intead.
156 if (plug == basicShape.aRadius):
157 datahandle.setDouble(self.__myGeometry.radius)
159 elif (plug == basicShape.aHeight):
160 datahandle.setDouble(self.__myGeometry.height)
162 elif (plug == basicShape.aWidth):
163 datahandle.setDouble(self.__myGeometry.width)
166 return OpenMayaMPx.MPxSurfaceShape.getInternalValue(self, plug, datahandle)
172 def setInternalValue(self, plug, datahandle):
174 Handle internal attributes.
175 In order to impose limits on our attribute values we
176 mark them internal and use the values in fGeometry intead.
181 if (plug == basicShape.aRadius):
182 radius = datahandle.asDouble()
187 self.__myGeometry.radius = radius
189 elif (plug == basicShape.aHeight):
190 val = datahandle.asDouble()
193 self.__myGeometry.height = val
195 elif (plug == basicShape.aWidth):
196 val = datahandle.asDouble()
199 self.__myGeometry.width = val
202 return OpenMayaMPx.MPxSurfaceShape.setInternalValue(self, plug, datahandle)
213 def boundingBox(self):
215 Returns the bounding box for the shape.
216 In this case just use the radius and height attributes
217 to determine the bounding box.
221 geom = self.geometry()
240 This function gets the values of all the attributes and
241 assigns them to the fGeometry. Calling MPlug::getValue
242 will ensure that the values are up-to-date.
246 this_object = self.thisMObject()
249 self.__myGeometry.radius = plug.asDouble()
251 plug.setAttribute(basicShape.aHeight)
252 self.__myGeometry.height = plug.asDouble()
254 plug.setAttribute(basicShape.aWidth)
255 self.__myGeometry.width = plug.asDouble()
257 plug.setAttribute(basicShape.aShapeType)
258 self.__myGeometry.shapeType = plug.asShort()
260 return self.__myGeometry
264 stream=OpenMaya.MStreamUtils.stdOutStream()
265 OpenMaya.MStreamUtils.writeCharBuffer(stream,msg)
271 class basicShapeUI(OpenMayaMPx.MPxSurfaceShapeUI):
273 __kDrawRectangle, __kDrawCircle, __kDrawTriangle = list(range(3))
274 __kDrawWireframe, __kDrawWireframeOnShaded, __kDrawSmoothShaded, __kDrawFlatShaded, __kLastToken = list(range(5))
277 OpenMayaMPx.MPxSurfaceShapeUI.__init__(self)
281 def getDrawRequests(self, info, objectAndActiveOnly, queue):
283 The draw data is used to pass geometry through the
284 draw queue. The data should hold all the information
285 needed to draw the shape.
289 request = info.getPrototype(self)
291 shapeNode = self.surfaceShape()
292 geom = shapeNode.geometry()
293 self.getDrawData(geom, data)
294 request.setDrawData(data)
297 if (
not info.objectDisplayStatus(OpenMayaUI.M3dView.kDisplayMeshes)):
301 if (info.displayStyle() == OpenMayaUI.M3dView.kWireFrame):
302 self.getDrawRequestsWireframe(request, info)
305 elif (info.displayStyle() == OpenMayaUI.M3dView.kGouraudShaded):
306 request.setToken(basicShapeUI.__kDrawSmoothShaded)
307 self.getDrawRequestsShaded(request, info, queue, data)
310 elif (info.displayStyle() == OpenMayaUI.M3dView.kFlatShaded):
311 request.setToken(basicShapeUI.__kDrawFlatShaded)
312 self.getDrawRequestsShaded(request, info, queue, data)
318 def draw(self, request, view):
320 From the given draw request, get the draw data and determine
321 which basic to draw and with what values.
324 data = request.drawData()
325 shapeNode = self.surfaceShape()
326 geom = shapeNode.geometry()
327 token = request.token()
331 if ((token == basicShapeUI.__kDrawSmoothShaded)
or
332 (token == basicShapeUI.__kDrawFlatShaded)):
334 material = request.material()
335 material.setMaterial(request.multiPath(), request.isTransparent())
343 drawTexture = material.materialIsTextured()
and not view.usingDefaultMaterial()
347 material.applyTexture(view, data)
349 glFT.glPushAttrib( OpenMayaRender.MGL_ALL_ATTRIB_BITS )
351 if ((token == basicShapeUI.__kDrawSmoothShaded)
or
352 (token == basicShapeUI.__kDrawFlatShaded)):
353 glFT.glEnable(OpenMayaRender.MGL_POLYGON_OFFSET_FILL)
354 glFT.glPolygonMode(OpenMayaRender.MGL_FRONT_AND_BACK, OpenMayaRender.MGL_FILL)
356 glFT.glEnable(OpenMayaRender.MGL_TEXTURE_2D)
358 glFT.glPolygonMode(OpenMayaRender.MGL_FRONT_AND_BACK, OpenMayaRender.MGL_LINE)
361 if (geom.shapeType == basicShapeUI.__kDrawCircle):
363 glFT.glBegin(OpenMayaRender.MGL_POLYGON)
364 for i
in range(0,360):
365 rad = (i*2*math.pi)/360;
366 glFT.glNormal3f(0.0, 0.0, 1.0)
368 glFT.glTexCoord3f(geom.radius*math.cos(0), geom.radius*math.sin(0), 0.0)
369 glFT.glVertex3f(geom.radius*math.cos(0), geom.radius*math.sin(0), 0.0)
371 glFT.glTexCoord3f(geom.radius*math.cos(rad), geom.radius*math.sin(rad), 0.0)
372 glFT.glVertex3f(geom.radius*math.cos(rad), geom.radius*math.sin(rad), 0.0)
375 elif (geom.shapeType == basicShapeUI.__kDrawRectangle):
377 glFT.glBegin(OpenMayaRender.MGL_QUADS)
379 glFT.glTexCoord2f(-1*(geom.width/2), -1*(geom.height/2))
380 glFT.glVertex3f(-1*(geom.width/2), -1*(geom.height/2), 0.0)
381 glFT.glNormal3f(0, 0, 1.0)
383 glFT.glTexCoord2f(-1*(geom.width/2), (geom.height/2))
384 glFT.glVertex3f(-1*(geom.width/2), (geom.height/2), 0.0)
385 glFT.glNormal3f(0, 0, 1.0)
387 glFT.glTexCoord2f((geom.width/2), (geom.height/2))
388 glFT.glVertex3f((geom.width/2), (geom.height/2), 0.0)
389 glFT.glNormal3f(0, 0, 1.0)
391 glFT.glTexCoord2f((geom.width/2), -1*(geom.height/2))
392 glFT.glVertex3f((geom.width/2), -1*(geom.height/2), 0.0)
393 glFT.glNormal3f(0, 0, 1.0)
398 glFT.glBegin(OpenMayaRender.MGL_TRIANGLES)
399 glFT.glTexCoord2f(-1*(geom.width/2), -1*(geom.height/2))
400 glFT.glVertex3f(-1*(geom.width/2), -1*(geom.height/2), 0.0)
401 glFT.glNormal3f(0.0, 0.0, 1.0)
403 glFT.glTexCoord2f(0.0, (geom.height/2))
404 glFT.glVertex3f(0.0, (geom.height/2), 0.0)
405 glFT.glNormal3f(0.0, 0.0, 1.0)
407 glFT.glTexCoord2f((geom.width/2), -1*(geom.height/2))
408 glFT.glVertex3f((geom.width/2), -1*(geom.height/2), 0.0)
409 glFT.glNormal3f(0.0, 0.0, 1.0)
412 if ((token == basicShapeUI.__kDrawSmoothShaded)
or
413 (token == basicShapeUI.__kDrawFlatShaded)):
414 glFT.glDisable(OpenMayaRender.MGL_POLYGON_OFFSET_FILL)
417 glFT.glDisable(OpenMayaRender.MGL_TEXTURE_2D)
424 def select(self, selectInfo, selectionList, worldSpaceSelectPts):
426 Select function. Gets called when the bbox for the object is selected.
427 This function just selects the object without doing any intersection tests.
432 item.add(selectInfo.selectPath())
434 selectInfo.addSelection(item, xformedPt, selectionList,
435 worldSpaceSelectPts, priorityMask,
False)
439 def getDrawRequestsWireframe(self, request, info):
441 request.setToken(basicShapeUI.__kDrawWireframe)
443 displayStatus = info.displayStatus()
444 activeColorTable = OpenMayaUI.M3dView.kActiveColors
445 dormantColorTable = OpenMayaUI.M3dView.kDormantColors
447 if (displayStatus == OpenMayaUI.M3dView.kLead):
448 request.setColor(kLeadColor, activeColorTable)
450 elif (displayStatus == OpenMayaUI.M3dView.kActive):
451 request.setColor(kActiveColor, activeColorTable)
453 elif (displayStatus == OpenMayaUI.M3dView.kActiveAffected):
454 request.setColor(kActiveAffectedColor, activeColorTable)
456 elif (displayStatus == OpenMayaUI.M3dView.kDormant):
457 request.setColor(kDormantColor, dormantColorTable)
459 elif (displayStatus == OpenMayaUI.M3dView.kHilite):
460 request.setColor(kHiliteColor, activeColorTable)
464 def getDrawRequestsShaded(self, request, info, queue, data):
466 path = info.multiPath()
468 material = OpenMayaMPx.MPxSurfaceShapeUI.material(self, path)
469 usingDefaultMat = view.usingDefaultMaterial()
473 displayStatus = info.displayStatus()
477 material.evaluateMaterial(view, path)
479 print(
"Couldn't evaluate material")
482 drawTexture =
not usingDefaultMat
483 if (drawTexture
and material.materialIsTextured()):
484 material.evaluateTexture(data)
486 request.setMaterial(material)
494 if ((displayStatus == OpenMayaUI.M3dView.kActive)
or
495 (displayStatus == OpenMayaUI.M3dView.kLead)
or
496 (displayStatus == OpenMayaUI.M3dView.kHilite)):
497 wireRequest = info.getPrototype(self)
498 wireRequest.setDrawData(data)
499 self.getDrawRequestsWireframe(wireRequest, info)
500 wireRequest.setToken(basicShapeUI.__kDrawWireframeOnShaded)
501 wireRequest.setDisplayStyle(OpenMayaUI.M3dView.kWireFrame)
502 queue.add(wireRequest)
507 return OpenMayaMPx.asMPxPtr( basicShape() )
511 return OpenMayaMPx.asMPxPtr( basicShapeUI() )
514 def nodeInitializer():
517 basicShape.aShapeType = enumAttr.create(
"shapeType",
"st", kDefaultShapeType)
518 enumAttr.addField(
"rectangle", 0)
519 enumAttr.addField(
"circle", 1)
520 enumAttr.addField(
"triangle", 2)
521 enumAttr.setHidden(
False)
522 enumAttr.setKeyable(
True)
523 basicShape.addAttribute(basicShape.aShapeType)
527 def setOptions(attr):
528 attr.setHidden(
False)
529 attr.setKeyable(
True)
530 attr.setInternal(
True)
534 basicShape.aRadius = numericAttr.create(
"radius",
"r", OpenMaya.MFnNumericData.kDouble, kDefaultRadius)
535 setOptions(numericAttr)
536 basicShape.addAttribute(basicShape.aRadius)
538 basicShape.aHeight = numericAttr.create("height",
"ht", OpenMaya.MFnNumericData.kDouble, kDefaultHeight)
539 setOptions(numericAttr)
540 basicShape.addAttribute(basicShape.aHeight)
542 basicShape.aWidth = numericAttr.create(
"width2",
"wt2", OpenMaya.MFnNumericData.kDouble, kDefaultWidth)
543 setOptions(numericAttr)
544 basicShape.addAttribute(basicShape.aWidth)
547 def initializePlugin(mobject):
548 mplugin = OpenMayaMPx.MFnPlugin(mobject,
"Autodesk",
"8.5",
"Any")
550 mplugin.registerShape( kPluginNodeTypeName, spBasicShapeNodeId,
551 nodeCreator, nodeInitializer, uiCreator )
553 sys.stderr.write(
"Failed to register node: %s" % kPluginNodeTypeName )
558 def uninitializePlugin(mobject):
559 mplugin = OpenMayaMPx.MFnPlugin(mobject)
561 mplugin.deregisterNode( spBasicShapeNodeId )
563 sys.stderr.write(
"Failed to deregister node: %s" % kPluginNodeTypeName )