scripted/customImagePlane.py

scripted/customImagePlane.py
1 #-
2 # ==========================================================================
3 # Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All
4 # rights reserved.
5 #
6 # The coded instructions, statements, computer programs, and/or related
7 # material (collectively the "Data") in these files contain unpublished
8 # information proprietary to Autodesk, Inc. ("Autodesk") and/or its
9 # licensors, which is protected by U.S. and Canadian federal copyright
10 # law and by international treaties.
11 #
12 # The Data is provided for use exclusively by You. You have the right
13 # to use, modify, and incorporate this Data into other products for
14 # purposes authorized by the Autodesk software license agreement,
15 # without fee.
16 #
17 # The copyright notices in the Software and this entire statement,
18 # including the above license grant, this restriction and the
19 # following disclaimer, must be included in all copies of the
20 # Software, in whole or in part, and all derivative works of
21 # the Software, unless such copies or derivative works are solely
22 # in the form of machine-executable object code generated by a
23 # source language processor.
24 #
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
26 # AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
27 # WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
28 # NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
29 # PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR
30 # TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS
31 # BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
32 # DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK
33 # AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY
34 # OR PROBABILITY OF SUCH DAMAGES.
35 #
36 # ==========================================================================
37 #+
38 
39 #
40 # Description:
41 # Demonstrates how to create your own custom image plane based on
42 # Maya's internal image plane classes. This allows API users to
43 # override the default Maya image plane behavior. This class works
44 # like typical API nodes in that it can have a compute method and
45 # can contain static attributes added by the API user. This
46 # example class overrides the default image plane behavior and
47 # allows users to add transparency to an image plane using the
48 # transparency attribute on the node. Note, this code also
49 # illustrates how to use MImage to control the floating point
50 # depth buffer. When useDepthMap is set to true, depth is added
51 # is added to the image such that half of the iamge is at the near
52 # clip plane and the remaining half is at the far clip plane.
53 #
54 # Note, once the image plane node has been created it you must
55 # attached it to the camera shape that is displaying the node.
56 # Image planes are attached to cameras via the imagePlane message
57 # attribute on the camera shape. To attach this example image
58 # plane you should connect the image plane's message attribute to
59 # the cameraShapes imagePlane attribute. Note, the imagePlane
60 # attribute is a multi attribute and can hold references to
61 # multiple image planes.
62 #
63 # This example works only with renderers that use node evaluation
64 # as a part of the rendering process, e.g. Maya Software. It does
65 # not work with renderes that rely on a scene translation mechanism,
66 # e.g. mental ray.
67 #
68 # Usage:
69 #
70 # Run the script:
71 #
72 # import maya
73 # maya.cmds.loadPlugin("customImagePlane.py")
74 # imageP = maya.cmds.createNode("spCustomImagePlane")
75 # maya.cmds.connectAttr( imageP + ".message", "perspShape.imagePlane[0]", force = True )
76 #
77 # Then assign an image to the customImagePlane node
78 #
79 
80 import maya.OpenMaya as OpenMaya
81 import maya.OpenMayaMPx as OpenMayaMPx
82 import sys
83 
84 kPluginNodeTypeName = "spCustomImagePlane"
85 kPluginNodeId = OpenMaya.MTypeId(0x87016)
86 
87 # Node definition
88 class customImagePlane(OpenMayaMPx.MPxImagePlane):
89  # class variables
90  aTransparency = OpenMaya.MObject()
91 
92  # internal variables
93  fTransparency = 0.0
94 
95  def __init__(self):
96  OpenMayaMPx.MPxImagePlane.__init__(self)
97 
98  def getInternalValueInContext( self, plug, handle, context ):
99  if plug == self.aTransparency:
100  handle.setDouble( self.fTransparency )
101  return True
102 
103  return OpenMayaMPx.MPxImagePlane.getInternalValueInContext( self, plug, handle, context )
104 
105  def setInternalValueInContext( self, plug, handle, context ):
106  if plug == self.aTransparency:
107  self.fTransparency = handle.asDouble()
108  self.setImageDirty()
109  return True
110 
111  return OpenMayaMPx.MPxImagePlane.setInternalValueInContext( self, plug, handle, context )
112 
113  def loadImageMap(self, fileName, frame, image):
114  try:
115  image.readFromFile(fileName)
116 
117  # get the width and height of the image an MScriptUtil is needed
118  # to pass in a pointer to the MImage::getSize() method
119  widthUtil = OpenMaya.MScriptUtil(0)
120  widthPtr = widthUtil.asUintPtr()
121  heightUtil = OpenMaya.MScriptUtil(0)
122  heightPtr = heightUtil.asUintPtr()
123  image.getSize( widthPtr, heightPtr )
124 
125  width = widthUtil.getUint(widthPtr)
126  height = heightUtil.getUint(heightPtr)
127  size = width * height
128 
129  # Implement transparency
130  charPixelPtr = image.pixels()
131  for i in range( 0, size, 4 ):
132  alphaIndex = (i*4)+3
133  alpha = OpenMayaScript.getCharArrayItem(charPixelPtr,alphaIndex)
134  OpenMayaScript.setCharArray( alpha * (1.0 - self.fTransparency), alphaIndex )
135 
136  # Implement use depth map
137  thisNode = self.thisMObject()
138  fnThisNode = OpenMaya.MFnDependencyNode(thisNode)
139  useDepthMap = fnThisNode.attribute("useDepthMap")
140  depthMap = OpenMaya.MPlug( thisNode, useDepthMap )
141  value = depthMap.asBool()
142 
143  if value:
144  buffer = []
145  c = 0
146  for i in range( 0, height ):
147  for j in range( 0, width ):
148  if i > height/2.0:
149  buffer.insert(c, -1.0)
150  else:
151  buffer.insert(c, 0.0)
152  c+=1
153 
154  depthMapArray = OpenMaya.MScriptUtil()
155  depthMapArray.createFromList( buffer )
156  depthMapArrayFloatPtr = depthMapArray.asFloatPtr()
157  image.setDepthMap( depthMapArrayFloatPtr, width, height )
158 
159  except:
160  pass
161 
162 # creator
163 def nodeCreator():
164  return OpenMayaMPx.asMPxPtr( customImagePlane() )
165 
166 # initializer
167 def nodeInitializer():
168  nAttr = OpenMaya.MFnNumericAttribute()
169 
170  # Setup the input attributes
171  customImagePlane.aTransparency = nAttr.create("transparency", "tp", OpenMaya.MFnNumericData.kDouble, 0.0)
172  nAttr.setStorable(True)
173  nAttr.setInternal(True)
174  nAttr.setMin(0.0)
175  nAttr.setMax(1.0)
176  nAttr.setKeyable(True)
177 
178  customImagePlane.addAttribute(customImagePlane.aTransparency)
179 
180 # initialize the script plug-in
181 def initializePlugin(mobject):
182  mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")
183  try:
184  mplugin.registerNode( kPluginNodeTypeName, kPluginNodeId, nodeCreator, nodeInitializer, OpenMayaMPx.MPxNode.kImagePlaneNode )
185  except:
186  sys.stderr.write( "Failed to register node: %s" % kPluginNodeTypeName )
187  raise
188 
189 
190 # uninitialize the script plug-in
191 def uninitializePlugin(mobject):
192  mplugin = OpenMayaMPx.MFnPlugin(mobject)
193  try:
194  mplugin.deregisterNode( kPluginNodeId )
195  except:
196  sys.stderr.write( "Failed to register node: %s" % kPluginNodeTypeName )
197  raise