Example #1
0
    def importDescription(self, palName, descName, version, binding=False):
        """
		XGen description will imported without validator.
		When importing baked description, @binding set to False should be fine.
		"""
        xdscFileName = descName + '.xdsc'
        xdscFile = '/'.join(
            [self.paletteVerDir(palName, version), descName, xdscFileName])
        if not os.path.isfile(xdscFile):
            pm.error('[XGen Hub] : .xdsc file is not exists. -> ' + xdscFile)
            return None

        self.clearPreview()

        # check if descriptions exists in current scene
        if descName in xg.descriptions(palName):
            # delete current description folder
            descDir = xg.expandFilepath('${DESC}', descName)
            if os.path.isdir(descDir):
                try:
                    dir_util.remove_tree(descDir)
                except:
                    pm.warning('[XGen Hub] : Dir may not remove. -> ' +
                               descDir)
            # delete current description
            xg.deleteDescription(palName, descName)
        # IMPORT DESCRIPTION
        desc = base.importDescription(palName, xdscFile)
        # create imported descriptions folder
        dataPath = xg.getAttr('xgDataPath', palName)
        paletteRoot = xg.expandFilepath(dataPath, '')
        msxgApi.setupDescriptionFolder(paletteRoot, palName, desc)
        # wrap into maya nodes
        pm.mel.xgmWrapXGen(pal=palName, d=desc, gi=binding)
        # bind to selected geometry
        if binding:
            igdesc = xg.getAttr('groom', palName, desc)
            xg.modifyFaceBinding(palName, desc, 'Append', '', False,
                                 len(igdesc))
            if igdesc:
                # set groom density and sampling method
                pm.setAttr(igdesc + '.density', 1)
                pm.setAttr(igdesc + '.interpStyle', 1)

            # import grooming as well
            self.importGrooming(palName, descName, version)
        # import guides as well
        self.importGuides(palName, descName, version)

        self.notifyMsg('Description Import Complete !', 0)

        return desc
Example #2
0
def current_data_paths(palette, expand=False):
    paths = list()
    for path in xg.getAttr("xgDataPath", palette).split(";"):
        if expand:
            path = xg.expandFilepath(str(path), "")
        path = os.path.normpath(path).replace("\\", "/")
        paths.append(path)
    return paths
Example #3
0
	def importGuides(self, palName, descName= None, version= None):
		"""
		"""
		self.clearPreview()

		if descName:
			descs = [descName]
		else:
			descs = xg.descriptions(palName)
		# copy groom dir from versionRepo if @version has given
		if version:
			# check exists
			guidesDesc = {}
			hasMissing = False
			for desc in descs:
				if self.descControlMethod(palName, desc) == 'Guides':
					abcPath = '/'.join([self.paletteVerDir(palName, version), desc, 'curves.abc'])
					if os.path.isfile(abcPath):
						guidesDesc[desc] = abcPath
					else:
						hasMissing = True
						msg = '[XGen Hub] : palette [%s] description [%s] version [%s] NOT exists. -> %s'
						pm.warning(msg % (palName, desc, version, abcPath))
			# copy file if no missing
			if not hasMissing:
				for desc in guidesDesc:
					src = guidesDesc[desc]
					dst = '/'.join([self.paletteWipDir(palName), desc, 'curves.abc'])
					if os.path.isdir(dst):
						os.remove(dst)
					shutil.copyfile(src, dst)
			else:
				pm.error('[XGen Hub] : Some .abc missing, Check ScriptEditor. guides import stopped.')

				return None

		# IMPORT GUIDES
		for desc in descs:
			# import alembic
			if not pm.pluginInfo('AbcImport', q= 1, l= 1):
				pm.loadPlugin('AbcImport')
			abcPath = xg.expandFilepath('${DESC}', desc) + 'curves.abc'
			if os.path.isfile(abcPath):
				pool = pm.group(em= 1, n= 'curvesToGuide_processPoll')
				pm.mel.AbcImport(abcPath, mode= 'import', rpr= pool)
				# select curves
				curves = pm.listRelatives(pool, c= 1)
				pm.select(curves, r= 1)
				# curvesToGuides
				pm.mel.xgmCurveToGuide(d= desc, tsp= 1.0, tsa= 0.0, deleteCurve= True)

		self.notifyMsg('Guides Import Complete !', 0)

		return True
