Package mrv :: Package maya
[hide private]
[frames] | no frames]

Source Code for Package mrv.maya

  1  # -*- coding: utf-8 -*- 
  2  """ Inialize the mrv.maya sub-system and startup maya as completely as possible or configured """ 
  3  import os, sys 
  4  import mrv 
  5  from mrv import init_modules 
  6  from mrv.util import capitalize, DAGTree, PipeSeparatedFile 
  7  from mrv.exc import MRVError 
  8  from mrv.path import make_path 
  9  from mrv.cmd.base import maya_to_py_version_map 
 10   
 11  from itertools import chain 
 12  import logging 
 13  log = logging.getLogger("mrv.maya") 
 14   
 15  # initialize globals 
 16  if not hasattr( sys,"_dataTypeIdToTrackingDictMap" ): 
 17          sys._dataTypeIdToTrackingDictMap = dict()                        # DataTypeId : tracking dict 
 18   
 19   
 20  __all__ = ("registerPluginDataTrackingDict", ) 
 21   
 22  ############################ 
 23  #### COMMON                     #### 
 24  ########################## 
 25   
 26  #{ Common 
 27   
28 -def registerPluginDataTrackingDict( dataTypeID, trackingDict ):
29 """Using the given dataTypeID and tracking dict, nt.PluginData can return 30 self pointers belonging to an MPxPluginData instance as returned by MFnPluginData. 31 Call this method to register your PluginData information to the mrv system. 32 Afterwards you can extract the self pointer using plug.masData().data()""" 33 sys._dataTypeIdToTrackingDictMap[ dataTypeID.id() ] = trackingDict
34 35 #} End Common 36 37 38 #{ Init new maya version
39 -def initializeNewMayaRelease( ):
40 """This method should be called once a new maya release is encountered. It will 41 initialize and update the database as well as possible, and give instructions 42 on what to do next. 43 44 :note: Will not run if any user setup is performed as we need a clean maya 45 without any plugins loaded. 46 :raise EnvironmentError: if the current maya version has already been initialized 47 or if the user setup was executed""" 48 if int(os.environ.get('MRV_STANDALONE_AUTOLOAD_PLUGINS', 0)) or \ 49 int(os.environ.get('MRV_STANDALONE_RUN_USER_SETUP', 0)): 50 raise EnvironmentError("Cannot operate if custom user setup was performed") 51 # END check environments 52 53 import env 54 import mdb 55 56 nodeshf = mdb.nodeHierarchyFile() 57 app_version = env.appVersion()[0] 58 if nodeshf.isfile(): 59 raise EnvironmentError("Maya version %g already initialized as hierarchy file at %s does already exist" % (app_version, nodeshf)) 60 # END assure we are not already initialized 61 62 # UPDATE MFN DB FILES 63 ##################### 64 # Get all MFn function sets and put in their new versions as well as files 65 mdb.writeMfnDBCacheFiles() 66 67 # UPDATE NODE HIERARCHY FILE 68 ############################ 69 # create all node types, one by one, and query their hierarchy relationship. 70 # From that info, generate a dagtree which is written to the hierarchy file. 71 # NOTE: for now we just copy the old one 72 dagTree, typeToMFnList = mdb.generateNodeHierarchy() 73 dagTree.to_hierarchy_file('_root_', mdb.nodeHierarchyFile()) 74 75 # UPDATE MFN ASSOCIATIONS 76 ######################### 77 fp = open(mdb.cacheFilePath('nodeTypeToMfnCls', 'map'), 'wb') 78 mla = reduce(max, (len(t[0]) for t in typeToMFnList)) 79 mlb = reduce(max, (len(t[1]) for t in typeToMFnList)) 80 81 psf = PipeSeparatedFile(fp) 82 psf.beginWriting((mla, mlb)) 83 for token in typeToMFnList: 84 psf.writeTokens(token) 85 # END for each line to write 86 fp.close() 87 88 89 # PROVIDE INFO TO THE USER 90 ############################ 91 print >> sys.stderr, "1. git status might reveals new MFnFunction sets as untracked files - check the new methods and possibly define aliases (or delete them wiht 'x')" 92 print >> sys.stderr, "2. Check the 'whats new' part of the maya docs for important API changes and possibly incorporate them into the code" 93 print >> sys.stderr, "3. run 'tmrv %g' and fix possibly breaking tests or the code being tested" % app_version 94 print >> sys.stderr, "4. run 'tmrvr' to assure all maya versions are still working - ideally on all platforms." 95 print >> sys.stderr, "5. run the UI tests and assure that they don't fail" 96 print >> sys.stderr, "6. Commit and push your changes - you are done"
97 98 #} END init new maya version 99 100 101 #{ Internal Utilities
102 -def dag_tree_from_tuple_list( tuplelist ):
103 """:return: DagTree from list of tuples [ (level,name),...], where level specifies 104 the level of items in the dag. 105 :note: there needs to be only one root node which should be first in the list 106 :return: `DagTree` item allowing to easily query the hierarchy """ 107 tree = None 108 lastparent = None 109 lastchild = None 110 lastlevel = 0 111 112 for no,item in enumerate( tuplelist ): 113 level, name = item 114 115 if level == 0: 116 if tree != None: 117 raise MRVError( "DAG tree must currently be rooted - thus there must only be one root node, found another: " + name ) 118 else: 119 tree = DAGTree( ) # create root 120 tree.add_node( name ) 121 lastparent = name 122 lastchild = name 123 continue 124 125 direction = level - lastlevel 126 if direction > 1: 127 raise MRVError( "Can only change by one down the dag, changed by %i in item %s" % ( direction, str( item ) ) ) 128 129 lastlevel = level 130 if direction == 0: 131 pass 132 elif direction == 1 : 133 lastparent = lastchild 134 elif direction == -1: 135 lastparent = tree.parent( lastparent ) 136 elif direction < -1: # we go many parents back, find the parent at level 137 lastparent = list( tree.parent_iter( lastparent ) )[ -level ] 138 139 tree.add_edge( lastparent, name ) 140 lastchild = name 141 # END for each line in hiearchy map 142 143 return tree
144
145 -def tuple_list_from_file( filepath ):
146 """Create a tuple hierarchy list from the file at the given path 147 :return: tuple list suitable for dag_tree_from_tuple_list""" 148 lines = make_path( filepath ).lines( retain = False ) 149 150 hierarchytuples = list() 151 # PARSE THE FILE INTO A TUPLE LIST 152 for no,line in enumerate( lines ): 153 item = ( line.count( '\t' ), line.lstrip( '\t' ) ) 154 hierarchytuples.append( item ) 155 156 return hierarchytuples
157
158 -def initWrappers( mdict, types, metacreatorcls, force_creation = False ):
159 """ Create standin classes that will create the actual class once creation is 160 requested. 161 :param mdict: module dictionary object from which the latter classes will be imported from, 162 can be obtained using ``globals()`` in the module 163 :param types: iterable containing the names of classnames ( they will be capitalized 164 as classes must begin with a capital letter )""" 165 from mrv.maya.util import StandinClass 166 167 # create dummy class that will generate the class once it is first being instatiated 168 standin_instances = list() 169 for uitype in types: 170 clsname = capitalize( uitype ) 171 172 # do not overwrite hand-made classes 173 if clsname in mdict: 174 continue 175 176 standin = StandinClass( clsname, metacreatorcls ) 177 mdict[ clsname ] = standin 178 179 if force_creation: 180 standin_instances.append(standin) 181 # END for each uitype 182 183 # delay forced creation as there may be hierarchical relations between 184 # the types 185 for standin in standin_instances: 186 standin.createCls( )
187
188 -def move_vars_to_environ( ):
189 """Move the maya vars as set in the shell into the os.environ to make them available to python""" 190 import maya.cmds as cmds 191 import subprocess 192 envcmd = "env" 193 194 if cmds.about( nt=1 ): 195 envcmd = "set" 196 197 p = subprocess.Popen( envcmd, shell=True, stdout=subprocess.PIPE ) 198 199 for line in p.stdout: 200 try: 201 var,value = line.split("=", 1) 202 except: 203 continue 204 else: 205 os.environ[ var ] = value.strip()
206 # END try to split line 207 # END for each line from process' stdout 208 #} END internal utilities 209 210 211 212 ############################ 213 #### INITIALIZATION #### 214 ######################### 215 216 #{ Initialization
217 -def init_system( ):
218 """ 219 Check if we are suited to import the maya namespace and try to set it 220 up such we can use the maya standalone package. 221 If running within maya or whith maya py, this is true, otherwise we have to 222 use the MAYA_LOCATION to get this to work. 223 """ 224 # RUNNING WITHIN MAYA ? Then we have everything 225 # if being launched in mayapy, we need initialization though ! 226 binBaseName = os.path.split( sys.executable )[1].split( '.' )[0] 227 if binBaseName[0:4].lower() == 'maya' and binBaseName[0:6].lower() != 'mayapy': 228 return 229 230 231 # try to setup the paths to maya accordingly 232 locvar = 'MAYA_LOCATION' 233 if not os.environ.has_key( locvar ): 234 raise EnvironmentError( locvar + " was not set - it must point to the maya installation directory" ) 235 236 # EXTRACT VERSION INFORMATION IF POSSIBLE 237 ########################################## 238 mayalocation = os.path.realpath(os.environ[locvar]) 239 splitpos = -1 240 241 # OS X special case 242 if mayalocation.endswith( "Contents" ): 243 splitpos = -3 244 245 mayabasename = mayalocation.split( os.sep )[ splitpos ] 246 247 # currently unused 248 bits = 32 249 if mayabasename.endswith( '64' ): 250 bits = 64 251 252 mayabasename = mayabasename.replace( "-x64", "" ) # could be mayaxxxx-x64 253 mayaversion = mayabasename[4:] # could be without version, like "maya" 254 fmayaversion = float(mayaversion) 255 256 257 # PYTHON COMPATABILITY CHECK 258 ############################## 259 pymayaversion = sys.version_info[0:2] 260 if len( mayaversion ): 261 pyminor = pymayaversion[1] 262 263 if float(mayaversion) not in maya_to_py_version_map: 264 raise EnvironmentError( "Requires Maya 8.5 or higher for python support, found " + mayaversion + " (or maya version is not implemented)" ) 265 266 pyversion = pymayaversion[0] + (pymayaversion[1]/10.0) 267 if maya_to_py_version_map[float(mayaversion)] != pyversion: 268 raise EnvironmentError( "Maya " + mayaversion + " python interpreter requirements not met" ) 269 # END check python version 270 # END check maya version 271 272 273 # CHECK AND FIX SYSPATH 274 ######################## 275 # to be very sure: If for some reason we have our own root package 276 # in the path, remove it as we would most likely import our own maya 277 # This appears to happen if mrv is installed as site-package btw. 278 # remove existing sys-paths containing maya, just to be sure we get the right one 279 for path in sys.path[:]: 280 if os.path.isdir(os.path.join(path, 'maya')) and not path.endswith("site-packages"): 281 sys.path.remove(path) 282 # END if if maya package was found 283 # END for each path in sys.path 284 285 # FINALLY INIALIZE MAYA TO TO MAKE USE OF MAYA STANDALONE 286 ########################################################### 287 if os.name == "nt": 288 osspecific = os.path.join("Python", "lib") 289 else: 290 pyversionstr = str( pymayaversion[0] ) + "." + str( pymayaversion[1] ) 291 osspecific = os.path.join("lib", "python" + pyversionstr, "site-packages") 292 293 mayapylibpath = os.path.join( mayalocation, osspecific, "site-packages" ) 294 sys.path.append( mayapylibpath ) 295 296 297 # although this was already done, do it again :). Its required if mrv is installed 298 # natively 299 mrv._remove_empty_syspath_entries() 300 301 try: 302 import maya 303 except Exception, e: 304 print "Paths in sys.path: " 305 for p in sys.path: print "%r" % p 306 raise EnvironmentError( "Failed to import maya - check this script or assure LD_LIBRARY path is set accordingly: " + str( e ) ) 307 # END handle import 308 309 310 # FINALLY STARTUP MAYA 311 ######################## 312 # This will also set all default path environment variables and read the 313 # maya environment file 314 try: 315 import maya.standalone 316 maya.standalone.initialize() 317 except: 318 log.debug("Paths in sys.path: ") 319 for p in sys.path: log.debug("%r" % p) 320 if 'maya' in locals(): 321 log.info("Imported maya module is located at: %r" % maya.__file__) 322 log.error("ERROR: Failed initialize maya") 323 raise 324 # END handle maya standalone initialization 325 326 327 # COPY ENV VARS 328 ############### 329 # NOTE: this might have to be redone in your own package dependent on when 330 # we are called - might be too early here 331 # This also handles the Maya.env variables 332 if fmayaversion < 2009: 333 move_vars_to_environ( ) 334 335 # FINISHED 336 return
337 338 # END INIT SYSTEM 339
340 -def init_path( ):
341 """Setup the path type to use slashes internally, no matter which operating 342 system we are on""" 343 import mrv.path 344 mrv.path.BasePath.set_separator('/')
345
346 -def init_user_prefs( ):
347 """intiialize the user preferences according to the set configuration variables""" 348 try: 349 init_mel = int(os.environ.get('MRV_STANDALONE_INIT_OPTIONVARS', 0)) 350 run_user_setup = int(os.environ.get('MRV_STANDALONE_RUN_USER_SETUP', 0)) 351 autoload_plugins = int(os.environ.get('MRV_STANDALONE_AUTOLOAD_PLUGINS', 0)) 352 except ValueError, e: 353 log.warn("Invalid value for MRV configuration variable: %s" % str(e).split(':', 1)[-1]) 354 # END safe access to variables 355 356 def source_file_safely(script): 357 try: 358 maya.mel.eval('source "%s"' % script) 359 except RuntimeError, e: 360 log.error(str(e) + "- ignored")
361 # END exception handling 362 # END utility 363 364 if not (init_mel|run_user_setup|autoload_plugins): 365 return 366 367 import maya.cmds as cmds 368 prefsdir = make_path(cmds.internalVar(userPrefDir=1)) 369 370 if not prefsdir.isdir(): 371 log.warn("User Preferences directory did not exist: %s" % prefsdir) 372 return 373 # END check for existence 374 375 # source actual MEL scripts 376 sources = list() 377 if init_mel: 378 sources.append("createPreferencesOptVars.mel") 379 sources.append("createGlobalOptVars.mel") 380 sources.append(prefsdir + "/userPrefs.mel") 381 # END option vars 382 383 if autoload_plugins: 384 sources.append(prefsdir + "/pluginPrefs.mel") 385 # END autoload plugins 386 387 # run scripts we collected 388 import maya.mel 389 for scriptpath in sources: 390 if os.path.isabs(scriptpath) and not os.path.isfile(scriptpath): 391 log.warn("Couldn't source %s as it did not exist" % scriptpath) 392 # END check whether absolute paths are available 393 394 source_file_safely(scriptpath) 395 # END for each script path 396 397 if run_user_setup: 398 # mel 399 source_file_safely("userSetup.mel") 400 401 # userSetup.py gets executed by maya 402 # END run user setup 403 404
405 -def init_singletons( ):
406 """ Initialize singleton classes and attach them direclty to our module""" 407 global Scene 408 global Mel 409 410 import scene 411 Scene = scene.Scene() 412 413 import util 414 Mel = util.Mel()
415 416
417 -def init_standard_output( ):
418 """Assure that logging can print to stdout and stderr which get overwritten 419 by special maya versions which lack the 'flush' method""" 420 421 class PassOnOrDummy(object): 422 def __init__(self, obj): 423 self.obj = obj
424 425 def does_nothing(self, *args, **kwargs): 426 return 427 428 def __getattr__(self, attr): 429 try: 430 return getattr(self.obj, attr) 431 except AttributeError: 432 return self.does_nothing 433 # END handle object retrieval 434 # END utility class 435 436 for channame in ('stdout', 'stderr'): 437 chan = getattr(sys, channame) 438 if hasattr(chan, 'flush'): 439 continue 440 # END skip channels that would work 441 442 # patch the curently established channel 443 fixedchan = PassOnOrDummy(chan) 444 setattr(sys, channame, fixedchan) 445 446 # find all loggers so far and patch up their logging objects 447 for l in chain((logging.root, ), logging.root.manager.loggerDict.values()): 448 if not isinstance(l, logging.Logger): 449 continue 450 # END skip placeholders 451 for handler in l.handlers: 452 if isinstance(handler, logging.StreamHandler) and handler.stream is chan: 453 handler.stream = fixedchan 454 # END if stream needs fixing 455 # END for each handler 456 # END for each logger 457 # END for each channel 458 459 460 #} Initialization 461 462 if 'init_done' not in locals(): 463 init_done = False 464 465 466 if not init_done: 467 # assure we do not run several times 468 init_system() 469 init_path() 470 init_standard_output() 471 init_modules(__file__, "mrv.maya") 472 init_singletons() 473 474 # this serves as a reentrance check in case userSetup is importing us again 475 init_done = True 476 init_user_prefs() 477