def get_filenames(url): ret = [] if not os.path.isdir(e(url)): return ret for dirpath, _, _ in os.walk(e(url)): dirpath = u(dirpath.replace('\\', '/')) filenames = nuke.getFileNameList(e(dirpath, 'UTF-8')) filenames = ['{}/{}'.format(dirpath, u(i)) for i in filenames] ret.extend(filenames) return ret
def import_resource(self, dir_path): """Import footages from config dictionary.""" # Get all subdir dirs = list(x[0] for x in os.walk(dir_path)) self.task_step('导入素材') for dir_ in dirs: # Get footage in subdir LOGGER.info('文件夹 %s:', dir_) if not re.match(BATCH_CONFIG['dir_pat'], os.path.basename(dir_.rstrip('\\/'))): LOGGER.info('\t不匹配文件夹正则, 跳过') continue files = nuke.getFileNameList(utf8(dir_)) footages = [ u(i) for i in files if not u(i).endswith(('副本', '.lock')) ] if files else [] if footages: for f in footages: if os.path.isdir(e(os.path.join(dir_, f))): LOGGER.info('\t文件夹: %s', f) continue LOGGER.info('\t素材: %s', f) if re.match(CONFIG['footage_pat'], f, flags=re.I): n = nuke.createNode( 'Read', utf8('file {{{}/{}}}'.format(dir_, f))) n['on_error'].setValue(utf8('nearest frame')) else: LOGGER.info('\t\t不匹配素材正则, 跳过') LOGGER.info('{:-^30s}'.format('结束 导入素材')) if not nuke.allNodes('Read'): raise FootageError(dir_path)
def submit(self, filenames=(), message="", account_id=None): """Submit file to task, then change status to `Check`. Args: pathnames (tuple, optional): Defaults to (). Server pathnames. filenames (tuple, optional): Defaults to (). Local filenames. message (Message, optional): Defaults to "". Submit note(and images). """ select = self.select message = Message.load(message) account_id = account_id or account.get_account_id(select.token) # Create path data. path_data = {'path': [], 'file_path': []} for i in filenames: path_data['path' if os.path.isdir(e(i)) else 'file_path'].append(i) select.call("c_work_flow", "submit", task_id=select[0], account_id=account_id, version_id=self.create_version(filenames), submit_file_path_array=path_data, text=message.dumps())
def upload_image(filename, folder, token): """Upload image to server. Args: filename (str): Filename. folder (str): Server upload folder, usually same with project name. token (str): Server session token. Returns: ImageInfo: Uploaded image information. """ filename = u(filename) basename = os.path.basename(filename) data = post('web_upload_file', { 'folder': folder, 'type': 'project', 'method': 'convert_image', 'filename': basename }, token=token, files={ 'file': (basename, open(e(filename), 'rb'), mimetypes.guess_type(basename)[0]) }) assert isinstance(data, dict), type(data) data['path'] = filename return ImageInfo(**data)
def _fix_dir(context): filename = context['filename'] n = context['node'] if not os.path.isdir(e(filename)): return False is_dropped = dropdata.drop('text/plain', filename) if is_dropped: u_print('修复读取: 文件夹展开: {name}: {filename}'.format(**context)) nuke.delete(n) return is_dropped
def generate_report(cls, shots_info): """Generate batchcomp report. """ assert isinstance(shots_info, dict) env = Environment(loader=PackageLoader(__about__.__name__)) template = env.get_template('batchcomp.html') data = template.render(shots_info=sorted(shots_info.items())) log_path = os.path.join(CONFIG['output_dir'], u'批量合成日志.html') with open(e(log_path), 'w') as f: f.write(data.encode('UTF-8')) return log_path
def walk(path): """(Generator)Walk through path. Ignore `history` forlder. Args: path (str): Path. """ path = e(path) for dirpath, dirnames, filenames in os.walk(path): try: dirnames.remove('history') except ValueError: pass for i in filenames: yield os.path.join(dirpath, i)
def execute(self): """Start task. """ files = self._files for f in progress(files, '分离exr'): cmd = u'"{nuke}" -t "{script}" "{file_path}" "{output_dir}" -f "{file_type}"'.format( nuke=nuke.EXE_PATH, script=__file__, file_path=os.path.join(self.input_dir, f), file_type=self.output_ext, output_dir=self.output_dir) proc = Popen(e(cmd)) proc.wait() webbrowser.open(self.output_dir)
def create_out_dirs(node=None): """Create this read node's output dir if need.""" n = node or nuke.thisNode() try: if n['disable'].value(): return except NameError: pass filename = u(nuke.filename(n)) if filename: target_dir = e(os.path.dirname(filename)) if not os.path.isdir(target_dir): LOGGER.debug('Create dir: %s', target_dir) os.makedirs(target_dir)
def warn_mtime(show_ok=False, since=None): """Show footage that mtime newer than script mtime. """ LOGGER.debug('Check warn_mtime') try: script_name = nuke.scriptName() except RuntimeError: if show_ok: nuke.message(utf8('文件未保存')) return script_mtime = os.path.getmtime(e(script_name)) since = since or script_mtime @run_with_clock('检查素材修改日期') def _get_mtime_info(): ret = {} for n in nuke.allNodes('Read', nuke.Root()): try: mtime = time.mktime( time.strptime(n.metadata('input/mtime'), '%Y-%m-%d %H:%M:%S')) except TypeError: continue if mtime > since: ret[nuke.filename(n)] = mtime ftime = time.strftime('%m-%d %H:%M:%S', time.localtime(mtime)) throtted_warning('{}: [new footage]{}'.format( u(n.name()), ftime)) return ret newer_footages = _get_mtime_info() if not (show_ok or newer_footages): return env = Environment(loader=FileSystemLoader(core.TEMPLATES_DIR)) template = env.get_template('mtime.html') data = [(k, pendulum.from_timestamp(v).diff_for_humans()) for k, v in newer_footages.items()] msg = template.render( script_name=script_name, script_mtime=pendulum.from_timestamp(script_mtime).diff_for_humans(), data=data) nuke.message(utf8(msg))
def __init__(self, parent=None): if self._is_initiated: return controller = control.Controller() controller.was_processed.connect(_handle_result) super(Window, self).__init__( controller, parent) self.resize(*settings.WindowSize) self.setWindowTitle(settings.WindowTitle) with open(e(filetools.module_path("pyblish_lite.css"))) as f: css = u(f.read()) # Make relative paths absolute root = util.get_asset("").replace("\\", "/") css = css.replace("url(\"", "url(\"%s" % root) self.setStyleSheet(css.encode('utf-8')) self.setObjectName('PyblishWindow') self.setAttribute(Qt.WA_DeleteOnClose, True) self._is_initiated = True
def set_writable(select): """Set final files writable. """ for i in get_files(select): os.chmod(e(i), stat.S_IWRITE) LOGGER.info('设为读写: %s', i)
def set_readonly(select): """Set final files readonly. """ for i in get_files(select): os.chmod(e(i), stat.S_IREAD) LOGGER.info('设为只读: %s', i)
def __str__(self): return e(self.__unicode__())
def test_plugin_folder_path(): path = filetools.plugin_folder_path('ToolSets') assert os.path.exists(e(path)), path
def __init__(self, nodes, renderer='redshift', async_=True): assert nodes, 'Can not precomp without node.' def _get_filename(n): return n.metadata('input/filename') or nuke.filename(n) or '' config_file = wlf_module_path('data', 'precomp.{}.json'.format(renderer)) with open(e(config_file)) as f: self._config = json.load(f) self._combine_dict = dict(self._config.get('combine')) self._translate_dict = dict(self._config.get('translate')) if isinstance(nodes, nuke.Node): nodes = [nodes] elif len(nodes) > 1: nodes = list(n for n in nodes if n.Class() == 'Read') # Record node for every source layer. self.source = {} for n in nodes: path = PurePath(_get_filename(n)) path.layers = self._config['layers'] layer = path.layer _layer = self.l10n(layer) _label = u(n['label'].value()) if _layer not in _label: n['label'].setValue('{}\n{}'.format( _label, _layer).strip().encode('utf-8')) if layer: self.source[layer] = n else: self.source['beauty'] = n if len(self.source) == 1: n = sorted(nodes, key=lambda n: (len(nuke.layers(n)), len(_get_filename(n)) * -1), reverse=True)[0] layers = nuke.layers(n) LOGGER.debug('Precomp single node that has this layers:\n%s', layers) self.source = { layer: True for layer in layers if layer in self._config['layers'] } self.source['beauty'] = n self.last_node = n LOGGER.debug('Source layers:\n%s', self.source.keys()) self.last_node = self.node('beauty') for layer in self._config.get('copy'): for i in self.source.keys(): if re.match('(?i)^{}\\d*$'.format(layer), i): self.copy(i) for layer, output in dict(self._config.get('rename')).items(): self.copy(layer, output) # Plus nodes. dot_node = nuke.nodes.Dot(inputs=(self.last_node, )) remove_node = nuke.nodes.Remove(inputs=(dot_node, ), channels='rgb') self.last_node = remove_node for layer in self._config.get('plus'): self.plus(layer) # Precomp Switch. kwargs = { 'which': '{{[python {__PrecompSwitch.get_which(nuke.thisNode())}]}}', 'inputs': [dot_node, self.last_node], 'label': '预合成自动开关', 'onCreate': inspect.getsource(PrecompSwitch) + """ __PrecompSwitch.init(nuke.thisNode())""" } setattr(sys.modules['__main__'], '__PrecompSwitch', PrecompSwitch) if self.last_node is remove_node: kwargs['disable'] = True self.last_node = PrecompSwitch.init( nuke.nodes.Switch(**utf8_dict(kwargs))) replace_node(dot_node.input(0), self.last_node) autoplace(self.last_node, recursive=True, undoable=False, async_=async_)