Nuke Python 自定義Panel

在nuke中有好幾種創(chuàng)建自定義panel的方法:

  • 簡單的panel命令 -- 常用任務(wù)腮猖,比如讓用戶確認(rèn)或者獲取文件名
  • 簡單panel對象 -- 定制某些擴(kuò)展饮焦,創(chuàng)建簡單闪湾。如果需要一個簡單的定制panel遍膜,可以添加大量knob
  • python panel -- 創(chuàng)建更加復(fù)雜爵赵,提供node中所有的knob,callback洲劣,部分layout控制
簡單panel命令

nuke有大量的簡單panel备蚓,不用繁瑣的定制就能使用课蔬。

  • 消息框
    nuke.message('Just saying hi')


    _images/panel_01.png
    _images/panel_01.png
  • 用戶查詢 給用戶一個“yes、no”選擇:

if nuke.ask('Are you sure you want to create  a Blur node? '):
        nuke.createNode('Blur')
_images/panel_09.png
_images/panel_09.png
  • 顯示窗口
def showChannels():
    return '\n'.join( nuke.thisNode().channels() )

node = nuke.selectedNode()
nuke.display('showChannels()', node, 'show channels for %s' % node.name() )

這是個非模式panel郊尝,運(yùn)行showChannels二跋,用其結(jié)果來填充窗口。node作為第二參數(shù)流昏。

_images/panel_02.png
_images/panel_02.png
  • 獲取用戶輸入-從用戶獲取輸入并賦給所選節(jié)點的label
txt = nuke.getInput('Change label', 'new label')
if txt:
    for n in nuke.selectedNodes():
        n['label'].setValue(txt)
_images/panel_03.png
_images/panel_03.png
  • 顏色選擇:給選定節(jié)點賦予指定顏色
col = nuke.getColor()
if col:
        for n in nuke.selectedNodes():
            n['title_color'].setValue(col)
            n['gl_color'].setValue(col)
_images/panel_04.png
_images/panel_04.png
  • 文件瀏覽扎即,返回文件全路徑:
filePath = nuke.getFilename('get file contents', '*.txt *.xml')
_images/panel_05.png
_images/panel_05.png
  • 序列瀏覽器 列出圖像序列
seqPath = nuke.getClipname('get sequence')
_images/panel_06.png
_images/panel_06.png
  • 獲取幀范圍,從用戶那獲取幀范圍横缔,如果是立體的铺遂,則附帶在哪個view操作:
    ret = nuke.getFramesAndViews('get range', '1-10' )
    返回值是字符串的list,和要求的view:
ret = nuke.getFramesAndViews('get range', '1-10')
range = ret[0]
views = ret[1]
print 'range is', range
print 'views are', views
_images/panel_07.png
_images/panel_07.png

多視圖腳本:


_images/panel_08.png
_images/panel_08.png


簡單panel對象

創(chuàng)建一個簡單panel對象:
p = nuke.Panel('my custom panel')
檢查哪些knob可用是個好主意:
dir(p)

添加knobs:

p.addClipnameSearch('clip path', '/tmp')
p.addFilenameSearch('file path', '/tmp')
p.addTextFontPulldown('font browser', '/myFonts/')
p.addRGBColorChip('some pretty color', '')
p.addExpressionInput('enter an expression', '4*25')
p.addBooleanCheckBox('yes or no?', True)
p.addEnumerationPulldown('my choices', 'A B C')
p.addScriptCommand('tcl or python code', '')
p.addSingleLineInput('just one line', 'not much space')
p.addMultilineTextInput('multiple lines of user input text', 'lineA\nlineB')
p.addNotepad('write something', 'some very long text could go in here. For now this is just some random default value')
p.addPasswordInput('password', 'donttellanyone')
p.addButton('push here')
p.addButton('or here')
p.addButton('or even here')

打開panel:
ret = p.show()

_images/panel_10.png
_images/panel_10.png

panel關(guān)閉后茎刚,獲取某個值:
print p.value('clip path')
pirnt p.value('file path')

python panel
shapePanel

有兩個下拉菜單的panel,第一個knob控制第二個knob shape的顯示

_images/shapePanel_01.png_images/shapePanel_02.png
_images/shapePanel_01.png_images/shapePanel_02.png

開始撤逢,創(chuàng)建一個繼承nukescripts.PythonPanels的類膛锭,運(yùn)行其構(gòu)造并傳入一個標(biāo)題