Example #4
0
	def exportFullPackage(self, palName, version, bake= False, anim= False):
		"""
		Export Palettes, Descriptions, Grooming, Guides, all together,
		even bake modifiers befoer export if needed.
		"""
		self.clearPreview()
		
		# bake modifiers
		generator = {}
		if bake:
			for desc in xg.descriptions(palName):
				# bake Noise modifiers
				# fxModules evals from bottom to top
				clumpModLast = ''
				for fxm in xg.fxModules(palName, desc):
					if xg.fxModuleType(palName, desc, fxm) == 'ClumpingFXModule':
						# set the top clumpingMod cvAttr to True, for anim modifiers which needs clump
						if clumpModLast:
							xg.setAttr('cvAttr', 'false', palName, desc, clumpModLast)
						xg.setAttr('cvAttr', 'true', palName, desc, fxm)
						clumpModLast = fxm
					if xg.fxModuleType(palName, desc, fxm) == 'NoiseFXModule':
						# temporarily turn off lod so we dont bake it in
						lod = xg.getAttr('lodFlag', palName, desc)
						xg.setAttr('lodFlag', 'false', palName, desc)
						# change mode for bake
						xg.setAttr('mode', '2', palName, desc, fxm)
						# bake the noise
						pm.mel.xgmNullRender(pb= desc)
						# restore
						xg.setAttr('lodFlag', lod, palName, desc)
						# change mode to baked
						xg.setAttr('mode', '1', palName, desc, fxm)
				# bake groom modifiers
				fxm = xg.addFXModule(palName, desc, 'BakedGroomManagerFXModule')
				xg.setAttr('active', 'true', palName, desc, fxm)
				xg.bakedGroomManagerBake(palName, desc)
				# set Generator to XPD
				generator[desc] = xg.getActive(palName, desc, 'Generator')
				xg.setActive(palName, desc, 'FileGenerator')
		
		# change to export version path and keep current
		workPath = xg.getAttr('xgDataPath', palName)
		workProj = xg.getAttr('xgProjectPath', palName)
		xg.setAttr('xgDataPath', self.paletteVerDir(palName, version, raw= True), palName)
		xg.setAttr('xgProjectPath', self.projPath, palName)
		# get resolved repo path
		dataPath = self.paletteVerDir(palName, version)

		# set [xgDogTag] attr for ANIM record branchName
		if anim:
			xg.setAttr('xgDogTag', version, palName)

		# export descriptions
		for desc in xg.descriptions(palName):
			dstDescDir = xg.expandFilepath('${DESC}', desc, True, True)
			expPath = dstDescDir + desc + '.xdsc'
			xg.exportDescription(palName, desc, expPath)
			# copy map files
			srcDescVar = workPath.replace('${PROJECT}', workProj) + '/${DESC}'
			srcDescDir = xg.expandFilepath(srcDescVar, desc)
			for mapDir in os.listdir(srcDescDir):
				srcMap = os.path.join(srcDescDir, mapDir)
				dstMap = os.path.join(dstDescDir, mapDir)
				if os.path.isdir(srcMap):
					dir_util._path_created = {}
					dir_util.copy_tree(srcMap, dstMap)

		# export palettes
		expPath = dataPath + '/' + palName + '.xgen'
		xg.exportPalette(palName, expPath)

		# export grooming
		for desc in xg.descriptions(palName):
			igdesc = xg.getAttr('groom', palName, desc)
			if igdesc:
				expPath = xg.expandFilepath('${DESC}/groom', desc, True, True)
				tpu = 5
				sampling = 1
				igDescr = xg.igDescription(desc)
				# export Attribute Map
				try:
					pm.waitCursor(state= True)
					# may have .ptx file handle lock issue
					pm.mel.iGroom(exportMaps= expPath, texelsPerUnit= tpu,
						instanceMethod= sampling, description= igDescr)
				finally:
					pm.waitCursor(state= False)
				# export Mask
				try:
					pm.waitCursor(state= True)
					# may have .ptx file handle lock issue
					pm.mel.iGroom(exportMask= expPath, texelsPerUnit= tpu,
						description= igDescr)
				finally:
					pm.waitCursor(state= False)
				# export Region
				try:
					pm.waitCursor(state= True)
					# may have .ptx file handle lock issue
					pm.mel.iGroom(exportRegion= expPath, texelsPerUnit= tpu,
						description= igDescr)
				finally:
					pm.waitCursor(state= False)
				# export Settings
				jsonPath = expPath + 'groomSettings.json'
				groomSettings = {}.fromkeys(['density', 'length', 'width'])
				for key in groomSettings:
					groomSettings[key] = pm.getAttr(igdesc + '.' + key)
				with open(jsonPath, 'w') as jsonFile:
					json.dump(groomSettings, jsonFile, indent=4)

		# export guides
		with undoable('exportGuides'):
			for desc in xg.descriptions(palName):
				# listGuides
				guides = xg.descriptionGuides(desc)
				if not guides:
					continue
				expPath = xg.expandFilepath('${DESC}', desc)
				pm.select(guides, r= 1)
				# guides to curves
				curves = pm.mel.xgmCreateCurvesFromGuides(0, True)
				# export as alembic
				if not pm.pluginInfo('AbcExport', q= 1, l= 1):
					pm.loadPlugin('AbcExport')
				abcCmds = '-frameRange 1 1 -uvWrite -worldSpace -dataFormat ogawa '
				abcRoot = '-root ' + ' -root '.join([cur.longName() for cur in pm.ls(curves)])
				abcPath = expPath + 'curves.abc'
				pm.mel.AbcExport(j= abcCmds + abcRoot + ' -file ' + abcPath)

		if anim:
			# save out hairSystem preset
			presetMel = []
			for nodeType in ['nucleus', 'hairSystem', 'nRigid']:
				presetDict = self.ioAttrPreset(nodeType, True)
				presetMel.extend(presetDict.values())
			# move preset file to version repo
			presetRepo = self.nDynPresetPath(palName, version)
			if not os.path.exists(presetRepo):
				os.makedirs(presetRepo)
			for prs in presetMel:
				dstPath = '/'.join([presetRepo, os.path.basename(prs)])
				shutil.move(prs, dstPath)
			# create empty _shot_ folder
			shotDir = self.paletteDeltaDir(palName, version, '')
			if not os.path.exists(shotDir):
				os.makedirs(shotDir)

		# export snapshot
		for i in range(5):
			tmpPath = self.snapshotTmp % (i+1)
			if os.path.isfile(tmpPath):
				imgPath = self.snapshotImgPath(palName, version, str(i+1))
				if not os.path.exists(os.path.dirname(imgPath)):
					os.makedirs(os.path.dirname(imgPath))
				shutil.move(tmpPath, imgPath)

		# restore dataPath
		xg.setAttr('xgDataPath', workPath, palName)
		xg.setAttr('xgProjectPath', workProj, palName)

		# restore modifiers
		if bake:
			for desc in xg.descriptions(palName):
				# bake Noise modifiers
				for fxm in xg.fxModules(palName, desc):
					if xg.fxModuleType(palName, desc, fxm) == 'NoiseFXModule':
						# restore to live mode
						xg.setAttr('mode', '0', palName, desc, fxm)
				# remove bake groom modifiers
				for fxm in xg.fxModules(palName, desc):
					if xg.fxModuleType(palName, desc, fxm) == 'BakedGroomManagerFXModule':
						xg.removeFXModule(palName, desc, fxm)
				# restore Generator
				xg.setActive(palName, desc, generator[desc])

		self.refresh('Full')

		self.notifyMsg('Collection Export Complete !', 0)

		return True
