def BackUPPPPPP(self,*args):
        Flag = cmds.checkBox(self.CheckScene,q=True,v=True)
        FlagXgen = cmds.checkBox(self.CheckXGen,q=True,v=True)
        day = datetime.datetime.now()
        Time = day.strftime("%m-%d_%Hh%Mm%Ss")
        Scene_Name = cmds.file( query=True, sn=True).rpartition( "/" )[0] 
        Scene_Name_Only = cmds.file( query=True, sn=True , shn=True).partition( "." )[0]
        Scene_Exten = cmds.file( query=True, sn=True , shn=True).partition( "." )[-1]
            
        Path = Scene_Name + "/versionFolder/"
        if not os.path.exists(Path): 
            os.makedirs(Path)
        Path2 = Path + "/" + Time + "/"
        if not os.path.exists(Path2): 
            os.makedirs(Path2)

        if Flag:
            cmds.file(save=True, force=True)            
            Rename = str(Path2)+str(Scene_Name_Only)+"_"+str(Time)+"."+Scene_Exten
            Scene_Dir = cmds.file( query=True, sn=True)
            shutil.copyfile(Scene_Dir, Rename)
        
        if FlagXgen:
            Scene_Name = cmds.file( query=True, sn=True).rpartition( "/" )[0]
            XGenPath = Scene_Name.rpartition( "/" )[0] + "/xgen/"

            if not os.path.exists(XGenPath): 
                os.makedirs(XGenPath)

            Sel = cmds.ls(sl=True)[0]
            try:
                xg.exportPalette(str(Sel), str(XGenPath) + "Collection.xgen")
            except:
                print "NG"
            RenameXgen = str(Path2)+str(Scene_Name_Only)+"_"+str(Time)+".xgen"
            shutil.copyfile(str(XGenPath) + "Collection.xgen", RenameXgen)
        
        FlagMemo = cmds.checkBox(self.CheckMemo,q=True,v=True)
        if FlagMemo:
            f = open(Path2 + Scene_Name_Only + "_" + Time +".txt",'w')
            textVal = cmds.scrollField(self.TectBox,q=True,text=True)
            WriteText = textVal.splitlines()
            for i in WriteText:
                f.write(i)
                f.write("\r\n")
            f.close()
    def _do_export(self):
        """
        Executes the export of the choose collection
        """

        # Get data from ui
        self.collection_name = self.ui.collection_cbx.currentText()
        self.shaders_dict = self._get_shaders()
        self.scalps_list = self._get_scalps()
        ptx_folder = self._get_root_folder()
        export_path = self.ui.path_txf.text()
        self.character = self.ui.export_character_cbx.currentText()
        comment = self.ui.comment_pte.toPlainText()

        # analise if there is an export folder
        if not export_path:
            if not self.character:
                raise ValueError("export path must be specified")

        ################################################################################################################
        # Export objects into a .groom folder
        ################################################################################################################
        # generate export path
        if export_path:
            self.export_path_folder = export_path
            if '.groom' not in export_path:
                self.export_path_folder = export_path + '.groom'
        else:
            working_folder = self._project.get_working_folder()
            self.export_path_folder = os.path.join(
                self.proje.get_asses_path(), "Characters", self.character, working_folder,
                "groom", "groom_package.groom")

        # if the folder already exists delete it, and create a new one
        self.delete_artella_folder(self.export_path_folder)
        os.makedirs(self.export_path_folder)

        # get the ptx path
        if '${PROJECT}' in ptx_folder:
            project_path = str(mc.workspace(fullName=True, q=True))
            ptx_folder = os.path.join(project_path, ptx_folder.replace('${PROJECT}', ''))
        LOGGER.debug("XGEN || All data parsed")
        self.ui.progress_lbl.setText("Exporting Files (PTX)")
        # copy the ptx files
        shutil.copytree(ptx_folder, os.path.join(self.export_path_folder, self.collection_name))
        LOGGER.debug("XGEN || PTEX files exported")

        # export xgen file
        xg.exportPalette(palette=str(self.collection_name),
                         fileName=str("{}/{}.xgen".format(self.export_path_folder, self.collection_name)))
        self.ui.progress_lbl.setText("Exporting Files (.XGEN)")
        LOGGER.debug("XGEN || Collection file exported")

        # export sculpts
        mc.select(self.scalps_list, replace=True)
        mc.file(rename=os.path.join(self.export_path_folder, 'scalps.ma'))
        mc.file(es=True, type='mayaAscii')
        mc.select(cl=True)
        self.ui.progress_lbl.setText("Exporting Scalps (.MA)")
        LOGGER.debug("XGEN || Sculpts Exported")

        # export material
        artellapipe.ShadersMgr().export_shaders(shader_names=self.shaders_dict.values(), publish=True, comment=comment)

        self.ui.progress_lbl.setText("Exporting Material (.sshader)")
        LOGGER.debug("XGEN || Material Exported")

        # export mapping
        with open(os.path.join(self.export_path_folder, 'shader.json'), 'w') as fp:
            json.dump(self.shaders_dict, fp)
        self.ui.progress_lbl.setText("Exporting Mapping (.JSON)")
        LOGGER.debug("XGEN || Mapping Exported")

        # add file to artella
        if comment:
            self._add_file_to_artella(file_path_global=self.export_path_folder, comment=comment)
            LOGGER.debug("XGEN || Files added to artella")
        else:
            LOGGER.warning("XGEN || Files are not been loaded to Artella. Do it manually")
