def autoplace(nodes=None, recursive=False, undoable=True, async_=None): """Auto place nodes.""" if async_ is None: async_ = DEBUG # Executing check if not LOCK.acquire(False): msg = u'不能同时进行两个自动摆放' nuke.message(utf8(msg)) LOGGER.warning(msg) return LOCK.release() # Args check nodes = nuke.allNodes() if not nodes else nodes if not nodes: return elif async_ and nuke.GUI and not DEBUG: return run_async(autoplace)(nodes, recursive, undoable, async_=False) # Call worker nodes = [nodes] if isinstance(nodes, nuke.Node) else nodes nodes = get_upstream_nodes( nodes, flags=nuke.INPUTS).union(nodes) if recursive else nodes nodes = Nodes(nodes) with LOCK: try: manager = Manager(nodes) manager.autoplace() except: LOGGER.error('Unexcepted excepitoion during autoplace.', exc_info=True) raise
def _update_missing_frame(self): ret = FrameRanges([]) checked = set() frames = self.frame_ranges.toFrameList() def _check(frame): try: path = Path(self.filename.with_frame(frame)) if path in checked: return if not path.is_file(): ret.add([frame]) checked.add(path) except OSError as ex: LOGGER.error(os.strerror(ex.errno), exc_info=True) pool = multiprocessing.Pool() pool.map(_check, frames) pool.close() pool.join() ret.compact() self._missing_frames = CachedMissingFrames(ret, time.time()) if ret: msg = '{} 缺帧: {}'.format(self, ret) nuke.warning(utf8(msg)) return ret
def __init__(self): nukescripts.PythonPanel.__init__( self, utf8('批量合成'), 'com.wlf.batchcomp') self._shot_list = None self.cfg = BatchCompConfig().read() for i in self.knob_list: k = i[0](*iutf8(i[1:])) try: k.setValue(utf8(self.cfg.get(i[1]))) except TypeError: pass self.addKnob(k) for i in ('exclude_existed',): self.knobs()[i].setFlag(nuke.STARTLINE) self.knobs()['generate_txt'].setLabel( utf8('生成 {}.txt'.format(self.txt_name)))
def _info(): info = '测试' if files: info = '# 共{}个素材\n'.format(len(files)) info += '\n'.join(files) else: info = '找不到素材' self.knobs()['info'].setValue(utf8(info))
def _add_colorcorrect_nodes(self, input_node): tag = input_node.metadata(self.tag_metadata_key) n = input_node # if CONFIG['autograde']: # if get_max(input_node, 'depth.Z') > 1.1: # n['farpoint'].setValue(10000) n = nuke.nodes.Unpremult(inputs=[n], label=b'调色开始') # if CONFIG['autograde']: # LOGGER.info('{:-^30s}'.format('开始 自动亮度')) # n = nuke.nodes.Grade( # inputs=[n], # unpremult='rgba.alpha', # label='白点: [value this.whitepoint]\n混合:[value this.mix]\n使亮度范围靠近0-1' # ) # _max = self._autograde_get_max(input_node) # n['whitepoint'].setValue(_max) # n['mix'].setValue(0.3 if _max < 0.5 else 0.6) # LOGGER.info('{:-^30s}'.format('结束 自动亮度')) if CONFIG['colorcorrect']: n = nuke.nodes.ColorCorrect(inputs=[n], disable=True) n = nuke.nodes.RolloffContrast(inputs=[n], channels='rgb', contrast=2, center=0.001, soft_clip=1, disable=True) if tag and tag.startswith('BG'): kwargs = {'in': 'depth', 'label': '远处'} input_mask = nuke.nodes.PositionKeyer(inputs=[n], **utf8_dict(kwargs)) n = nuke.nodes.ColorCorrect(inputs=[n, input_mask], disable=True) n = nuke.nodes.Grade(inputs=[n, input_mask], black=0.05, black_panelDropped=True, label=utf8('深度雾'), disable=True) kwargs = {'in': 'depth', 'label': '近处'} input_mask = nuke.nodes.PositionKeyer(inputs=[n], **utf8_dict(kwargs)) n = nuke.nodes.ColorCorrect(inputs=[n, input_mask], disable=True) n = nuke.nodes.RolloffContrast(inputs=[n, input_mask], channels='rgb', contrast=2, center=0.001, soft_clip=1, disable=True) n = self._attenuation_adjust(n) n = nuke.nodes.Premult(inputs=[n], label=b'调色结束') return n
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 _info(): _info = u'测试' self._shot_list = list(self.batchcomp.get_shot_list()) if self._shot_list: _info = u'# 共{}个镜头\n'.format(len(self._shot_list)) _info += u'\n'.join(self._shot_list) else: _info = u'找不到镜头' self.knobs()['info'].setValue(utf8(_info))
def _gizmo_to_group_update_ui(): n = nuke.thisNode() _temp_knob_name = 'wlf_gizmo_to_group' _has_temp_knob = nuke.exists( utf8('{}.{}'.format(u(n.name()), _temp_knob_name))) if _has_temp_knob: n = edit.gizmo_to_group(n) n.removeKnob(n[_temp_knob_name]) n.removeKnob(n['User'])
def _add_zdefocus_control(input_node): # Use for one-node zdefocus control n = nuke.nodes.ZDefocus2(inputs=[input_node], math='depth', output='focal plane setup', center=0.00234567, blur_dof=False, label=utf8('** 虚焦总控制 **\n在此拖点定虚焦及设置')) n.setName('_ZDefocus') return n
def use_relative_path(nodes): """Convert given nodes's file knob to relative path.""" if isinstance(nodes, nuke.Node): nodes = [nodes] proj_dir = PurePath(nuke.value('root.project_directory')) for n in nodes: try: path = PurePath(n['file'].value()) n['file'].setValue(utf8(path.relative_to(proj_dir).as_posix())) except NameError: continue
def node(self, layer): """Return a node that should be treat as @layer. """ add_layer(layer) ret = self.source.get(layer) if layer in self.layers(): kwargs = { 'inputs': (self.last_node, ), 'in': layer, 'label': '修改日期: [metadata input/mtime]\n{}'.format(self.l10n(layer)) } try: kwargs['postage_stamp'] = self.last_node[ 'postage_stamp'].value() except NameError: pass ret = nuke.nodes.Shuffle(**utf8(kwargs)) elif layer in self._combine_dict.keys(): pair = self._combine_dict[layer] if self.source.get(pair[0])\ and self.source.get(pair[1]): LOGGER.debug('Combine for layer: %s, %s -> %s', pair[0], pair[1], layer) input0, input1 = self.node(pair[0]), self.node(pair[1]) kwargs = { 'inputs': [input0, input1], 'operation': 'multiply', 'output': 'rgb', 'label': self.l10n(layer) } try: kwargs['postage_stamp'] = (input0['postage_stamp'].value() and input1['postage_stamp'].value()) except NameError: pass n = nuke.nodes.Merge2(**utf8_dict(kwargs)) self.source[layer] = n ret = n else: LOGGER.debug('Source not enough: %s', self.source.keys()) if not ret: LOGGER.debug('Can not get node for layer:%s', layer) return ret
def plus(self, layer): """Plus a layer to last rgba. """ input1 = self.node(layer) if not input1: return LOGGER.debug('Plus layer to last:%s', layer) if not self.last_node: self.last_node = nuke.nodes.Constant() if layer not in self.layers(): input1 = nuke.nodes.Shuffle(inputs=[input1], out=layer) self.last_node = nuke.nodes.Merge2( inputs=[self.last_node, input1], operation='plus', also_merge=layer if layer not in self.layers() else 'none', label=utf8(self.l10n(layer)), output='rgb')
def _bg_ch_nodes(self): nodes = self._precomp() if not nodes: raise FootageError('BG', 'CH') for i, n in enumerate(nodes): self.task_step('创建{}'.format( n.metadata(self.tag_metadata_key) or n.name())) n = self._prepare_channels(n) n = self._add_colorcorrect_nodes(n) if i == 0: self.task_step('创建MP') n = self._merge_mp(n, mp_file=CONFIG['mp'], lut=CONFIG.get('mp_lut')) n = self._merge_occ(n) n = self._merge_shadow(n) n = self._merge_screen(n) n = self._add_filter_nodes(n) if i == 0: n = nuke.nodes.ModifyMetaData( inputs=[n], metadata='{{set {} main}}'.format(self.tag_metadata_key), label=utf8('主干开始')) if i > 0: n = nuke.nodes.Merge2(inputs=[nodes[i - 1], n], label=n.metadata(self.tag_metadata_key) or '') nodes[i] = n return n
def dialog_create_dirs(): """A dialog for create dirs from cgtwq. """ folder_input_name = b'输出文件夹' database_input_name = b'数据库' prefix_input_name = b'镜头名前缀限制' panel = nuke.Panel(b'为项目创建文件夹') panel.addSingleLineInput(database_input_name, 'proj_qqfc_2017') panel.addSingleLineInput(prefix_input_name, '') panel.addFilenameSearch(folder_input_name, 'E:/temp') confirm = panel.show() if not confirm: return try: database = panel.value(database_input_name) save_path = panel.value(folder_input_name) prefix = panel.value(prefix_input_name) for _ in progress(['连接CGTeamWork...', ], '创建文件夹'): try: select = cgtwq.Database(database)['shot_task'].filter( cgtwq.Field('pipeline') == '合成') except cgtwq.IDError as ex: nuke.message(utf8('找不到对应条目\n{}'.format(ex))) return for name in progress(select['shot.shot'], '创建文件夹'): if not name or not name.startswith(prefix): continue _path = os.path.join(save_path, name) if not os.path.exists(_path): os.makedirs(_path) webbrowser.open(save_path) except CancelledError: LOGGER.debug('用户取消创建文件夹')
def _autocomp(): try: comp.Comp().create_nodes() except comp.FootageError: nuke.message(utf8('请先导入素材'))
def create_nodes(self): """Create nodes that a comp need.""" self.task_step('分析读取节点') self.setup() self.task_step('创建节点树') self.task_step('合并BG CH') n = self._bg_ch_nodes() if CONFIG['other']: self.task_step('合并其他层') n = self._merge_other(n, self._bg_ch_end_nodes) if CONFIG['depth']: self.task_step('创建整体深度') nodes = nuke.allNodes('DepthFix') n = self._merge_depth(n, nodes) if CONFIG['zdefocus']: self.task_step('添加虚焦控制') try: self._add_zdefocus_control(n) except RuntimeError as ex: LOGGER.error(u(ex)) n = nuke.nodes.Unpremult(inputs=[n], label=utf8('整体调色开始')) n = nuke.nodes.Premult(inputs=[n], label=utf8('整体调色结束')) n = nuke.nodes.Reformat(inputs=[n], resize='none', label=utf8('整体滤镜开始')) n = nuke.nodes.SoftClip(inputs=[n], conversion='logarithmic compress') if CONFIG.get('filters'): n = nuke.nodes.Glow2(inputs=[n], tolerance=0.6, saturation=0.5, size=100, mix=0.25, disable=True) if 'motion' in nuke.layers(n): n = nuke.nodes.VectorBlur2(inputs=[n], uv='motion', scale=1, soft_lines=True, normalize=False, disable=True) n = nuke.nodes.Aberration(inputs=[n], distortion1='0 0 0.003', label=utf8('溢色')) n = nuke.nodes.Reformat(inputs=[n], resize='none', label=utf8('整体滤镜结束')) n = nuke.nodes.wlf_Write(inputs=[n]) n.setName('_Write') self.task_step('输出节点创建') self.task_step('设置查看器') map(nuke.delete, nuke.allNodes('Viewer')) nuke.nodes.Viewer(inputs=[n, n.input(0), n, n]) autoplace(undoable=False)
def custom_autolabel(): ''' add addition information on Node in Gui ''' def _add_to_autolabel(text, center=False): if not isinstance(text, (str, unicode)): return ret = u(autolabel()).split('\n') ret.insert(1, text) ret = '\n'.join(ret).rstrip('\n') if center: ret = ('<div align="center" ' 'style="margin:0px;padding:0px">{}</div>').format(ret) return ret def _keyer(): label = '输入通道 : ' + u(nuke.value('this.input')) ret = _add_to_autolabel(label) return ret def _read(): missing_frames = asset.Footage(this).missing_frames(this) label = ('<style>* {font-family:微软雅黑} ' 'span {color:red} b {color:#548DD4}</style>') label += '<b>帧范围: </b><span>{} - {}</span>'.format( this.firstFrame(), this.lastFrame()) if missing_frames: label += '\n<span>缺帧: {}</span>'.format(missing_frames) label += '\n<b>修改日期: </b>{}'.format(this.metadata('input/mtime')) ret = _add_to_autolabel(label, True) return ret def _shuffle(): channels = dict.fromkeys(['in', 'in2', 'out', 'out2'], '') for i in channels.keys(): channel_value = u(nuke.value('this.' + i)) if channel_value != 'none': channels[i] = channel_value + ' ' label = (channels['in'] + channels['in2'] + '-> ' + channels['out'] + channels['out2']).rstrip(' ') ret = _add_to_autolabel(label) return ret def _timeoffset(): return _add_to_autolabel('{:.0f}'.format(this['time_offset'].value())) this = nuke.thisNode() class_ = this.Class() dict_ = { 'Keyer': _keyer, 'Read': _read, 'Shuffle': _shuffle, 'TimeOffset': _timeoffset } if class_ in dict_: ret = dict_[class_]() if isinstance(ret, unicode): ret = utf8(ret) return ret