Example #5
0
	def importGrooming(self, palName, descName= None, version= None):
		"""
		"""
		self.clearPreview()

		if descName:
			descs = [descName]
		else:
			descs = xg.descriptions(palName)
		# copy groom dir from versionRepo if @version has given
		if version:
			# check exists
			groomDesc = {}
			hasMissing = False
			for desc in descs:
				if xg.getAttr('groom', palName, desc):
					groomSource = '/'.join([self.paletteVerDir(palName, version), desc, 'groom'])
					if os.path.exists(groomSource):
						groomDesc[desc] = groomSource
					else:
						hasMissing = True
						msg = '[XGen Hub] : palette [%s] description [%s] version [%s] NOT exists. -> %s'
						pm.warning(msg % (palName, desc, version, groomSource))
			# copy file if no missing
			if not hasMissing:
				for desc in groomDesc:
					src = groomDesc[desc]
					dst = '/'.join([self.paletteWipDir(palName), desc, 'groom'])
					if os.path.isdir(dst):
						try:
							dir_util.remove_tree(dst)
						except:
							pm.warning('[XGen Hub] : Dir may not remove. -> ' + dst)
					dir_util._path_created = {}
					dir_util.copy_tree(src, dst)
			else:
				pm.error('[XGen Hub] : Some data missing, Check ScriptEditor. grooming import stopped.')

				return None

		self.refresh()
		# IMPORT GROOMING
		# clear out autoExport path for preventing grooming auto export
		xg.setOptionVarString('igAutoExportFolder', '')
		for desc in descs:
			if xg.getAttr('groom', palName, desc):
				importPath = xg.expandFilepath('${DESC}/groom', desc)
				igDescr = xg.igDescription(desc)
				# import Attribute Map
				try:
					pm.waitCursor(state= True)
					pm.mel.iGroom(im= importPath, d= igDescr)
				finally:
					pm.waitCursor(state= False)
				# import Mask
				try:
					pm.waitCursor(state= True)
					pm.mel.iGroom(ik= importPath, d= igDescr)
				finally:
					pm.waitCursor(state= False)
				# import Region
				try:
					pm.waitCursor(state= True)
					pm.mel.iGroom(ir= importPath, d= igDescr)
				finally:
					pm.waitCursor(state= False)
		# restore default autoExport path
		xg.setOptionVarString('igAutoExportFolder', '${DESC}/groom')

		# IMPORT GROOM SETTINGS
		"""
		Currently only grab [density] setting,
		['length', 'width'] will messed up imported grooming's map attribute
		"""
		for desc in descs:
			igdesc = xg.getAttr('groom', palName, desc)
			jsonPath = xg.expandFilepath('${DESC}/groom', desc) + 'groomSettings.json'
			if igdesc and os.path.isfile(jsonPath):
				groomSettings = {}
				with open(jsonPath) as jsonFile:
					groomSettings = json.load(jsonFile)
				for key in groomSettings:
					# grab [density] setting only
					if key == 'density':
						pm.setAttr(igdesc + '.' + key, groomSettings[key])

		self.notifyMsg('Grooming Import Complete !', 0)

		return True
