Python API 2.0 Reference
viewRenderOverrideFromFragments/pyGroundReflectionRenderer.py
1 '''
2 //**************************************************************************/
3 // Copyright (c) 2016 Autodesk, Inc.
4 // All rights reserved.
5 //
6 // These coded instructions, statements, and computer programs contain
7 // unpublished proprietary information written by Autodesk, Inc., and are
8 // protected by Federal copyright law. They may not be disclosed to third
9 // parties or copied or duplicated in any form, in whole or in part, without
10 // the prior written consent of Autodesk, Inc.
11 '''
12 
13 import maya.api.OpenMaya as om
14 import maya.api.OpenMayaRender as omr
15 import maya.cmds as cmds
16 
17 # Using the Maya Python API 2.0.
18 def maya_useNewAPI():
19  pass
20 
21 class RenderOverrideOptions(om.MPxNode):
22  kTypeId = om.MTypeId(0x00080043)
23  kTypeName = "RenderOverrideOptions"
24 
25  # Attributes
26 
27  reflectionTint = om.MObject()
28  enableReflections = om.MObject()
29  blurReflections = om.MObject()
30  reflectionRange = om.MObject()
31  saturation = om.MObject()
32 
33  # Selector node output.
34  #out = om.MObject()
35 
36  @staticmethod
37  def creator():
38  return RenderOverrideOptions()
39 
40  @staticmethod
41  def initializer():
42 
43  stringData = om.MFnStringData().create('')
44  attrFn = om.MFnTypedAttribute()
45  numAttrFn = om.MFnNumericAttribute()
46  numericData = om.MFnNumericData()
47 
48  # Add typeFilter attribute
49  RenderOverrideOptions.enableReflections = numAttrFn.create("enableReflections", "ef", om.MFnNumericData.kBoolean)
50  numAttrFn.default = True
51  numAttrFn.storable = True
52  numAttrFn.keyable = True
53  numAttrFn.readable = True
54  numAttrFn.writable = True
55  numAttrFn.hidden = False
56  om.MPxNode.addAttribute(RenderOverrideOptions.enableReflections)
57 
58  # Add typeFilter attribute
59  RenderOverrideOptions.reflectionTint = numAttrFn.createColor("reflectionTint", "rt")
60  numAttrFn.default = (0.3, 0.3, 0.3)
61  numAttrFn.storable = True
62  numAttrFn.keyable = True
63  numAttrFn.readable = True
64  numAttrFn.writable = True
65  numAttrFn.hidden = False
66  om.MPxNode.addAttribute(RenderOverrideOptions.reflectionTint)
67 
68  RenderOverrideOptions.saturation = numAttrFn.create("saturation", "sat", om.MFnNumericData.kFloat)
69  numAttrFn.default = 1.0
70  numAttrFn.storable = True
71  numAttrFn.keyable = True
72  numAttrFn.readable = True
73  numAttrFn.writable = True
74  numAttrFn.hidden = False
75  om.MPxNode.addAttribute(RenderOverrideOptions.saturation)
76 
77  RenderOverrideOptions.blurReflections = numAttrFn.create("blurReflections", "br", om.MFnNumericData.kBoolean)
78  numAttrFn.default = True
79  numAttrFn.storable = True
80  numAttrFn.keyable = True
81  numAttrFn.readable = True
82  numAttrFn.writable = True
83  numAttrFn.hidden = False
84  om.MPxNode.addAttribute(RenderOverrideOptions.blurReflections)
85 
86  RenderOverrideOptions.reflectionRange = numAttrFn.create("reflectionRange", "rr", om.MFnNumericData.k2Float)
87  numAttrFn.default = (0.0, 100.0)
88  numAttrFn.storable = True
89  numAttrFn.keyable = True
90  numAttrFn.readable = True
91  numAttrFn.writable = True
92  numAttrFn.hidden = False
93  om.MPxNode.addAttribute(RenderOverrideOptions.reflectionRange)
94 
95  def __init__(self):
96  super(RenderOverrideOptions, self).__init__()
97 
98  def postConstructor(self):
99 
100  # Add the callback
101  om.MNodeMessage.addAttributeChangedCallback(self.thisMObject(), RenderOverrideOptions.attrChangedCB, self)
102 
103  @staticmethod
104  def attrChangedCB(msg, plg, otherPlug, self):
105  cmds.refresh()
106 
107 def _selectPlug(name):
108  sl = om.MSelectionList()
109  try:
110  sl.add(name)
111  except RuntimeError:
112  # not found
113  return None
114  plg = sl.getPlug(0)
115 
116  if plg.isElement and name.find('[') == -1:
117  # Hack because MSelectionList returns a plug over the first element of
118  # a array of plug when no logical index is given
119  return None
120  return plg
121 
122 def nameToNode(name):
123  """Returns the MObject matching given name or None if not found.
124  Raises RuntimeError if name is ambiguous."""
125  plg = _selectPlug(name + ".message")
126  return plg.node() if plg else None
127 
128 def getFloat4PlugValue(plug):
129  object = plug.asMObject()
130  numDataFn = om.MFnNumericData( object )
131  return numDataFn.getData( )
132 
133 def getFloat3PlugValue(plug):
134  object = plug.asMObject()
135  numDataFn = om.MFnNumericData( object )
136  return numDataFn.getData( )
137 
138 def getFloat2PlugValue(plug):
139  object = plug.asMObject()
140  numDataFn = om.MFnNumericData( object )
141  return numDataFn.getData( )
142 
143 def getBoolPlugValue(plug):
144  return plug.asBool()
145 
146 def getFloatPlugValue(plug):
147  return plug.asFloat()
148 
149 def getIntPlugValue(plug):
150  return plug.asInt()
151 
152 class FragmentSceneRender(omr.MSceneRender):
153  def __init__(self, name):
154  super(FragmentSceneRender, self).__init__(name, "GroundReflections")
155 
156  def preSceneRender(self, context):
157  params = self.getParameters()
158  if params is None:
159  return
160 
161  # Find the options node
162  optionsNodeName = 'groundReflectionOptions'
163  optionObj = nameToNode(optionsNodeName)
164  if optionObj is None:
165  optionObj = nameToNode(cmds.createNode(RenderOverrideOptions.kTypeName, name=optionsNodeName, skipSelect=True))
166 
167  if optionObj is not None:
168  # set the fragment's enabled input
169  optionPlug = om.MPlug(optionObj, RenderOverrideOptions.enableReflections)
170  if optionPlug is not None:
171  enabled = getBoolPlugValue(optionPlug)
172  params.setParameter('EnableReflection', enabled)
173 
174  # set the fragment's blur input
175  optionPlug = om.MPlug(optionObj, RenderOverrideOptions.blurReflections)
176  if optionPlug is not None:
177  blur = getBoolPlugValue(optionPlug)
178  if blur:
179  params.setParameter('BlurType', 3)
180  else:
181  params.setParameter('BlurType', 0)
182 
183  # set the fragment composite color
184  optionPlug = om.MPlug(optionObj, RenderOverrideOptions.reflectionTint)
185  if optionPlug is not None:
186  color = getFloat3PlugValue(optionPlug)
187  params.setParameter('Color', color)
188 
189  # set the fragment saturation
190  optionPlug = om.MPlug(optionObj, RenderOverrideOptions.saturation)
191  if optionPlug is not None:
192  val = getFloatPlugValue(optionPlug)
193  params.setParameter('Saturation', val)
194 
195  # set the reflection range
196  optionPlug = om.MPlug(optionObj, RenderOverrideOptions.reflectionRange)
197  if optionPlug is not None:
198  val = getFloat2PlugValue(optionPlug)
199  params.setParameter('DistanceRange', val)
200 
201 class FragmentRenderOverride(omr.MRenderOverride):
202 
203  def __init__(self, name):
204  self.operatioIndex = 0
205  self.operations = [FragmentSceneRender("sceneAndGroundReflections"),
206  omr.MHUDRender(),
207  omr.MPresentTarget("present")]
208 
209  # set the clear op to use the settings from Maya and disable the clear op embeded in the scene render.
210  self.operations[0].clearOperation().setOverridesColors(False)
211 
212  super(FragmentRenderOverride, self).__init__(name)
213 
214  def uiName(self):
215  return 'Ground Reflections'
216 
217  def setup(self, destination):
218  super(FragmentRenderOverride, self).setup(destination)
219 
220  def cleanup(self):
221  super(FragmentRenderOverride, self).cleanup()
222 
223  def supportedDrawAPIs(self):
224  return omr.MRenderer.kAllDevices
225 
226  def startOperationIterator(self):
227  self.operationIndex = 0
228  return True
229 
230  def renderOperation(self):
231  return self.operations[self.operationIndex]
232 
233  def nextRenderOperation(self):
234  self.operationIndex += 1
235  return self.operationIndex < len(self.operations)
236 
237 # global instance of this override.
238 fragmentRenderer = None
239 
240 def initializePlugin(mobject):
241  # NOTICE: Please set the path to the plugin before running
242  pathToPlugin = './'
243 
244  omr.MRenderer.getShaderManager().addShaderPath(pathToPlugin + "Shaders/OGSFX")
245  omr.MRenderer.getShaderManager().addShaderPath(pathToPlugin + "Shaders/HLSL")
246  omr.MRenderer.getShaderManager().addShaderPath(pathToPlugin + "Shaders/Cg")
247 
248  omr.MRenderer.getFragmentManager().addFragmentPath(pathToPlugin + "ScriptFragment")
249  omr.MRenderer.getFragmentManager().addFragmentGraphFromFile("GroundReflections.xml")
250 
251  plugin = om.MFnPlugin(mobject, "Autodesk", "3.0", "Any")
252  plugin.registerNode(RenderOverrideOptions.kTypeName, RenderOverrideOptions.kTypeId, RenderOverrideOptions.creator, RenderOverrideOptions.initializer)
253 
254  global fragmentRenderer
255  fragmentRenderer = FragmentRenderOverride('GroundReflectionsOverride')
256  omr.MRenderer.registerOverride(fragmentRenderer)
257 
258 def uninitializePlugin(mobject):
259  global fragmentRenderer
260  plugin = om.MFnPlugin(mobject)
261  try:
262  plugin.deregisterNode(apiMeshCreator.id)
263  omr.MRenderer.unregisterOverride(fragmentRenderer)
264  fragmentRenderer = None
265  except:
266  sys.stderr.write("Failed to deregister node\n")
267  pass
268 
269 
270