2
""" Inialize the mrv.maya sub-system and startup maya as completely as possible or configured """
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
11
from itertools import chain
13
log = logging.getLogger("mrv.maya")
16
if not hasattr( sys,"_dataTypeIdToTrackingDictMap" ):
17
sys._dataTypeIdToTrackingDictMap = dict() # DataTypeId : tracking dict
20
__all__ = ("registerPluginDataTrackingDict", )
22
############################
24
##########################
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
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
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
56
nodeshf = mdb.nodeHierarchyFile()
57
app_version = env.appVersion()[0]
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
64
# Get all MFn function sets and put in their new versions as well as files
65
mdb.writeMfnDBCacheFiles()
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())
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))
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
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"
98
#} END init new maya version
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 """
112
for no,item in enumerate( tuplelist ):
117
raise MRVError( "DAG tree must currently be rooted - thus there must only be one root node, found another: " + name )
119
tree = DAGTree( ) # create root
120
tree.add_node( name )
125
direction = level - lastlevel
127
raise MRVError( "Can only change by one down the dag, changed by %i in item %s" % ( direction, str( item ) ) )
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 ]
139
tree.add_edge( lastparent, name )
141
# END for each line in hiearchy map
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 )
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 )
156
return hierarchytuples
158
def initWrappers( mdict, types, metacreatorcls, force_creation = False ):
159
""" Create standin classes that will create the actual class once creation is
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
167
# create dummy class that will generate the class once it is first being instatiated
168
standin_instances = list()
170
clsname = capitalize( uitype )
172
# do not overwrite hand-made classes
176
standin = StandinClass( clsname, metacreatorcls )
177
mdict[ clsname ] = standin
180
standin_instances.append(standin)
181
# END for each uitype
183
# delay forced creation as there may be hierarchical relations between
185
for standin in standin_instances:
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
194
if cmds.about( nt=1 ):
197
p = subprocess.Popen( envcmd, shell=True, stdout=subprocess.PIPE )
199
for line in p.stdout:
201
var,value = line.split("=", 1)
205
os.environ[ var ] = value.strip()
206
# END try to split line
207
# END for each line from process' stdout
208
#} END internal utilities
212
############################
213
#### INITIALIZATION ####
214
#########################
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.
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':
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" )
236
# EXTRACT VERSION INFORMATION IF POSSIBLE
237
##########################################
238
mayalocation = os.path.realpath(os.environ[locvar])
242
if mayalocation.endswith( "Contents" ):
245
mayabasename = mayalocation.split( os.sep )[ splitpos ]
249
if mayabasename.endswith( '64' ):
252
mayabasename = mayabasename.replace( "-x64", "" ) # could be mayaxxxx-x64
253
mayaversion = mayabasename[4:] # could be without version, like "maya"
254
fmayaversion = float(mayaversion)
257
# PYTHON COMPATABILITY CHECK
258
##############################
259
pymayaversion = sys.version_info[0:2]
260
if len( mayaversion ):
261
pyminor = pymayaversion[1]
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)" )
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
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
285
# FINALLY INIALIZE MAYA TO TO MAKE USE OF MAYA STANDALONE
286
###########################################################
288
osspecific = os.path.join("Python", "lib")
290
pyversionstr = str( pymayaversion[0] ) + "." + str( pymayaversion[1] )
291
osspecific = os.path.join("lib", "python" + pyversionstr, "site-packages")
293
mayapylibpath = os.path.join( mayalocation, osspecific, "site-packages" )
294
sys.path.append( mayapylibpath )
297
# although this was already done, do it again :). Its required if mrv is installed
299
mrv._remove_empty_syspath_entries()
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 ) )
310
# FINALLY STARTUP MAYA
311
########################
312
# This will also set all default path environment variables and read the
313
# maya environment file
315
import maya.standalone
316
maya.standalone.initialize()
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")
324
# END handle maya standalone initialization
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( )
341
"""Setup the path type to use slashes internally, no matter which operating
344
mrv.path.BasePath.set_separator('/')
346
def init_user_prefs( ):
347
"""intiialize the user preferences according to the set configuration variables"""
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
356
def source_file_safely(script):
358
maya.mel.eval('source "%s"' % script)
359
except RuntimeError, e:
360
log.error(str(e) + "- ignored")
361
# END exception handling
364
if not (init_mel|run_user_setup|autoload_plugins):
367
import maya.cmds as cmds
368
prefsdir = make_path(cmds.internalVar(userPrefDir=1))
370
if not prefsdir.isdir():
371
log.warn("User Preferences directory did not exist: %s" % prefsdir)
373
# END check for existence
375
# source actual MEL scripts
378
sources.append("createPreferencesOptVars.mel")
379
sources.append("createGlobalOptVars.mel")
380
sources.append(prefsdir + "/userPrefs.mel")
384
sources.append(prefsdir + "/pluginPrefs.mel")
385
# END autoload plugins
387
# run scripts we collected
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
394
source_file_safely(scriptpath)
395
# END for each script path
399
source_file_safely("userSetup.mel")
401
# userSetup.py gets executed by maya
405
def init_singletons( ):
406
""" Initialize singleton classes and attach them direclty to our module"""
411
Scene = scene.Scene()
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"""
421
class PassOnOrDummy(object):
422
def __init__(self, obj):
425
def does_nothing(self, *args, **kwargs):
428
def __getattr__(self, attr):
430
return getattr(self.obj, attr)
431
except AttributeError:
432
return self.does_nothing
433
# END handle object retrieval
436
for channame in ('stdout', 'stderr'):
437
chan = getattr(sys, channame)
438
if hasattr(chan, 'flush'):
440
# END skip channels that would work
442
# patch the curently established channel
443
fixedchan = PassOnOrDummy(chan)
444
setattr(sys, channame, fixedchan)
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):
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
462
if 'init_done' not in locals():
467
# assure we do not run several times
470
init_standard_output()
471
init_modules(__file__, "mrv.maya")
474
# this serves as a reentrance check in case userSetup is importing us again