Example #6
0
	def importPalette(self, palName, version, binding= False, anim= False, asDelta= False, delta= []):
		"""
		** NOT SUPPORT NAMESPACE **
		XGen palette will imported without validator.
		[!!!] When importing [BAKED] palette, @binding set to False should be fine.
		"""
		xgenFileName = palName + '.xgen'
		xgenFile = str('/'.join([self.paletteVerDir(palName, version), xgenFileName]))
		if not os.path.isfile(xgenFile):
			self.notifyMsg('.xgen file is not exists.', 2)
			pm.error('[XGen Hub] : .xgen file is not exists. -> ' + xgenFile)
			return None
		if asDelta and not pm.sceneName():
			self.notifyMsg('Please save the scene.', 2)
			return None
		
		self.clearPreview()
		
		# check if palette exists in current scene
		if palName in xg.palettes():
			# delete current palette folder
			palDir = xg.expandFilepath(xg.getAttr('xgDataPath', palName), '')
			if os.path.isdir(palDir):
				try:
					dir_util.remove_tree(palDir)
				except:
					pm.warning('[XGen Hub] : Dir may not remove. -> ' + palDir)
			# delete current palette
			# this action might cry about 'None type object has no attr "previewer"'
			# when there is no xgen ui panel
			xg.deletePalette(palName)
		
		# IMPORT PALETTE
		palName = base.importPalette(xgenFile, delta, '')
		# update the palette with the current project
		xg.setAttr('xgProjectPath', str(pm.workspace(q= 1, rd= 1)), palName)
		dataPath = xg.paletteRootVar() + '/' + palName
		xg.setAttr('xgDataPath', dataPath, palName)
		# create imported palette folder
		paletteRoot = xg.expandFilepath(dataPath, '', True, True)
		# create all imported descriptions folder
		msxgApi.setupDescriptionFolder(paletteRoot, palName)
		# wrap into maya nodes
		palName = str(pm.mel.xgmWrapXGen(pal= palName, wp= binding, wlg= binding, gi= binding))
		# copy maps from source
		descNames = xg.descriptions(palName)
		msxgApi.setupImportedMap(xgenFile, palName, descNames, self.projPath)
		# bind grooming descriptions to geometry
		if binding:
			for desc in descNames:
				igdesc = xg.getAttr('groom', palName, desc)
				if igdesc:
					# get groom dag node
					igdesc = xg.igActivateDescription(desc)
					# bind groom to geo
					pm.mel.igBindFromXGen(desc)
					# set groom density and sampling method
					pm.setAttr(igdesc + '.density', 1)
					pm.setAttr(igdesc + '.interpStyle', 1)
					# set all groom visible on
					xg.igSetDescriptionVisibility(True)
					# sync primitives tab attritube map path with auto export path
					xg.igSyncMaps(desc)

			# import grooming as well
			self.importGrooming(palName)

		# import as anim, build hairSystem
		if anim:
			# build hairSystem
			self.linkHairSystem(palName)
			# check preset dir exists
			presetLocalDir = str(pm.internalVar(userPresetsDir= 1))
			presetRepo = self.nDynPresetPath(palName, version)
			if os.path.exists(presetRepo):
				# copy preset
				for prs in os.listdir(presetRepo):
					dstPath = presetLocalDir + prs
					prs = '/'.join([presetRepo, prs])
					shutil.copyfile(prs, dstPath)
				# load preset
				# [note] nucleus preset will not be loaded during current devlope
				presetMel = []
				for nodeType in ['hairSystem', 'nRigid']:
					presetDict = self.ioAttrPreset(nodeType, False)
					presetMel.extend(presetDict.values())
				# dump preset
				for prs in presetMel:
					if os.path.isfile(prs):
						os.remove(prs)
			else:
				pm.warning('[XGen Hub] : nDynamic attribute presets folder not found.')

		if asDelta:
			dataPath = xg.getAttr('xgDataPath', palName)
			dataPath = dataPath + ';' + self.paletteVerDir(palName, version, raw= True)
			xg.setAttr('xgDataPath', dataPath, palName)
			# save scenes
			pm.saveFile(f= 1)
			# set export delta
			pm.setAttr(palName + '.xgExportAsDelta', 1)

		pm.warning('[XGen Hub] : Collection Import Complete !')
		self.notifyMsg('Collection Import Complete !', 0)

		return palName