class ShapePanel( nukescripts.PythonPanel):
        def __init__(self):
                nukescripts.PythonPanel.__init__(self, 'RotoPaint Elements')

用參數(shù)傳遞我們想分析的節(jié)點,在init中的參數(shù)列表中蚊荣,賦值給self.rpNode:

class ShapePanel( nukescripts.PythonPanel):
    def __init__(self, node):
        nukescripts.PythonPanel.__init__(self, 'RotoPaint Elements')
        self.rpNode = node

使用nuke.Enumeration_Knob創(chuàng)建下拉列表:
self.typeKnob = nuke.Enumeration_Knob('element', 'element', ['Shape', 'Strokes'])

再一次初狰,在全局命名空間中引用這個knob的值,讀取so easy互例。提供給knob的三個參數(shù)是:

  • element knob的對象名字
  • element knob的標(biāo)簽
  • ['Shapes', 'Strokes'] 下拉菜單中顯示的選項

創(chuàng)建第二個enumeration knob奢入, 但其選項設(shè)置為空, 動態(tài)設(shè)置:
self.elementKnob = nuke.Enumeration_Knob('curve', 'curve', [])

現(xiàn)在添加兩個knob:
for k in ( self,typeKnob, self.elementKnob):
self.addKnob(k)

目前的代碼:

class ShapePanel( nukescripts.PythonPanel):
    def __init__(self, node):
        nukescripts.PythonPanel.__init__(self, 'RotoPaint Elements')
        self.rpNode = node
        self.typeKnob = nuke.Enumeration_Knob('element', 'element', ['Shapes', 'Strokes'])
        self.elementKnob = nuke.Enumeration_Knob('curve', 'curve', [])
        for k in (self.typeKnob, self.elementKnob):
            self.addKnob(k)

如果你創(chuàng)建了這個類的例子媳叨,可以用showModalDialog()將其作為模式對話框打開腥光。創(chuàng)建一個RotoPaint節(jié)點,名為RotoPaint1.

node = nuke.toNode('RotoPaint1')
p = ShapePanel(node)
p.showModalDialog()
_images/shapePanel_03.png
_images/shapePanel_03.png

注意showModalDialog給我了帶ok糊秆,cancel按鈕的對話框武福。下面將其美化下:

默認(rèn)情況下,enumeration knob從新一行開始痘番,但是如果我們清除了這個標(biāo)志位捉片,就可以讓兩個knob在同一行:

class ShapePanel( nukescripts.PythonPanel):
        def __init__(self, node):
                nukescripts.PythonPanel.__init__(self, 'RotoPaint Elements')
                self.rpNode = node

                self.typeKnob = nuke.Enumeration_Knob('element', 'element/shape', ['Shapes', 'Strokes'])
                self.elementKnob = nuke.Enumeration_Knob('curve', '', [])
                self.elementKnob.clearFlag(nuke.STARTLINE)
                for k in (self.typeKnob, self.elementKnob):
                        self.addKnob(k)

這也改變了標(biāo)簽上的第一個knob,并將第二個上的knob移除汞舱,這看上去更加簡潔:


_images/shapePanel_04.png
_images/shapePanel_04.png

最后一件在構(gòu)造時要做的事情就是 創(chuàng)建一個字典伍纫,按類型保存元素。在init函數(shù)最后面添加如下代碼:
self.curveDict = {}
實際上不真需要昂芜,可以init在全局范圍內(nèi)初始化變量, 用節(jié)點的shape和stroke來填充字典:
def getData( self):
self.curveDict={'Shapes':[], 'Strokes':[] }
rootLayer = self.rpNode['curves'].rootLayer
1. 用填充第一個enumeration knob的關(guān)鍵字來填充字典(shape莹规,stroke)
2. 抓取node的curve knob,其能列出Roto或者RotoPaint的所有元素说铃,并獲取其rootLayer
rootLayer是個可迭代的對象访惜,能產(chǎn)生curve knob中列出的所有元素嘹履。因此可以遍歷獲取其所有孩子元素。檢查對應(yīng)元素的類型债热,保存進(jìn)
對應(yīng)的字典:

for e in rootLayer:
    if isinstance(e, nuke.rotopaint.Shape):
        self.curveDict['Shapes'].append(e.name)
    elif isinstance( e, nuke.rotopaint.Stroke):
        self.curveDict['Stokes'].append( e.name)

用感興趣的數(shù)據(jù)填充字典砾嫉,通過'shape’和‘stroke’保存。在init最后添加如下代碼:

class ShapePanel(nukescripts.PythonPanel):
    def __init__(self, node):
    '''List all roto paint nodes and the name of their respective shapes and strokes'''
    nukescripts.PythonPanel.__init__(self, 'RotoPaint Elements')
    self.rpNode = node
    # CREATE KNOBS
    self.typeKnob = nuke.Enumeration_Knob('element', 'element / curve', ['Shapes', 'Strokes'])
    self.elementKnob = nuke.Enumeration_Knob('curve', '', [])
    self.elementKnob.clearFlag(nuke.STARTLINE)
    # ADD KNOBS
    for k in (self.typeKnob, self.elementKnob):
        self.addKnob(k)

    # STORE DICTIONARY OF ELEMENTS PER TYPE
    self.curveDict = {}
    # FILL DICTIONARY
    self.getData()

最后窒篱,添加knobChanged方法焕刮,每次panel內(nèi)的knob有變化就觸發(fā)此函數(shù)。knobChanged方法接收一個額外的參數(shù)墙杯,將正在變化的knob傳入
函數(shù)內(nèi)配并。

來看運(yùn)行情況,或者調(diào)試高镐。當(dāng)你改變panel內(nèi)容是溉旋,這是打印knob名字的好方法,并留意腳本編輯器的輸出panel:
def knobChanged( self, knob):
print knob.name()
如果你在這步運(yùn)行panel的代碼嫉髓,注意用knob的showPanel打開panel的觸發(fā)器 knobChanged的回調(diào)函數(shù)观腊。


_images/shapePanel_05.png
_images/shapePanel_05.png

如果你換了第一個enumeration knob,你將看到它的名字會被打印到輸出panel上算行。
現(xiàn)在梧油,用它干點有用的事。我們已經(jīng)有一個字典存儲了所有的shape和stroke州邢,因此我們要做的就是讀取并賦予對應(yīng)的值(基于第一個knob
的當(dāng)前值):

def knobChanged(self, knob):
    self.elementKnob.setValues(self.curveDict[ self.typeKnob.value() ])

通過typeKnob里面找到的當(dāng)前值可以從字典里面讀取self.elementKnob的值儡陨。但是我們僅想panel打開或者typeKnob改變時才做:

def knobChanged(self, knob):
    if knob is self.typeKnob or knob.name()=='showPanel':

        self.elementKnob.setValues(self.curveDict[ self.typeKnob.value() ])

現(xiàn)在可以把第一個enumeration knob從shape轉(zhuǎn)換到stroke,并看到第二個konb自動更新自己的content
最終代碼:

import nuke
import nukescripts

class ShapePanel( nukescripts.PythonPanel ):
    def __init__( self, node ):
        '''List all roto paint nodes and the name of their respective shapes and strokes'''
        nukescripts.PythonPanel.__init__( self, 'RotoPaint Elements' )
        self.rpNode = node
        # CREATE KNOBS
        self.typeKnob = nuke.Enumeration_Knob( 'element', 'element / curve', ['Shapes', 'Strokes'] )
        self.elementKnob = nuke.Enumeration_Knob( 'curve', '', [] )
        self.elementKnob.clearFlag( nuke.STARTLINE )
        # ADD KNOBS
        for k in ( self.typeKnob, self.elementKnob ):
            self.addKnob( k )

        # STORE DICTIONARY OF ELEMENTS PER TYPE
        self.curveDict = {}
        # FILL DICTIONARY
        self.getData()

    def getData( self ):
        '''return a nested dictionary of all shapes and strokes per node'''
        self.curveDict={ 'Shapes':[], 'Strokes':[] }
        rootLayer = self.rpNode['curves'].rootLayer
        for e in rootLayer:
            if isinstance( e, nuke.rotopaint.Shape ):
                self.curveDict[ 'Shapes' ].append( e.name )
            elif isinstance( e, nuke.rotopaint.Stroke ):
                self.curveDict[ 'Strokes' ].append( e.name )


    def knobChanged( self, knob ):
        if knob is self.typeKnob or knob.name()=='showPanel':
            self.elementKnob.setValues( self.curveDict[ self.typeKnob.value() ] )

通過showModalDialog模塊來調(diào)用panel量淌,我們知道用戶的決定骗村,任何事情發(fā)生前的確認(rèn)或者取消。用戶點ok就返回true类少,否則返回false叙身。
在全局范圍內(nèi)引用knobs,在panel關(guān)閉后也可以讀取knob的值硫狞。例子:

