def _on_sync_all_assets_of_type(self, asset_type, ask=True): """ Synchronizes all the assets of a given type :param asset_type: str :param ask: bol """ assets_to_sync = artellapipe.AssetsMgr().get_assets_by_type(asset_type) if not assets_to_sync: LOGGER.warning('No Assets found of type "{}" to sync!'.format(asset_type)) return total_assets = len(assets_to_sync) if ask: result = qtutils.show_question( None, 'Synchronizing All {} Assets ({})'.format(asset_type, total_assets), 'Are you sure you want to synchronize all {} assets ({})? This can take lot of time!'.format( asset_type, total_assets)) if result == QMessageBox.No: return for asset in assets_to_sync: asset.sync(sync_type=defines.ArtellaFileStatus.ALL) self.show_ok_message('All assets have been synced!')
def update_thumbnail_icon(self, force=False): """ Function that updates the thumbnail icon :return: """ try: thumbnail_path = self.get_thumbnail_path() if thumbnail_path and os.path.isfile(thumbnail_path) and not force: thumb_icon = QIcon(QPixmap(thumbnail_path)) self._asset_btn.setIcon(thumb_icon) self._thumbnail_icon = thumb_icon return thumb_icon else: self._thumbnail_icon = tpDcc.ResourcesMgr().icon( artellapipe.AssetsMgr().get_default_asset_thumb()) self._asset_btn.setIcon(self._thumbnail_icon) asset_thumbnail_path = self._asset.get_thumbnail_path() if not asset_thumbnail_path: return self._thumbnail_icon self._worker_started = True self._worker.set_path(thumbnail_path) self._worker.set_force(force) self._worker.set_preview_id(asset_thumbnail_path) self.ThreadPool.start(self._worker) return self._thumbnail_icon except Exception as exc: LOGGER.error('Impossible to update thumbnail icon: {} | {}'.format( exc, traceback.format_exc()))
def change_category(self, category=None): """ Changes the category assets that are being showed by the viewer :param category: str """ if not category: category = defines.ArtellaFileStatus.ALL if category != defines.ArtellaFileStatus.ALL and category not in artellapipe.AssetsMgr().get_asset_categories(): LOGGER.warning( 'Asset Type {} is not a valid asset type for project {}'.format(category, self._project.name.title())) category = defines.ArtellaFileStatus.ALL self.clear() new_assets = list() for new_asset in reversed(self._assets): if category == defines.ArtellaFileStatus.ALL: new_asset.setVisible(True) new_assets.insert(0, new_asset) else: if new_asset.asset.get_category() == category: new_asset.setVisible(True) new_assets.insert(0, new_asset) else: new_asset.setVisible(False) new_assets.append(new_asset) for new_asset in new_assets: self._add_widget(new_asset)
def get_asset_shaders_to_export(self, asset, return_only_shaders=True, skip_standard_shaders=True): """ Returns a list shaders that should be exported :param asset: :param return_only_shaders: :param skip_standard_shaders: :return: """ shading_file_type = artellapipe.AssetsMgr().get_shading_file_type() file_path = asset.get_file(file_type=shading_file_type, status=defines.ArtellaFileStatus.WORKING, fix_path=True) valid_open = asset.open_file(file_type=shading_file_type, status=defines.ArtellaFileStatus.WORKING) if not valid_open: LOGGER.warning( 'Impossible to open Asset Shading File: {}'.format(file_path)) return None asset_shaders = self.get_asset_shaders( asset=asset, return_only_shaders=return_only_shaders, skip_standard_shaders=skip_standard_shaders) if not asset_shaders: LOGGER.warning( 'No shaders found in current Asset Shading File: {}'.format( file_path)) return None return asset_shaders
def _get_asset_categories(self): """ Returns a list with the asset categories supported :return: list(str) """ return artellapipe.AssetsMgr().get_asset_categories()
def get_path(self): """ Implements abstract get_path function Returns the path of the asset :return: str """ path_template_name = artellapipe.AssetsMgr().config.get( 'data', 'path_template_name') template = artellapipe.FilesMgr().get_template(path_template_name) if not template: LOGGER.warning( 'Impossible to retrieve asset path because template "{}" is not in configuration file' .format(path_template_name)) return None template_dict = { 'project_id': self._project.id, 'project_id_number': self._project.id_number, 'asset_type': self.get_category(), 'asset_name': self.get_name() } asset_path = template.format(template_dict) if not asset_path: LOGGER.warning( 'Impossible to retrieve asset path from template: "{} | {} | {}"' .format(template.name, template.pattern, template_dict)) return None asset_path = os.path.expandvars(asset_path) asset_path = artellapipe.FilesMgr().prefix_path_with_project_path( asset_path) return asset_path
def _init(self): """ Internal function that initializes asset info widget """ if not self._asset_widget: return self._title_breadcrumb.set_items([{ 'text': self._asset_widget.asset.get_name() }]) thumb_icon = self._asset_widget.get_thumbnail_icon() thumb_size = artellapipe.AssetsMgr().config.get('thumb_size') self._asset_icon_lbl.setPixmap( thumb_icon.pixmap(thumb_icon.availableSizes()[-1]).scaled( thumb_size[0], thumb_size[1], Qt.KeepAspectRatio)) self._asset_toolbar = self._create_asset_toolbar() self._status_stack = StatusStack(asset_widget=self._asset_widget) self._status_stack.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._asset_toolbar_layout.addWidget(self._asset_toolbar) self.main_layout.addWidget(self._status_stack)
def get_ocurrences_of_asset_in_shot(self, asset_name, shot_name, force_update=False): """ Returns the number of ocurrences of given asset in given shot :param asset_name: str, name of the asset :param shot_name: str, name of the shot :return: int or None """ if not self._check_project(): return None asset = artellapipe.AssetsMgr().find_asset(asset_name) if not asset: LOGGER.warning( 'Impossible to return occurrences because asset "{}" does not exists!' .format(asset_name)) return None shot = shots.ShotsManager().find_shot(shot_name) if not shot: LOGGER.warning( 'Impossible to return occurrences because shot "{}" does not exists!' .format(shot_name)) return None shot_id = shot.get_id() tracker = artellapipe.Tracker() total_occurrences = tracker.get_occurrences_of_asset_in_shot( shot_id, asset_name, force_update=force_update) return total_occurrences
def get_assets_from_breakdown(self): """ Returns all the assets contained in shot breakdown defined in production tracker :return: list(ArtellaAsset) """ shot_id = self.get_id() return artellapipe.AssetsMgr().get_assets_in_shot(shot_id)
def get_latest_published_versions(self): """ Implements base ArtellaFile get_path function Returns latest published version of file :return: str """ file_path = self.get_path() return artellapipe.AssetsMgr().get_latest_published_versions( file_path, file_type=self.FILE_TYPE)
def get_thumbnail_path(self): """ Returns path where asset thumbnail is located :return: str """ asset_name = self._asset.get_name() return artellapipe.AssetsMgr().get_asset_thumbnail_path( asset_name=asset_name, create_folder=True)
def get_artella_url(self): """ Returns Artella URL of the file :return: str """ assets_relative_path = os.path.relpath(self.get_path(), artellapipe.AssetsMgr().get_assets_path()) assets_url = self._project.get_artella_assets_url() artella_url = '{}{}'.format(assets_url, assets_relative_path) return artella_url
def _on_hires_assets(self): """ Internal function that is called when High Res Assets menubar button is pressed """ scene_assets = artellapipe.AssetsMgr().get_scene_assets() if not scene_assets: return for scene_asset in scene_assets: scene_asset.switch_to_hires()
def _set_path(self, driver, setter, k): """ Sets path to the text widget """ asset_name = driver.currentText() if asset_name: save_path = os.path.join( artellapipe.AssetsMgr().get_assets_path(), "Characters", asset_name, "__working__", "groom", "groom_package.groom") setter.setText(save_path) return setter.setText("")
def get_asset_shaders(self, asset, return_only_shaders=True, skip_standard_shaders=True): """ Returns list of shaders applied to the given asset :param asset: list of dict """ if not asset: return asset_shaders = dict() only_shaders = list() renderable_shapes = artellapipe.AssetsMgr( ).get_asset_renderable_shapes(asset, full_path=False) if not renderable_shapes: LOGGER.warning('No renderable shapes found in asset: "{}"'.format( asset.get_name())) return asset_shaders default_scene_shaders = tp.Dcc.default_shaders() or list() for shape in renderable_shapes: if shape not in asset_shaders: asset_shaders[shape] = dict() shading_groups = tp.Dcc.list_connections_of_type( shape, connection_type='shadingEngine') if not shading_groups: shading_groups = ['initialShadingGroup'] for shading_grp in shading_groups: shading_grp_mat = tp.Dcc.list_materials( nodes=tp.Dcc.list_node_connections(shading_grp)) if skip_standard_shaders: for mat in shading_grp_mat: if mat in default_scene_shaders: continue for mat in shading_grp_mat: if mat not in only_shaders: only_shaders.append(mat) asset_shaders[shape][shading_grp] = shading_grp_mat if not asset_shaders: LOGGER.warning('No shaders found in current Asset: {}'.format( asset.get_name())) return None if return_only_shaders: return only_shaders return asset_shaders
def update_cache(self, force=False): """ Updates internal cache with the current assets located in Artella server """ if self._cache and not force: return self._cache python.clear_list(self._cache) self._cache = artellapipe.AssetsMgr().find_all_assets() or list() return self._cache
def get_thumbnail_path(self): """ Implements abstract get_path function Returns the path where asset thumbnail is located :return: str """ thumb_attr = artellapipe.AssetsMgr().config.get( 'data', 'thumb_attribute') thumb_path = self._asset_data.get(thumb_attr, None) return thumb_path
def get_shaders_paths(self): """ Returns path where shaders are located in the project :return: str """ shaders_paths = self.config.get('paths') return [ path_utils.clean_path( os.path.join(artellapipe.AssetsMgr().get_assets_path(), p)) for p in shaders_paths ]
def replace_by_rig(self, rig_control=None): """ Replaces current asset by its rig file :param rig_control: str :return: """ if not rig_control: rig_control = 'root_ctrl' if self.is_rig(): return rig_file_class = artellapipe.FilesMgr().get_file_class('rig') if not rig_file_class: LOGGER.warning( 'Impossible to reference rig file because Rig File Class (rig) was not found!' ) return node_namespace = tp.Dcc.node_namespace(self.node, clean=True) current_matrix = tp.Dcc.node_matrix(self.node) parent_node = tp.Dcc.node_parent(self.node) self.remove() rig_file = rig_file_class(self.asset) ref_nodes = rig_file.import_file(reference=True, namespace=node_namespace, unique_namespace=False) if not ref_nodes: LOGGER.warning( 'No nodes imported into current scene for rig file!') return None root_ctrl = None for node in ref_nodes: root_ctrl = utils.get_control(node=node, rig_control=rig_control) if root_ctrl: break if not root_ctrl: return False tp.Dcc.set_node_matrix(root_ctrl, current_matrix) if parent_node and tp.Dcc.object_exists(parent_node): asset_node = artellapipe.AssetsMgr().get_asset_node_in_scene( root_ctrl) if not asset_node: return tp.Dcc.set_parent(asset_node.node, parent_node) return True
def _setup_synchronize_menu(self): """ Internal function that creates the synchronize menu """ sync_menu = QMenu(self) sync_icon = tpDcc.ResourcesMgr().icon('sync') for asset_type in artellapipe.AssetsMgr().get_asset_types(): action_icon = tpDcc.ResourcesMgr().icon(asset_type.lower()) if action_icon: sync_action = QAction(action_icon, asset_type.title(), self) else: sync_action = QAction(asset_type.title(), self) sync_menu.addAction(sync_action) asset_file_types = artellapipe.AssetsMgr().get_asset_type_files(asset_type=asset_type) or list() if asset_file_types: asset_files_menu = QMenu(sync_menu) sync_action.setMenu(asset_files_menu) for asset_file_type in asset_file_types: asset_type_icon = tpDcc.ResourcesMgr().icon(asset_file_type) asset_file_action = QAction(asset_type_icon, asset_file_type.title(), asset_files_menu) asset_files_menu.addAction(asset_file_action) asset_file_template = artellapipe.FilesMgr().get_template(asset_file_type) if not asset_file_template: LOGGER.warning('No File Template found for File Type: "{}"'.format(asset_file_type)) asset_file_action.setEnabled(False) continue asset_file_action.triggered.connect(partial(self._on_sync_file_type, asset_type, asset_file_type)) all_asset_types_action = QAction(sync_icon, 'All', asset_files_menu) all_asset_types_action.triggered.connect(partial(self._on_sync_all_assets_of_type, asset_type)) asset_files_menu.addAction(all_asset_types_action) sync_menu.addSeparator() sync_all_action = QAction(sync_icon, 'All', self) sync_all_action.triggered.connect(self._on_sync_all_types) sync_menu.addAction(sync_all_action) self._synchronize_btn.setMenu(sync_menu)
def __init__(self, asset, text=None, parent=None): self._asset = asset self._text = text or artellapipe.AssetsMgr().get_default_asset_name() self._thumbnail_icon = None super(ArtellaAssetWidget, self).__init__(parent=parent) self._worker = worker.ThumbDownloaderWorker() self._worker.setAutoDelete(False) self._worker.signals.triggered.connect(self._on_thumbnail_from_image) self._worker_started = False self._init()
def _populate_data(self): self.ui.collection_cbx.addItems(self._get_all_collections()) self.ui.renderer_cbx.addItems(["None", "Arnold Renderer"]) self.ui.renderer_cbx.setCurrentIndex(1) self.ui.renderer_mode_cbx.addItems(["Live", "Batch Render"]) self.ui.renderer_mode_cbx.setCurrentIndex(1) self.ui.motion_blur_cbx.addItems(["Use Global Settings", "On", "Off"]) self.ui.extra_depth_sbx.setValue(16) self.ui.extra_samples_sbx.setValue(0) characters_to_set = os.listdir(os.path.join(artellapipe.AssetsMgr().get_assets_path(), "Characters")) characters_to_set.insert(0, "") self.ui.export_character_cbx.addItems(characters_to_set) self.ui.import_character_cbx.addItems(characters_to_set)
def set_id(self, new_id): """ Sets the ID of this asset :param new_id: str """ id_attr = artellapipe.AssetsMgr().config.get('data', 'id_attribute') asset_id = self._asset_data.get(id_attr, None) if not asset_id: LOGGER.warning( 'Impossible to retrieve asset ID because asset data does not contains "{}" attribute.' '\nAsset Data: {}'.format(id_attr, self._asset_data)) return None self._asset_data[id_attr] = new_id
def _open_asset_shaders_file(self): if not self._asset: return shading_file_type = artellapipe.AssetsMgr().get_shading_file_type() file_path = self._asset.get_file( file_type=shading_file_type, status=defines.ArtellaFileStatus.WORKING, fix_path=True) valid_open = self._asset.open_file( file_type=shading_file_type, status=defines.ArtellaFileStatus.WORKING) if not valid_open: LOGGER.warning( 'Impossible to open Asset Shading File: {}'.format(file_path)) return None
def get_tags(self): """ Returns tags of the asset Implements abstract get_tags function :return: list(str) """ tags_attr = artellapipe.AssetsMgr().config.get('data', 'tag_attribute') tags_list = self._asset_data.get(tags_attr, None) if not tags_list: LOGGER.warning( 'Impossible to retrieve tags name because asset data does not contains "{}" attribute.' '\nAsset Data: {}'.format(tags_attr, self._asset_data)) return None return tags_list
def get_id(self): """ Implements abstract get_id function Returns the id of the asset :return: str """ id_attr = artellapipe.AssetsMgr().config.get('data', 'id_attribute') asset_id = self._asset_data.get(id_attr, None) if not asset_id: LOGGER.warning( 'Impossible to retrieve asset ID because asset data does not contains "{}" attribute.' '\nAsset Data: {}'.format(id_attr, self._asset_data)) return None return asset_id.rstrip()
def _on_sync_file_type(self, asset_type, file_type, sync_type=defines.ArtellaFileStatus.ALL): """ Internal callback function that is called when a file is selected from the sync menu :param file_type: str, file type to sync :param sync_type: ArtellaFileStatus, type of sync we want to do """ assets_to_sync = artellapipe.AssetsMgr().get_assets_by_type(asset_type) if not assets_to_sync: LOGGER.warning('No Assets found of type "{}" to sync!'.format(asset_type)) return for asset in assets_to_sync: asset.sync(file_type=file_type, sync_type=defines.ArtellaFileStatus.ALL) self.show_ok_message('Files of type {} has been synced!'.format(file_type))
def get_category(self): """ Implements abstract get_category function Returns the category of the asset :return: str """ category_attr = artellapipe.AssetsMgr().config.get( 'data', 'category_attribute') category = self._asset_data.get(category_attr, None) if not category: LOGGER.warning( 'Impossible to retrieve asset category because asset data does not contains "{}" attribute.' '\nAsset Data: {}'.format(category_attr, self._asset_data)) return category
def _init(self): assets = artellapipe.AssetsMgr().get_scene_assets( allowed_types=self.CATEGORIES, allowed_tags=self.CATEGORIES) or list() for asset in assets: asset_widget = self.OUTLINER_ITEM(asset) # asset_widget.overrideAdded.connect(self._on_override_added) # asset_widget.overrideRemoved.connect(self._on_override_removed) asset_widget.contextRequested.connect(self._on_show_context_menu) asset_widget.clicked.connect(self._on_item_clicked) asset_widget.viewToggled.connect(self._on_toggle_view) self.append_widget(asset_widget) self._widget_tree[asset_widget] = list() overrides = asset.get_overrides() if overrides: for override in overrides: self._add_override(override=override, parent=asset_widget)
def load_scene_shaders(self, status=defines.ArtellaFileStatus.PUBLISHED, apply_shaders=True): """ Loads all shaders of the current assets in the scene :param status: :param apply_shaders: bool :return: """ scene_assets = artellapipe.AssetsMgr().get_scene_assets() if not scene_assets: LOGGER.warning( 'Impossible to load shaders because there are no assets in current scene!' ) for asset in scene_assets: asset.load_shaders(status=status, apply_shaders=apply_shaders)