Beispiel #3
0
 def publishCollection(self):
     xg.exportPalette(
         self.collection,
         str(self.publishPath / self.collection + '.xgen').replace(
             '\\', '/'))
Beispiel #4
0
class MayaXGenPublishPlugin(HookBaseClass):
    @property
    def description(self):

        return """
        <p>
        This plugin handles exporting and publishing Maya XGen.
        Collected mesh shaders are exported to disk as .ma files that can
        be loaded by artists downstream. This is a simple, example
        implementation and not meant to be a robust, battle-tested solution for
        shader or texture management on production.
        </p>
        """

    @property
    def settings(self):

        plugin_settings = super(MayaXGenPublishPlugin, self).settings or {}

        # settings specific to this class
        xgen_publish__settings = {
            "Publish Template": {
                "type":
                "template",
                "default":
                None,
                "description":
                "Template path for published shader networks. "
                "Should correspond to a template defined in "
                "templates.yml.",
            }
        }

        # update the base settings
        plugin_settings.update(xgen_publish__settings)

        return plugin_settings

    @property
    def item_filters(self):
        return ["maya.session.xgen"]

    ############################################################################
    # Publish processing methods

    def accept(self, settings, item):

        accepted = True

        # a handle on the instance of the publisher app
        publisher = self.parent

        # extract the value of the template configured for this instance
        template_name = settings["Publish Template"].value

        # ensure a work file template is available on the parent maya session
        # item.
        work_template = item.parent.properties.get("work_template")
        if not work_template:
            self.logger.debug(
                "A work template is required for the session item in order to "
                "publish session geometry. Not accepting session geom item.")
            accepted = False

        # ensure the publish template is defined and valid
        publish_template = publisher.get_template_by_name(template_name)
        self.logger.debug("TEMPLATE NAME: " + str(template_name))
        if not publish_template:
            self.logger.debug(
                "A valid publish template could not be determined for the "
                "session geometry item. Not accepting the item.")
            accepted = False

        # we've validated the publish template. add it to the item properties
        # for use in subsequent methods
        item.properties["publish_template"] = publish_template

        # because a publish template is configured, disable context change. This
        # is a temporary measure until the publisher handles context switching
        # natively.
        item.context_change_allowed = False

        return {"accepted": accepted, "checked": True}

    def validate(self, settings, item):

        path = _session_path()
        _ext = os.path.splitext(path)[-1]
        project_root, basename = os.path.split(path)
        basename = basename.split(_ext)[0]
        collection = item.properties['collection']

        # ---- ensure the session has been saved

        if not path:
            # the session still requires saving. provide a save button.
            # validation fails.
            error_msg = "The Maya session has not been saved."
            self.logger.error(error_msg, extra=_get_save_as_action())
            raise Exception(error_msg)

        # get the normalized path. checks that separators are matching the
        # current operating system, removal of trailing separators and removal
        # of double separators, etc.
        path = sgtk.util.ShotgunPath.normalize(path)

        object_name = item.properties["collection"]
        self.logger.debug("object_name:%s" % object_name)
        # check that there is still geometry in the scene:
        if (not cmds.ls(object_name, dag=True, type="xgmPalette")):
            error_msg = (
                "Validation failed because there are no meshes in the scene "
                "to export xgen collection for. You can uncheck this plugin or create "
                "xgen collection.")
            self.logger.error(error_msg)
            raise Exception(error_msg)

        # get the configured work file template
        work_template = item.parent.properties.get("work_template")
        publish_template = item.properties.get("publish_template")
        self.logger.debug("work_template:---%s" % work_template)
        # get the current scene path and extract fields from it using the work
        # template:
        work_fields = work_template.get_fields(path)
        work_fields["xgfilename"] = basename + "__" + collection

        # we want to override the {name} token of the publish path with the
        # name of the object being exported. get the name stored by the
        # collector and remove any non-alphanumeric characters
        object_display = re.sub(r'[\W_]+', '', object_name)
        work_fields["name"] = object_display

        # set the display name as the name to use in SG to represent the publish
        item.properties["publish_name"] = object_display

        # ensure the fields work for the publish template
        missing_keys = publish_template.missing_keys(work_fields)
        if missing_keys:
            error_msg = "Work file '%s' missing keys required for the " \
                        "publish template: %s" % (path, missing_keys)
            self.logger.error(error_msg)
            raise Exception(error_msg)

        item.properties["path"] = publish_template.apply_fields(work_fields)
        # use the work file's version number when publishing
        if "version" in work_fields:
            item.properties["publish_version"] = work_fields["version"]
        self.logger.debug("version:%s" % item.properties["publish_version"])

        # run the base class validation

        return super(MayaXGenPublishPlugin, self).validate(settings, item)

    def publish(self, settings, item):

        # save the file
        cmds.file(save=True)

        publisher = self.parent
        path = _session_path()
        _ext = os.path.splitext(path)[-1]
        project_root, basename = os.path.split(path)
        # basename = basename.split(_ext)[0]

        # get the path to create and publish
        publish_path = item.properties["path"]
        publish_dir = os.path.dirname(publish_path)
        collection_path = item.properties['collection_path']
        collection = item.properties['collection']
        # ensure the publish folder exists:
        publisher.ensure_folder_exists(publish_dir)
        # copy work's collection to publish path
        _, folder = os.path.split(collection_path)
        dst = os.path.join(publish_dir, folder)
        sgtk.util.filesystem.copy_folder(collection_path, dst)

        # export .xgen
        try:
            import xgenm as xg
        except Exception, e:
            self.logger.debug(e)
            return
        xg.exportPalette(collection, publish_path)
        # change xgProjectPath
        publish_path_root = project_root.replace("/work/", "/publish/") + "/"
        changeXGenProjectPath(publish_path, publish_path_root,
                              item.properties["publish_version"], collection,
                              self.logger)

        self.logger.info("A Publish will be created in Shotgun and linked to:")
        self.logger.info("  %s" % (publish_path))
        # publish the path to shotgun

        item.properties["publish_type"] = "Maya XGen"

        # plugin to do all the work to register the file with SG
        super(MayaXGenPublishPlugin, self).publish(settings, item)
Beispiel #5
0
def export_palette(palette, out_path):
    out_path = out_path.replace("\\", "/")
    xg.exportPalette(str(palette), str(out_path))
Beispiel #6
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
Beispiel #7
0
 def export_palette(self, palette, xgen_path):
     xgen_dir = os.path.dirname(xgen_path)
     if not os.path.isdir(xgen_dir):
         os.makedirs(xgen_dir)
     xgen.exportPalette(palette, xgen_path)