node = nuke.toNode('RotoPaint1')
p = ShapePanel(node)
if p.showModalDialog():
    print p.elementKnob.value()

當(dāng)點擊ok關(guān)閉panel時信轿,就打印出值,否則啥也不發(fā)生残吩。


ShapeAndCVPanel

這個簡單的面板掃描Roto或RotoPaint節(jié)點的shape财忽,并將找到的所有shape的name放入下拉列表中。允許輸入幀范圍泣侮,指定CV編號即彪。這是
用來trackCV

從導(dǎo)入使用的包開始

import nuke
import nukescripts
import nuke.rotopaint as rp

然后創(chuàng)建一個類繼承nukescripts中的PythonPanel,接收一個名為node的參數(shù)。調(diào)用父類的構(gòu)造函數(shù)給panle一個標(biāo)題隶校。

class ShapeAndCVPanel(nukescripts.PythonPanel):
def __init__(self, node):
        nukescripts.PythonPanel.__init__(self, 'Get Shape and CV index')

在全局命名空間中引用傳給panel的node漏益,方便在其他地方使用。

self.rpNode = node

從node的curvesknob中獲取root 層深胳。

root = node['curves'].rootLayer

使用列表生成來獲取節(jié)點中的所有shape name:

shapeNames = [c.name for c in root if isinstance(c, rp.Shape)]

添加快速檢測:

if not shapeNames:
    nuke.message('No Shapes found in %s' % node.name()
    return

將knob添加到panel绰疤。字符串knob用來接收幀范圍:

self.fRange = nuke.String_Knob('fRange', 'Track Range')

注意 我們在panel的全局命名空間中引用knob(self.),因此后續(xù)可以在panle外訪問

String knob接收第三個可選參數(shù),來提供默認(rèn)值舞终。 此處使用來設(shè)置默認(rèn)值轻庆。

self.fRange = nuke.String_Knob('fRange', 'Track Range', '%s-%s' % (nuke.root().fristFrame(), nuke.root().lastFrame()))

接下來就是將名字添加到 enumeration knob中:

self.shape = nuke.Enumeration_Knob('shape', 'Shape', shapeNames)

添加一個整數(shù)knob讓用戶輸入CV的編號:

self.cv = nuke.Int_Knob('pointNumber', 'Point Number')

檢查整數(shù)knob,如果有錯敛劝,需要顯示提示信息:

self.warning = nuke.Text_Knob('warning', 'invalid index')

使用Html代碼讓提示更加醒目:

self.warning = nuke.Text_Knob('warning', '<span style="color:red">invalid index</span>')

靜態(tài)文本knob挨著pointNumber knob余爆,在此加入一行來分割:

self.warning.clearFlag(nuke.STARTLINE)

打開panle是需要隱藏警告提示的內(nèi)容:

self.warning.setVisible(False)

最后將四個knob添加到panel:

self.addKnob(self.fRange)
self.addKnob(self.shape)
self.addKnob(self.cv)
self.addKnob(self.warning)

想偷懶的可以這么做:

for k in (self.fRange, self.shape, self.cv, self.warning):
        self.addKnob(k)

零碎代碼整合起來后如下:

import nuke
import nukescripts
import nuke.rotopaint as rp

class ShapeAndCVPanel(nukescripts.PythonPanel):
    def __init__(self, node):
        nukescripts.PythonPanel.__init__(self, 'Get Shape and CV index')
        self.rpNode  = node
        # GET THE NODES ROOT LAYER AND COLLECT ALL SHAPES IN IT
        root = node['curves'].rootLayer
        shapeNames = [ c.name for c in root if isinstance(c, rp.Shape) ]
        if not shapeNames:
            nuke.message('No Shapes found in %s' % node.name())
            return
        # CREATE KNOBS
        self.fRange = nuke.String_Knob('fRange', 'Track Range', '%s-%s' % (nuke.root().firstFrame(), nuke.root().lastFrame()))
        self.shape = nuke.Enumeration_Knob('shape', 'Shape', shapeNames)
        self.cv = nuke.Int_Knob('pointNumber', 'Point Number')
        self.warning = nuke.Text_Knob('warning', 'invalid index')
        self.warning.clearFlag(nuke.STARTLINE)
        self.warning.setVisible(False)

        # ADD KNOBS
        for k in (self.fRange, self.shape, self.cv, self.warning):
            self.addKnob(k)

為了檢測給定點編號是否正確,需要使用knobChanged方法夸盟,當(dāng)knob改變時會自動運(yùn)行蛾方。此方法需要knob參數(shù),其提供了此
功能满俗,并且knob觸發(fā)了這個回調(diào):

def knobChanged(self, knob):

僅需要self.cvself.shape索引的knob變動時調(diào)用此函數(shù):

def knobChanged(self, knob):
    if knob in(self.cv, self.shape):

如上發(fā)生转捕,就要講shape的knob設(shè)置如下:

currentShape = self.rpNode['curves'].toElement(self.shape.value())

我們僅想知道shape中有多少個點:

size = len([pt for pt in currentShape])

現(xiàn)在檢測pointNumber的值是否在合理范圍內(nèi):
validNumber = -1 < knob.value() < size

如果點在合理范圍內(nèi),上面的判別式返回true唆垃,否則返回false。取非來作為控制warnging knob顯示的開關(guān)痘儡。

self.warning.setVisible(not validNumber)

最終代碼如下:

import nuke
import nukescripts
import nuke.rotopaint as rp

class ShapeAndCVPanel( nukescripts.PythonPanel ):
    def __init__( self, node ):
        nukescripts.PythonPanel.__init__( self, 'Get Shape and CV index' )
        self.rpNode  = node
        # GET THE NODES ROOT LAYER AND COLLECT ALL SHAPES IN IT
        root = node['curves'].rootLayer
        shapeNames = [ c.name for c in root if isinstance( c, rp.Shape ) ]
        if not shapeNames:
            nuke.message( 'No Shapes found in %s' % node.name() )
            return
        # CREATE KOBS
        self.fRange = nuke.String_Knob( 'fRange', 'Track Range', '%s-%s' % ( nuke.root().firstFrame(), nuke.root().lastFrame() ) )
        self.shape = nuke.Enumeration_Knob( 'shape', 'Shape', shapeNames )
        self.cv = nuke.Int_Knob( 'pointNumber', 'Point Number' )
        self.warning = nuke.Text_Knob( 'warning', '<span style="color:red">invalid index</span>' )
        self.warning.clearFlag( nuke.STARTLINE )
        self.warning.setVisible( False )

        # ADD KOBS
        for k in ( self.fRange, self.shape, self.cv, self.warning ):
            self.addKnob( k )

    def knobChanged( self, knob ):
        # IF AN INVALID INDEX IS SHOWN DISPLAY THE WARNING TEXT
        if knob in( self.cv, self.shape ):
            currentShape = self.rpNode['curves'].toElement( self.shape.value() )
            size = len( [pt for pt in currentShape] )
            validNumber = -1 < knob.value() < size
            self.warning.setVisible( not validNumber )

測試panle辕万,創(chuàng)建Roto或RotoPaint節(jié)點,新的shape沉删,運(yùn)行:

ShapeAndCVPanel(nuke.selectedNode()).showModalDialog()

panel顯示如下:


如果點編號不合法顯示如下:


增加panel的寬度渐尿,顯示完整的警告信息:

p = ShapeAndCVPanel(nuke.selectedNode())
p.setMinimumSize(400, 50)
p.showModalDialog()


搜索和替換面板

下面的代碼創(chuàng)建了一個面板,在NUKE腳本中執(zhí)行搜索和替換操作矾瑰。其使用了幫助函數(shù)search來簡化代碼砖茸。視頻教程在Nukepedia.

def search(searchstr, nodes):
    """ Search in nodes with file knobs. """
    fileKnobNodes = [i for i in nodes if __NodeHasKnobWithName(i, 'file')]
    proxyKnobNodes = [i for i in nodes if __NodeHasKnobWithName(i, 'proxy')]
    if not fileKnobNodes and not proxyKnobNodes: raise ValueError, "No file nodes selected"
    nodeMatches = []
    knobMatches = []
    for i in fileKnobNodes:
        if __FindNode(searchstr, i['file']):
            nodeMatches.append(i)
            knobMatches.append(i['file'])
    for i in proxyKnobNodes:
        if __FindNode(searchstr, i['proxy']):
            nodeMatches.append(i)
            knobMatches.append(i['proxy'])
    return nodeMatches, knobMatches

URL是構(gòu)造函數(shù)第二個參數(shù),這能讓面板保存或作為自定義布局的一部分再次喚醒:

class SearchReplacePanel(nukescripts.PythonPanel):
    def __init__(self):
        nukescripts.PythonPanel.__init__(self, 'Search and Replace', 'com.ohufx.SearchReplace')
        # CREATE KNOBS
        self.nodesChoice = nuke.Enumeration_Knob('nodes', 'Source Nodes', ['all', 'selected'])
        self.searchStr = nuke.String_Knob('searchStr', 'Search for:')
        self.update = nuke.PyScript_Knob('update', 'Update')
        self.info = nuke.Multiline_Eval_String_Knob('info', 'Found')
        self.info.setEnabled(False)
        self.replaceStr = nuke.String_Knob('replaceStr', 'Replace with:')
        self.replace = nuke.PyScript_Knob('replace', 'Replace')
        # ADD KNOBS
        self.addKnob(self.nodesChoice)
        self.addKnob(self.searchStr)
        self.addKnob(self.update)
        self.addKnob(self.info)
        self.addKnob(self.replaceStr)
        self.addKnob(self.replace)

        self.matches = None

    def search(self, nodes):
        nodeMatches, knobMatches = search(self.searchStr.value(), nodes)
        nodes = [n.name() for n in nodeMatches]
        infoStr = '%s node(s) found:\n\t%s' % (len(nodes), ', '.join(nodes))
        self.info.setValue(infoStr)
        return knobMatches

    def knobChanged(self, knob):
        if knob in (self.searchStr, self.update, self.nodesChoice):
            srcNodes = { 'all': nuke.allNodes(), 'selected': nuke.selectedNodes() }
            self.matches = self.search(srcNodes[self.nodesChoice.value()])
        elif knob is self.replace and self.matches is not None:
            for k in self.matches:
                newStr = re.sub(self.searchStr.value(), self.replaceStr.value(), k.value())
                k.setValue(newStr)

下面是將面板添加到Panel的默認(rèn)方法(下面代碼放入menu.py):

def addSRPanel():
    global srPanel
    srPanel = SearchReplacePanel()
    return srPanel.addToPane()

paneMenu = nuke.menu('Pane')
paneMenu.addCommand('SearchReplace', addSRPanel)
nukescripts.registerPanel('com.ohufx.SearchReplace', addSRPanel)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末殴穴,一起剝皮案震驚了整個濱河市凉夯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌采幌,老刑警劉巖劲够,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異休傍,居然都是意外死亡征绎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門磨取,熙熙樓的掌柜王于貴愁眉苦臉地迎上來人柿,“玉大人柴墩,你說我怎么就攤上這事≠灬” “怎么了江咳?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長隘截。 經(jīng)常有香客問我扎阶,道長,這世上最難降的妖魔是什么婶芭? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任东臀,我火速辦了婚禮,結(jié)果婚禮上犀农,老公的妹妹穿的比我還像新娘惰赋。我一直安慰自己,他們只是感情好呵哨,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布赁濒。 她就那樣靜靜地躺著,像睡著了一般孟害。 火紅的嫁衣襯著肌膚如雪拒炎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天挨务,我揣著相機(jī)與錄音击你,去河邊找鬼。 笑死谎柄,一個胖子當(dāng)著我的面吹牛丁侄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朝巫,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鸿摇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了劈猿?” 一聲冷哼從身側(cè)響起拙吉,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎糙臼,沒想到半個月后庐镐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡变逃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年必逆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡名眉,死狀恐怖粟矿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情损拢,我是刑警寧澤陌粹,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏囱皿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一蒙幻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧胆筒,春花似錦邮破、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至彤蔽,卻和暖如春摧莽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背顿痪。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工范嘱, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人员魏。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像叠聋,于是被迫代替她去往敵國和親撕阎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 使用下文描述的nuke.add...()函數(shù)碌补,當(dāng)有變量事件(比如虏束,創(chuàng)建節(jié)點,加載腳本)時就自動調(diào)用python函數(shù)...
    N景波閱讀 2,677評論 0 1
  • 快捷鍵厦章,菜單镇匀,菜單項 的做法。這類代碼一般在menu.py里面袜啃。至于如何安裝請參看installing Plug-...
    N景波閱讀 1,746評論 0 3
  • 怎么創(chuàng)建roto 圖形和 畫筆當(dāng)獲取或者設(shè)置roto汗侵,rotopaint節(jié)點時,需要讀取節(jié)點的curves kno...
    N景波閱讀 1,560評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)晰韵,斷路器发乔,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 本章的例子幫你初步了解Nuke Python API的使用。 腳本大小寫敏感雪猪,需要輸入正確才能運(yùn)行栏尚。拷貝時注意縮進(jìn)...
    N景波閱讀 7,578評論 0 14