def set_abs_path(self, xgen_dir): if not xgg.Maya: return # palette is collection, use palettes to get collections first. palettes = xgen.palettes() for palette in palettes: # Use descriptions to get description of each collection descriptions = xgen.descriptions(palette) for description in descriptions: commaon_objs = xgen.objects(palette, description, True) fx_objs = xgen.fxModules(palette, description) objs = commaon_objs + fx_objs # Get active objs,e.g. SplinePrimtives for obj in objs: attrs = xgen.allAttrs(palette, description, obj) for attr in attrs: value = xgen.getAttr(attr, palette, description, obj) if "${DESC}" in value: print palette, description, obj, attr description_dir = os.path.join(xgen_dir, "collections", palette, description).replace("\\", "/") new_value = value.replace("${DESC}", description_dir) xgen.setAttr(attr, new_value, palette, description, obj) de = xgg.DescriptionEditor de.refresh("Full")
def get_xgen(task_id): _xgen_ = [] _file_name = cmds.file(q=True, sceneName=True) _file_path = os.path.dirname(_file_name) if not xgg.Maya: return _xgen_ _all_palettes = xg.palettes() _task = zfused_api.task.Task(task_id) _task_project_entity = _task.project_entity() _task_production_path = _task.production_path() # for _palette in _all_palettes: # _palette_dict ={} # _palette_xgen_filename =cmds.getAttr('{}.xgFileName'.format(_palette)) # _palette_path =os.path.join(_file_path,_palette_xgen_filename) # _palette_date =xg.getAttr('xgDataPath',_palette) # _palette_dict['_palette_name'] = _palette # _palette_dict['_palette_path'] = _palette_path # _palette_dict['_palette_date'] = _palette_date for _palette in _all_palettes: _palette_dict = {} _palette_xgen_filename = cmds.getAttr('{}.xgFileName'.format(_palette)) _palette_path = os.path.join(_task_production_path, _palette_xgen_filename).replace( '\\', '/') _palette_date = xg.getAttr('xgDataPath', _palette) _palette_dict['_palette_name'] = _palette _palette_dict['_palette_path'] = _palette_path _palette_dict['_palette_date'] = _palette_date _xgen_.append(_palette_dict) return _xgen_
def _get_all_collections(self): """ Get all collections in the maya scene :return: list, with the collection names """ collections_list = list() for item in xg.palettes(): collections_list.append(item) return collections_list
def get_description(): palettes = xgen.palettes() if not palettes: return descriptions = list() for palette in palettes: cell_desc = xgen.descriptions(palette) if cell_desc: descriptions.extend(cell_desc) return descriptions
def get_error_list(self): collections = xgen.palettes() if len(collections) > 1: return collections elif len(collections) == 1: collection_name = collections[0] context = pipeFile.PathDetails.parse_path() asset_name = context.asset_name if collection_name != "%s_collection" % asset_name: return collections
def setRefWiresFrame(self, refWiresFrame= None): """doc""" if not refWiresFrame: refWiresFrame = str(int(pm.PyNode('nucleus1').startFrame.get())) else: if pm.objExists('nucleus1'): pm.PyNode('nucleus1').startFrame.set(int(refWiresFrame)) for palName in xg.palettes(): for desc in xg.descriptions(palName): for fxm in xg.fxModules(palName, desc): if xg.fxModuleType(palName, desc, fxm) == 'AnimWiresFXModule': xg.setAttr('refWiresFrame', refWiresFrame, palName, desc, fxm) self.refresh('Full')
def _do_import(self): """ Imports the groom into the scene """ # todo: query if is it the last version import_folder = self.ui.groom_package_txf.text() self.character = self.ui.import_character_cbx.currentText() if not import_folder: raise ValueError("Import path must be specified") # build scene mc.loadPlugin('xgenToolkit.mll') import_path_folder = import_folder.replace('.zip', '') _, groom_asset = os.path.split(import_path_folder) xgen_file = [f for f in os.listdir(import_path_folder) if f.endswith('.xgen')][-1] xgen_file = os.path.join(import_path_folder, xgen_file).replace('\\', '/') map_folder = [os.path.join(import_path_folder, d) for d in os.listdir(import_path_folder) if os.path.isdir(os.path.join(import_path_folder, d))][0] # import maya scenes mc.file(os.path.join(import_folder, 'scalps.ma'), i=True, type="mayaAscii", ignoreVersion=True, mergeNamespacesOnClash=False, gl=True, namespace=self.character, options="v=0", groupReference=False) # load mapping in_data = dict() with open(os.path.join(import_path_folder, 'mapping.json'), 'r') as fp: in_data = json.load(fp) # import xgen try: xg.importPalette(fileName=str(xgen_file), deltas=[], nameSpace=str(self.character)) except Exception: LOGGER.warning('Not found maps folder') # set path to xgen xg.setAttr('xgDataPath', str(map_folder), xg.palettes()[0]) # todo: remember shader is not imported, it will be imported by the shader import tool # Get the description editor first. # Changes in the groom itself, guides, and so on de = xgg.DescriptionEditor # # # # # Do a full UI refresh de.refresh("Full")
def run(): # todo delete rig # ############ asset_name, ok = QInputDialog.getText(None, "Input", "Asset Name") if not ok: return palettes = xgen.palettes() if palettes: xgen_dir = QFileDialog.getExistingDirectory() if not xgen_dir: return maya = Maya(asset_name) maya.copy_textures() logger.info("Copy textures done.") if palettes: maya.set_xgen_path(xgen_dir) logger.info("xgen done.") maya.save_to_publish() logger.info("Save to publish done.") QMessageBox(None, "Warming Tip", "Congratulations, All done.")
def import_xgen_cache(): palettes = xgen.palettes() if not palettes: return for palette in palettes: asset_name = palette.split("_")[0] descriptions = xgen.descriptions(palette) if not descriptions: continue cache_dir = get_cache_dir() for description in descriptions: cache_file_name = "%s/%s/hair/%s.abc" % (cache_dir, asset_name, description) if not os.path.isfile(cache_file_name): continue xgen.setAttr("useCache", "true", palette, description, "SplinePrimitive") xgen.setAttr("liveMode", "false", palette, description, "SplinePrimitive") xgen.setAttr("cacheFileName", cache_file_name, palette, description, "SplinePrimitive") de = xgg.DescriptionEditor de.refresh("Full")
def buildUI(self): centralWidget = QWidget() self.setCentralWidget(centralWidget) mainLayout = QVBoxLayout() centralWidget.setLayout(mainLayout) # Guide tools section guideToolGrpBox = QGroupBox('Guide Tools') mainLayout.addWidget(guideToolGrpBox) guideMainLayout = QVBoxLayout() guideToolGrpBox.setLayout(guideMainLayout) guideToolBar = QToolBar() guideToolBar.setIconSize(QSize(32, 32)) guideMainLayout.addWidget(guideToolBar, 0, 1) addGuideAction = QAction( QIcon(os.path.join(XGEN_ICON_PATH, 'xgGuideContext.png')), 'Add or Move Guides', self) guideToolBar.addAction(addGuideAction) sculptGuideAction = QAction( QIcon(os.path.join(XGEN_ICON_PATH, 'fx_sculpt.png')), 'Sculpt Guides', self) guideToolBar.addAction(sculptGuideAction) convertToPolyAction = QAction( QIcon(os.path.join(XGEN_ICON_PATH, 'xgConvertToPoly.png')), 'Convert Primitives to Polygons', self) guideToolBar.addAction(convertToPolyAction) guideLayout = QGridLayout() guideMainLayout.addLayout(guideLayout) numOfCVsLabel = QLabel('Number of CP') guideLayout.addWidget(numOfCVsLabel, 0, 0) minusButton = QPushButton('-') guideLayout.addWidget(minusButton, 0, 1) plusButton = QPushButton('+') guideLayout.addWidget(plusButton, 0, 2) normalizeButton = QPushButton('Normalize') guideLayout.addWidget(normalizeButton, 1, 0) bakeButton = QPushButton('Bake') guideLayout.addWidget(bakeButton, 1, 1, 1, 2) # Description section scrollArea = QScrollArea() scrollArea.setWidgetResizable(True) mainLayout.addWidget(scrollArea) scrollWidget = QWidget() scrollWidget.setContentsMargins(0, 0, 0, 0) scrollArea.setWidget(scrollWidget) scrollLayout = QVBoxLayout() scrollWidget.setLayout(scrollLayout) collections = xg.palettes() for collection in collections: descriptions = xg.descriptions(collection) for description in descriptions: descriptionWidget = DescriptionWidget(collection, description) scrollLayout.addWidget(descriptionWidget) # Connections addGuideAction.triggered.connect(lambda: pm.mel.eval('XgGuideTool;')) sculptGuideAction.triggered.connect( lambda: xgui.createDescriptionEditor(False).guideSculptContext( False)) convertToPolyAction.triggered.connect(XGenManager.showWarningDialog) minusButton.clicked.connect( lambda: XGenManager.editNumGuideCP('decrease')) plusButton.clicked.connect( lambda: XGenManager.editNumGuideCP('increase')) normalizeButton.clicked.connect( lambda: pm.mel.eval('xgmNormalizeGuides();')) bakeButton.clicked.connect( lambda: pm.mel.eval('xgmBakeGuideVertices;'))
class MayaSessionCollector(HookBaseClass): """ Collector that operates on the maya session. Should inherit from the basic collector hook. """ @property def settings(self): """ Dictionary defining the settings that this collector expects to receive through the settings parameter in the process_current_session and process_file methods. A dictionary on the following form:: { "Settings Name": { "type": "settings_type", "default": "default_value", "description": "One line description of the setting" } The type string should be one of the data types that toolkit accepts as part of its environment configuration. """ # grab any base class settings collector_settings = super(MayaSessionCollector, self).settings or {} # settings specific to this collector maya_session_settings = { "Work Template": { "type": "template", "default": None, "description": "Template path for artist work files. Should " "correspond to a template defined in " "templates.yml. If configured, is made available" "to publish plugins via the collected item's " "properties. ", }, } # update the base settings with these settings collector_settings.update(maya_session_settings) return collector_settings def process_current_session(self, settings, parent_item): """ Analyzes the current session open in Maya and parents a subtree of items under the parent_item passed in. :param dict settings: Configured settings for this collector :param parent_item: Root item instance """ path = cmds.file(query=True, sn=True) if not path: em = "Please save the scene first." self.logger.error(em) raise Exception(em) filename = os.path.basename(path) isProxy = False if "RSProxyRig" in filename: isProxy = True # create an item representing the current maya session item = self.collect_current_maya_session(settings, parent_item) project_root = item.properties["project_root"] context = item.context # self.logger.debug("collector:session----%s----" % context) self.logger.debug("collector:session----%s----" % context.task) # look at the render layers to find rendered images on disk self.collect_rendered_images(item) step_id = context.step.get('id') # self.logger.debug("step_id:---%s---" % step_id) # if we can determine a project root, collect other files to publish if project_root: self.logger.info("Current Maya project is: %s." % (project_root, ), extra={ "action_button": { "label": "Change Project", "tooltip": "Change to a different Maya project", "callback": lambda: mel.eval('setProject ""') } }) # self.collect_playblasts(item, project_root) if step_id == 138: self._collect_xgen(item, project_root) self._collect_xgen_shader(item) self._collect_xgen_geometry(item) else: self.logger.info("Could not determine the current Maya project.", extra={ "action_button": { "label": "Set Project", "tooltip": "Set the Maya project", "callback": lambda: mel.eval('setProject ""') } }) if step_id in [106, 35]: self._collect_cameras(item) if step_id in [15]: if not isProxy: self._collect_meshes(item) # if step_id in [14,15]: # self._collect_assembly(item) if step_id in [16, 136]: self._collect_fbx_geometry(item) # self._collect_uvmap(item) if step_id in [143]: self._collect_simcrv(item) self._collect_lightrig(item) # print "ISASSEMBLY:",ISASSEMBLY if step_id not in [138, 150, 155]: if cmds.ls(geometry=True, noIntermediate=True): # if not ISASSEMBLY: if not isProxy: self._collect_session_geometry(item) if project_root: # if not ISASSEMBLY: if not isProxy: self.collect_alembic_caches(item, project_root) def collect_current_maya_session(self, settings, parent_item): """ Creates an item that represents the current maya session. :param parent_item: Parent Item instance :returns: Item of type maya.session """ publisher = self.parent # get the path to the current file path = cmds.file(query=True, sn=True) # determine the display name for the item if path: file_info = publisher.util.get_file_path_components(path) display_name = file_info["filename"] else: display_name = "Current Maya Session" # create the session item for the publish hierarchy session_item = parent_item.create_item("maya.session", "Maya Session", display_name) # get the icon path to display for this item icon_path = os.path.join(self.disk_location, os.pardir, "icons", "maya.png") session_item.set_icon_from_path(icon_path) # discover the project root which helps in discovery of other # publishable items project_root = cmds.workspace(q=True, rootDirectory=True) session_item.properties["project_root"] = project_root # if a work template is defined, add it to the item properties so # that it can be used by attached publish plugins work_template_setting = settings.get("Work Template") if work_template_setting: work_template = publisher.engine.get_template_by_name( work_template_setting.value) # store the template on the item for use by publish plugins. we # can't evaluate the fields here because there's no guarantee the # current session path won't change once the item has been created. # the attached publish plugins will need to resolve the fields at # execution time. session_item.properties["work_template"] = work_template self.logger.debug("Work template defined for Maya collection.") self.logger.info("Collected current Maya scene") return session_item def collect_alembic_caches(self, parent_item, project_root): """ Creates items for alembic caches Looks for a 'project_root' property on the parent item, and if such exists, look for alembic caches in a 'cache/alembic' subfolder. :param parent_item: Parent Item instance :param str project_root: The maya project root to search for alembics """ # ensure the alembic cache dir exists # print "parent_item:",parent_item.to_dict() # modify abc folder like this: .../cache/alembic/{shot_name} # publisher = self.parent # # # get the path to the current file # path = cmds.file(query=True, sn=True) # # # determine the display name for the item # if path: # shot_version_name = getCurrentShotName(path) # else: # shot_version_name = "untitled" # cache_dir = os.path.join(project_root, "cache", "alembic",shot_version_name) # if not os.path.exists(cache_dir): # return # # self.logger.info( # "Processing alembic cache folder: %s" % (cache_dir,), # extra={ # "action_show_folder": { # "path": cache_dir # } # } # ) from func import shotgun_func, _shotgun_server, replace_special_character as rsc reload(shotgun_func) scene_data = shotgun_func.getSceneSGData() current_id = scene_data.get('entity').get('id') current_entity_type = scene_data.get('entity').get('type') sg = _shotgun_server._shotgun() publish_files = sg.find( "PublishedFile", [['entity.%s.id' % current_entity_type, 'is', current_id]], ['published_file_type', 'path']) abc_publish_files = [] for pf in publish_files: if pf.get('published_file_type').get('name') == "Alembic Cache": _path = pf.get('path').get('local_path_windows') if "\\cache\\alembic" not in _path: continue if _path not in abc_publish_files: abc_publish_files.append( rsc.replaceSpecialCharacter(_path)) print abc_publish_files cache_dir = os.path.join(project_root, "cache", "alembic") if not os.path.exists(cache_dir): return self.logger.info("Processing alembic cache folder: %s" % (cache_dir, ), extra={"action_show_folder": { "path": cache_dir }}) # look for alembic files in the cache folder for filename in os.listdir(cache_dir): cache_path = os.path.join(cache_dir, filename) cache_path = rsc.replaceSpecialCharacter(cache_path) # do some early pre-processing to ensure the file is of the right # type. use the base class item info method to see what the item # type would be. item_info = self._get_item_info(filename) if item_info["item_type"] != "file.alembic": continue if cache_path in abc_publish_files: continue # allow the base class to collect and create the item. it knows how # to handle alembic files item = super(MayaSessionCollector, self)._collect_file(parent_item, cache_path) item._expanded = False item._active = True def _collect_session_geometry(self, parent_item): """ Creates items for session geometry to be exported. :param parent_item: Parent Item instance """ geo_item = parent_item.create_item("maya.session.geometry", "Geometry", "All Session Geometry") # get the icon path to display for this item icon_path = os.path.join(self.disk_location, os.pardir, "icons", "geometry.png") geo_item.set_icon_from_path(icon_path) geo_item._expanded = False # geo_item._active = False def collect_playblasts(self, parent_item, project_root): """ Creates items for quicktime playblasts. Looks for a 'project_root' property on the parent item, and if such exists, look for movie files in a 'movies' subfolder. :param parent_item: Parent Item instance :param str project_root: The maya project root to search for playblasts """ movie_dir_name = None # try to query the file rule folder name for movies. This will give # us the directory name set for the project where movies will be # written if "movie" in cmds.workspace(fileRuleList=True): # this could return an empty string movie_dir_name = cmds.workspace(fileRuleEntry='movie') if not movie_dir_name: # fall back to the default movie_dir_name = "movies" # ensure the movies dir exists movies_dir = os.path.join(project_root, movie_dir_name) if not os.path.exists(movies_dir): return self.logger.info("Processing movies folder: %s" % (movies_dir, ), extra={"action_show_folder": { "path": movies_dir }}) # look for movie files in the movies folder # get max version file: import re version = 0 max_file = "" pattern = "\w+_[A-Za-z]+\.v\d+\.mov" pattern2 = "\w+_[A-Za-z]+\.v(\d+)\.mov" for filename in os.listdir(movies_dir): item_info = self._get_item_info(filename) if item_info["item_type"] != "file.video": continue if re.match(pattern, filename): num = int(re.findall(pattern2, filename)[0]) if num > version: version = num max_file = filename if not max_file: return max_file_path = os.path.join(movies_dir, max_file) item = super(MayaSessionCollector, self)._collect_file(parent_item, max_file_path) # the item has been created. update the display name to include # the an indication of what it is and why it was collected item.name = os.path.splitext(max_file)[0] item.name = "%s (%s)" % (item.name, "playblast") item._expanded = False # item._active = False def collect_rendered_images(self, parent_item): """ Creates items for any rendered images that can be identified by render layers in the file. :param parent_item: Parent Item instance :return: """ scene = cmds.file(q=True, sn=True) basename = os.path.basename(scene) _name, ext = os.path.splitext(basename) work_dir = cmds.workspace(q=True, sn=True) image_dir = work_dir + '/images' # get a list of render layers not defined in the file render_layers = [] _render = cmds.getAttr("defaultRenderGlobals.currentRenderer") # _prefix = cmds.getAttr("vraySettings.fileNamePrefix") for layer_node in cmds.ls(type="renderLayer"): try: # if this succeeds, the layer is defined in a referenced file cmds.referenceQuery(layer_node, filename=True) except RuntimeError: # runtime error means the layer is defined in this session render_layers.append(layer_node) # iterate over defined render layers and query the render settings for # information about a potential render for layer in render_layers: self.logger.info("Processing render layer: %s" % (layer, )) # use the render settings api to get a path where the frame number # spec is replaced with a '*' which we can use to glob (frame_glob, ) = cmds.renderSettings(genericFrameImageName="*", fullPath=True, layer=layer) if _render == "vray": try: mel.eval("unifiedRenderGlobalsWindow;") cmds.workspaceControl("unifiedRenderGlobalsWindow", e=True, vis=0, r=True) fileprefix = cmds.getAttr('vraySettings.fileNamePrefix') _image_format = cmds.getAttr("vraySettings.imageFormatStr") if fileprefix == '<Scene>/<Layer>/<Scene>': image_file = image_dir + '/' + _name + '/' + layer + '/' + _name + '*.%s' % _image_format frame_glob = image_file except: pass # see if there are any files on disk that match this pattern rendered_paths = glob.glob(frame_glob) self.logger.debug("rendered_paths: ----%s----" % rendered_paths) if rendered_paths: # we only need one path to publish, so take the first one and # let the base class collector handle it item = super(MayaSessionCollector, self)._collect_file(parent_item, rendered_paths[0], frame_sequence=True) # the item has been created. update the display name to include # the an indication of what it is and why it was collected item.name = "%s (Render Layer: %s)" % (item.name, layer) item._expanded = False item._active = False def _collect_meshes(self, parent_item): """ Collect mesh definitions and create publish items for them. :param parent_item: The maya session parent item """ # build a path for the icon to use for each item. the disk # location refers to the path of this hook file. this means that # the icon should live one level above the hook in an "icons" # folder. icon_path = os.path.join(self.disk_location, os.pardir, "icons", "mesh.png") # iterate over all top-level transforms and create mesh items # for any mesh. context = parent_item.context for object in cmds.ls(assemblies=True): if not cmds.ls(object, dag=True, type="mesh"): # ignore non-meshes continue # create a new item parented to the supplied session item. We # define an item type (maya.session.mesh) that will be # used by an associated shader publish plugin as it searches for # items to act upon. We also give the item a display type and # display name (the group name). In the future, other publish # plugins might attach to these mesh items to publish other things # object = object.replace(":","_") mesh_item = parent_item.create_item("maya.session.mesh", "Shader", object) # set the icon for the item mesh_item.set_icon_from_path(icon_path) # finally, add information to the mesh item that can be used # by the publish plugin to identify and export it properly mesh_item.properties["object"] = object mesh_item._expanded = False mesh_item._active = False # if step is shading , active is True. if context.step.get('id') == 15: mesh_item._active = True def _collect_cameras(self, parent_item): """ Creates items for each camera in the session. :param parent_item: The maya session parent item """ # build a path for the icon to use for each item. the disk # location refers to the path of this hook file. this means that # the icon should live one level above the hook in an "icons" # folder. self.logger.debug("Camera publish...") icon_path = os.path.join(self.disk_location, os.pardir, "icons", "camera.png") # iterate over each camera and create an item for it for camera_shape in cmds.ls(cameras=True): # try to determine the camera display name try: camera_name = cmds.listRelatives(camera_shape, parent=True)[0] except Exception: # could not determine the name, just use the shape camera_name = camera_shape # create a new item parented to the supplied session item. We # define an item type (maya.session.camera) that will be # used by an associated camera publish plugin as it searches for # items to act upon. We also give the item a display type and # display name. In the future, other publish plugins might attach to # these camera items to perform other actions cam_item = parent_item.create_item("maya.session.camera", "Camera", camera_name) # set the icon for the item cam_item.set_icon_from_path(icon_path) # store the camera name so that any attached plugin knows which # camera this item represents! cam_item.properties["camera_name"] = camera_name cam_item.properties["camera_shape"] = camera_shape def _collect_uvmap(self, parent_item): # if the step is uv ,display these items self.logger.info("uv map publish...") icon_path = os.path.join(self.disk_location, os.pardir, "icons", "uvmap.png") objects = set() meshs = cmds.ls(type="mesh") for m in meshs: parent = cmds.listRelatives(m, p=True)[0] # parent = parent.replace(":", "_") # parent = parent.replace("_", "") objects.add(parent) for obj in objects: uv_item = parent_item.create_item("maya.session.uvmap", "UVMap", obj) uv_item.set_icon_from_path(icon_path) uv_item.properties["uvmap_name"] = obj file_name = obj.replace(":", "_") uv_item.properties["uvmap_file_name"] = file_name uv_item._expanded = False # uv_item._active = False def _collect_xgen(self, parent_item, project_root): try: import xgenm as xg except Exception, e: self.logger.debug(e) return self.logger.debug("XGen publish...") icon_path = os.path.join(self.disk_location, os.pardir, "icons", "xgen.png") # check xgmPalette node in scene collections = xg.palettes() if not collections: return xgen_dir_name = "xgen/collections" xgen_dir = os.path.join(project_root, xgen_dir_name) if not os.path.exists(xgen_dir): return self.logger.info("Processing xgen folder: %s" % (xgen_dir, ), extra={"action_show_folder": { "path": xgen_dir }}) for collection in collections: collection_path = os.path.join(xgen_dir, collection) self.logger.debug("collection:%s" % collection) if not os.path.isdir(collection_path): continue xgen_item = parent_item.create_item("maya.session.xgen", "XGen", collection) # xgen_item.name = "%s (%s)" % (xgen_item.name, "XGen") xgen_item.set_icon_from_path(icon_path) xgen_item.properties['collection_path'] = collection_path xgen_item.properties['collection'] = collection xgen_item._expanded = False
xgen_item.properties['collection_path'] = collection_path xgen_item.properties['collection'] = collection xgen_item._expanded = False # item._active = False def _collect_xgen_shader(self, parent_item): try: import xgenm as xg except Exception, e: self.logger.debug(e) return icon_path = os.path.join(self.disk_location, os.pardir, "icons", "XGen.png") for collection in xg.palettes(): xgen_item = parent_item.create_item("maya.session.xgshader", "XGen Shader", collection + "_Shader") # set the icon for the item xgen_item.set_icon_from_path(icon_path) xgen_item.properties["collection"] = collection xgen_item._expanded = False xgen_item._active = True def _collect_xgen_geometry(self, parent_item): try: import xgenm as xg
def list_palettes(): """Return all palettes in scene""" return list(xg.palettes())
def get_descriptions(): collections = xgen.palettes() needed_collection = collections[0] descriptions = xgen.descriptions(needed_collection) return descriptions
# import collections for geo in geoCollection.keys(): cmds.select(cmds.ls('*' + geo, r=1)[0], r=1) cmds.setAttr(cmds.ls(sl=1)[0] + '.v', 0) xg.importPalette(geoCollection[geo], [], '') # get abc for disc in hairCacheDisc: xg.setAttr('cacheFileName', str(hairSimRoot + cutId + '/' + disc + '.abc'), hairColl, disc, 'SplinePrimitive') xg.setAttr('useCache', 'true', hairColl, disc, 'SplinePrimitive') xg.setAttr('liveMode', 'false', hairColl, disc, 'SplinePrimitive') # set renderer for collection in xg.palettes(): for disc in xg.descriptions(collection): xg.setAttr('renderer', 'VRay', collection, disc, 'RendermanRenderer') # update ui de = xgg.DescriptionEditor de.refresh('Full') # assign shader hairGrp = [ 'hairA3', 'hairA4', 'hairA5', 'hairA6', 'hairA14', 'assassin1', 'assassin2' ] browlashGrp = ['lash1', 'lash2', 'lash3', 'lashBottom1'] cmds.select(hairGrp, r=1) cmds.hyperShade(a='VRayHair_HairRed')
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
# import collections for geo in geoCollection.keys(): cmds.select(cmds.ls('*' + geo, r= 1)[0], r= 1) cmds.setAttr(cmds.ls(sl= 1)[0] + '.v', 0) xg.importPalette( geoCollection[geo], [], '' ) # get abc for disc in hairCacheDisc: xg.setAttr( 'cacheFileName', str(hairSimRoot + cutId + '/' + disc + '.abc'), hairColl, disc, 'SplinePrimitive') xg.setAttr( 'useCache', 'true', hairColl, disc, 'SplinePrimitive') xg.setAttr( 'liveMode', 'false', hairColl, disc, 'SplinePrimitive') # set renderer for collection in xg.palettes(): for disc in xg.descriptions(collection): xg.setAttr( 'renderer', 'VRay', collection, disc, 'RendermanRenderer') # update ui de = xgg.DescriptionEditor de.refresh('Full') # assign shader hairGrp = ['hairA3', 'hairA4', 'hairA5', 'hairA6', 'hairA14', 'assassin1', 'assassin2'] browlashGrp = ['lash1', 'lash2', 'lash3', 'lashBottom1'] cmds.select(hairGrp, r= 1) cmds.hyperShade(a= 'VRayHair_HairRed') cmds.select(browlashGrp, r= 1)
def update_collections(self, flag=False): if not self.ui_collection: return self.ui_collection.set_items(xg.palettes())