Scrieți un manager de redare pentru Nuke folosind Python

Aflați cum să scrieți un manager personalizat de redare pentru Nuke utilizând Python, permițându-vă să redați unul sau mai multe proiecte Nuke fără a fi nevoie să deschideți software-ul.

1. Introducere

Scopul acestui tutorial este de a explica cum să scrieți un software care vă permite să gestionați procesul de redare în Nuke. S-ar putea să aveți mai multe computere Nuke care trebuie să fie redate, deci, folosind un astfel de program, le puteți reda pe toate fără să deschideți Nuke, ceea ce înseamnă că sistemul nu încorporează interfața grafică Nuke pentru a putea rezerva mai multă memorie pentru redare proces. Aici puteți vedea un exemplu de program pe care îl veți construi:

Interfața grafică a utilizatorului.Programul de redare a trei proiecte.

Programul are o interfață clară pentru utilizatori care vă permite să organizați și să colageți cât mai multe renderări de care aveți nevoie.

cerinţe

În acest tutorial presupun că aveți o înțelegere de bază despre Python și unele comenzi de dos. Acest software este conceput pentru a fi rulat pe sistemul de operare Windows. Instrumentele de care aveți nevoie sunt următoarele:

Python 2.x instalat (https://www.python.org) Nu utilizați versiunea 3.x deoarece Nuke nu o acceptă.

wxPython library (http://www.wxpython.org) Aceasta vă permite să creați o interfață de utilizator. S-ar putea să utilizați și Tkinter, Qt, dar acest lucru nu este acoperit de acest tutorial.

Structura de software

Vom numi acest software NukeRenderManager. Programul este format din trei fișiere:

  • NukeRenderingManager.py

  • exeNuke.bat

  • Rendering.py

NukeRenderingManager.py: conține totul despre interfața grafică a utilizatorului și despre toate informațiile privind localizarea proiectelor Nuke și a tuturor intervalelor de cadre.

exeNuke.bat: este responsabil de lansarea lui Nuke în modul terminal prin trecerea tuturor informațiilor provenite din fișierul NukeRenderingManager.py. Acest fișier este apelat pentru fiecare randare, deci dacă trei computere Nuke trebuie să fie redate, acest fișier va fi rulat de trei ori.

Rendering.py: primește toate informațiile de la exeNuke.bat și efectuează redarea. Acest fișier este executat pentru fiecare proiect Nuke.

2. Scrieți NukeRenderingManager.py

Descriere

NukeRenderingManager.py gestionează interfața cu utilizatorul și organizează lista proiectelor de render.

Interfața cu utilizatorul

Pentru a construi interfața cu utilizatorul, folosim biblioteca wxPython. Așa cum am spus înainte, puteți utiliza o altă bibliotecă, dar în scopul acestui tutorial, voi explica wxPython. Pentru a le instala, trebuie doar să descarci instalatorul, să îl lansezi și totul să fie gata (poți găsi linkul de mai sus). După instalarea bibliotecii trebuie să porniți Python 2.x IDLE și aceasta vă oferă shell-ul Python. De la Fişier alegeți meniul Fișier nou, acum aveți un editor gol. Dacă vrei, poți folosi orice alt editor care te-ar putea simți confortabil. 

Goliți editorul Python.

 Salvați fișierul ca NukeRenderingManager.py și puneți-l în orice dosar doriți.

Primul lucru pe care trebuie să-l facem este importul modulelor de care avem nevoie. Primul este os care ne permite să folosim funcțiile sistemului de operare, al doilea este wx care va fi util pentru a construi o interfață grafică de utilizator:

import os import wx

Vom crea o fereastră care conține tot ceea ce avem nevoie, așa că realizăm acest obiectiv creând o clasă personalizată derivată din wx.Frame:

Clasa mainWindow (wx.Frame):

Apoi implementăm constructorul sunând la wx.Frame .__ init__:

def __init __ (auto): #constructor wx.Frame .__ init __ (auto, None, title = "Nuke Rendering Manager", dimensiune = (600,300), style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)

Apoi vom crea o bară de stare:

self.CreateStatusBar ()

 Adăugăm un control de text pentru a arăta care dintre proiectele Nuke vor fi procesate:

# pregătește lista de scripturi Nuke pe ecranul self.NukeScriptsList = wx.TextCtrl (auto, stil = wx.TE_MULTILINE) self.NukeScriptsList.SetEditable (False) self.NukeScriptsList.SetBackgroundColour ((120,120,120)) self.NukeScriptsList.SetForegroundColour ((50,255 , 50)) self.NukeScriptsList.SetValue ("Scripturi Nuke: \ n ')

wx.TextCtrl ne oferă o zonă în care putem scrie lista, avem nevoie de ea ca multiline pentru a ne declara wx.TE_MULTILINE. Nu avem nevoie să fie editate, așa că vom folosi SetEditable (False), apoi definim câteva culori și, în cele din urmă, afișăm un text.

Apoi vom crea un buton de redare:

# creează butonul de redare auto.RenderButton = wx.Button (auto, etichetă = "Render", pos = (8,200))

 Un lucru foarte important este sizerul. Sizer-ul ne permite să definim un aspect, vom folosi BoxSizer care plasează elementele orizontal și vertical, vom alege o plasare verticală pentru controlul textului și butonul:

auto.layout = wx.BoxSizer (wx.VERTICAL) auto.layout.Add (auto.NukeScriptsList, 1, wx.EXPAND) self.layout.Add (auto.RenderButton, 0, wx.EXPAND) self.SetSizer (auto. aspect)

Al doilea parametru din Adăuga metoda este un număr care descrie modul în care fiecare spațiu ocupă fiecare spațiu, 0 înseamnă că dimensiunea minimă va fi utilizată, 1 înseamnă că spațiul disponibil va fi ocupat, în cazul nostru dorim ca butonul să fie minimizat, iar controlul textului să aibă spațiul rămas.

Pregătim câteva variabile:

auto.NukeScripts = [] auto.dirName = "" auto.fileName = ""

Apoi pregătim meniul. Începem prin crearea unui menubar ca wx.MenuBar (), creăm meniul numit filemenu as wx.Menu (), adăugăm Adăugați scripturi Nuke și Ieșire și adăugați-le la filmenu. Și în final adăugăm filemenu la menuBar:

# creează elemente de meniu menuBar = wx.MenuBar () filemenu = wx.Menu () addNukeScript = filemenu.Append (wx.ID_ANY, "Adăugați scriptul Nuke", "Add Nuke script") ClearList = filemenu.Append (wx.ID_ANY , "Șterge lista", "Șterge lista") exitEvt = filemenu.Append (wx.ID_EXIT, "Ieșire", "Ieșire") meniuBar.Append (filemenu, "Fișier") self.SetMenuBar

wx.ID_ANY wx.ID_EXIT sunt utilizate pentru a furniza o ID-ul la elementele, în primul caz primim un ID pentru element, dar în al doilea caz avem un a ID_EXIT care creează un ID special pentru acțiunea de ieșire.

Următorul pas este să lăsăm aceste elemente să efectueze o anumită operație, pentru care le folosim wx.Bind funcție care ne permite să legăm elementul de o funcție specifică:

self.Bind (wx.EVT_MENU, self.onAdd, addNukeScript)

Primul argument spune că avem de-a face cu un eveniment din meniu, al doilea numeste funcția pe care vrem să o conectăm la acest element, iar al treilea este elementul în sine. În acest caz este addNukeScritp din meniu. Trebuie să implementăm în continuare self.onAdd funcția, vom face acest lucru mai târziu:

self.Bind (wx.EVT_MENU, self.onClearList, ClearList)

  Listă clară acțiunea este legată de onClearList metodă:

self.Bind (wx.EVT_BUTTON, self.onRender, self.RenderButton)

Aici le legăm self.RenderButton la self.onRender funcție pe care trebuie să o punem în aplicare:

self.Bind (wx.EVT_MENU, self.onExit, exitEvt)

 În cele din urmă, îi atribuim self.onExit funcția la exitEvt element.

Pentru a finaliza constructorul vom arăta fereastra principala:

# se afișează fereastra principală self.Show (True)

Până acum avem constructorul nostru:

importul importului wx class mainWindow (wx.Frame): def __init __ (auto): #constructor wx.Frame .__ init __ (auto, None, title = "Nuke Rendering Manager", size = (600,300), style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) # creează o bară de stare self.CreateStatusBar () # pregătește lista de scripturi Nuke pe ecranul self.NukeScriptsList = wx.TextCtrl (self, style = wx.TE_MULTILINE) self.NukeScriptsList.SetEditable (False ) self.NukeScriptsList.SetBackgroundColour ((120,120,120)) self.NukeScriptsList.SetForegroundColour ((50,255,50)) self.NukeScriptsList.SetValue ("Scripts Nuke: \ n ') # creează butonul de render self.RenderButton = wx.Button (auto, etichetă = "Render", pos = (8,8)) # layout auto.layout = wx.BoxSizer (wx.VERTICAL) auto.layout.Add (auto.NukeScriptsList, 1, wx.EXPAND) self.layout .Add (auto.RenderButton, 0, wx.EXPAND) self.SetSizer (auto.layout) #variables self.NukeScripts = [] self.dirName = "" auto.fileName = "" # creează elemente de meniu menuBar = wx. MenuBar () fișiermenu = wx.Menu () addNukeScript = filemenu.Append (wx.ID_ANY, "Add Nuke script", " Adăugați scriptul Nuke ") ClearList = filemenu.Append (wx.ID_ANY," Ștergeți lista "," Ștergeți lista ") exitEvt = filemenu.Append (wx.ID_EXIT," Exit " Fișier ") self.SetMenuBar (menuBar) # se leagă de elemente la evenimente self.Bind (wx.EVT_MENU, self.onAdd, addNukeScript) self.Bind (wx.EVT_MENU, self.onClearList, ClearList) self.Bind (wx.EVT_BUTTON , self.onRender, selfRenderButton) self.Bind (wx.EVT_MENU, self.onExit, exitEvt) # afișează fereastra principală self.Show (True)
Snapshot a editorului.

Să aruncăm o privire asupra funcțiilor. Primul lucru pe care vreau să-l explic este onAdd care este executată ori de câte ori evenimentul din meniu addNukeScript se numește. Scopul acestei funcții este de a adăuga informațiile despre scripturile Nuke într-o listă:

# adaugă scripturi Nuke pe lista def onAdd (auto, eveniment): wildcard = "Scripts Nuke * .nk | * .nk" dlg = wx.FileDialog (self, message = "Add Nuke script" = wx.OPEN) dacă dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () self.fileName = dlg.GetFilename () self.NukeScripts.append (auto.dirName + self.fileName) .updateList () dlg.Destroy ()

Deoarece această funcție este apelată ca un eveniment, așa cum îl definim, trebuie să includem un parametru suplimentar care în acest caz am apelat la eveniment. Definim un wildcard ca un șir, care este util pentru a ghida utilizatorii la ce extensie trebuie să caute:

wildcard = "Scrisori Nuke * .nk | * .nk"

Se creează un dialog de deschidere a fișierului și, pe măsură ce utilizatorul face clic pe OK, memorăm directorul și numele fișierului în variabilele noastre și sunăm updateList pentru a actualiza ecranul:

dacă dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () auto.fileName = dlg.GetFilename () self.NukeScripts.append (auto.dirName + self.fileName) auto.updateList ()

updateList metoda șterge ecranul, buclele prin NukeScripts scrieți și scrieți din nou pe ecran:

#it ​​actualizează lista de scripturi Nuke pe ecran def updateList (auto): self.NukeScriptsList.Clear () pentru i în self.NukeScripts: self.NukeScriptsList.AppendText (i + "\ n") 

onClearList funcția curăță ecranul și NukeScripts listă:

def onClearList (auto, eveniment): self.NukeScriptsList.Clear () self.NukeScripts = []

Noi avem onRender () , care vor fi implementate în secțiunea următoare și onExit funcție care închide aplicația:

# începe procesul de redare def onRender (auto, eveniment): imprimă "Rendering ..." # închide programul def onExit (auto, eveniment): self.Close (True)

Aceasta este definiția principală a claselorWindow, acum trebuie să facem o instanță a acesteia pentru ao vedea și utiliza, dar mai întâi trebuie să creăm o wx.App obiect:

app = wx.App (False)

Apoi ne creăm pe noi fereastra principala instanță:

MainWindow = MainWindow ()

În cele din urmă trebuie să sunăm MainLoop pentru a porni aplicația:

app.MainLoop ()

Deci, în acest moment avem codul NukeRenderingManager.py cu excepția metodei onRender pe care o vom implementa în secțiunea următoare.

Pentru a face programul nostru mai robust, am adăugat câteva linii pentru a face niște controale. Pe măsură ce încarcăm un script Nuke, ar fi bine să verificăm dacă extensia de fișier este .nk, chiar dacă macheta filtrează alegerea noastră. Folosim os.path.splitext funcția, atunci dacă extensia este .nk procedăm în mod normal:

#we check dacă avem un script Nuke self.extension = os.path.splitext (self.fileName) dacă auto.extension [1] == ".nk": self.NukeScripts.append (auto.dirName + self.fileName ) self.updateList ()

os.path.splitext oferă o listă cu numele și extensia de fișier de la [0] și [1] poziţie. Deoarece încărcăm fișiere externe, este posibil ca unele dintre ele să fie corupte, astfel încât pentru a spori calitatea aplicației noastre vom face față excepțiilor:

# adaugă scripturi Nuke pe lista def onAdd (auto, eveniment): wildcard = "Scripts Nuke * .nk | * .nk" dlg = wx.FileDialog (self, message = "Add Nuke script" = wx.OPEN) încercați: dacă dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () self.fileName = dlg.GetFilename () verificăm dacă avem un script Nuke self.extension = os.path.splitext (auto.fileName) dacă auto.extension [1] == ".nk": self.NukeScripts.append (auto.dirName + "\\" + self.fileName) self.updateList () excepție: print "imposibil de citit acest fișier" dlg.Destroy ()

 După cum ați observat că am folosit-o self.NukeScripts.append (self.dirName +“\\“ + self.fileName), A trebuit să adaug „\\“ pentru că am aflat că dacă este localizat vreun script nuke C: \ se întoarce C: \, trebuie să adăugați \ manual.

Înainte de sfârșitul acestei secțiuni vreau să menționez că, pentru a face întregul sistem să funcționeze, ar trebui să evităm plasarea scripturilor nucleare, exeNuke.bat si Rendering.py fișiere într-un folder care are o cale foarte lungă. Am testat programul și, din anumite motive, atunci când această cale este prea lungă, nu funcționează, s-ar putea ca aceasta să nu fie capabilă să se ocupe de astfel de șiruri de caractere.

Deci, NukeRenderingManager.py este următorul:

importul importului wx class mainWindow (wx.Frame): def __init __ (auto): #constructor wx.Frame .__ init __ (auto, None, title = "Nuke Rendering Manager", size = (600,300), style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) # creează o bară de stare self.CreateStatusBar () # pregătește lista de scripturi Nuke pe ecranul self.NukeScriptsList = wx.TextCtrl (self, style = wx.TE_MULTILINE) self.NukeScriptsList.SetEditable (False ) self.NukeScriptsList.SetBackgroundColour ((120,120,120)) self.NukeScriptsList.SetForegroundColour ((50,255,50)) self.NukeScriptsList.SetValue ("Scripts Nuke: \ n ') # creează butonul de render self.RenderButton = wx.Button (auto, etichetă = "Render", pos = (8,8)) # layout auto.layout = wx.BoxSizer (wx.VERTICAL) auto.layout.Add (auto.NukeScriptsList, 1, wx.EXPAND) self.layout .Add (auto.RenderButton, 0, wx.EXPAND) self.SetSizer (self.layout) # variabile self.NukeScripts = [] self.dirName = "" self.fileName = "" # creează elemente de meniu menuBar = wx. MenuBar () fișiermenu = wx.Menu () addNukeScript = filemenu.Append (wx.ID_ANY, "Add Nuke script" "Adăugați scriptul Nuke") ClearList = filemenu.Append (wx.ID_ANY, "Listă ștergere", "Ștergeți lista") exitEvt = filemenu.Append (wx.ID_EXIT, "Exit" "Fișier") self.SetMenuBar (menuBar) # se leagă elemente de evenimente self.Bind (wx.EVT_MENU, self.onAdd, addNukeScript) self.Bind (wx.EVT_MENU, self.onClearList, ClearList) self.Bind (wx. EVT_BUTTON, self.onRender, self.RenderButton) auto.Bonduință (wx.EVT_MENU, self.onExit, exitEvt) # arată fereastra principală self.Show (True) #it actualizează lista de scripturi Nuke pe ecranul def updateList (auto) : self.NukeScriptsList.Clear () pentru i în self.NukeScripts: self.NukeScriptsList.AppendText (i + "\ n") # adaugă scripturi Nuke din lista def onAdd (auto, eveniment): wildcard = "Scripts Nuke *. nk | * .nk "dlg = wx.FileDialog (auto, mesaj =" Adăugați scriptul Nuke ", wildcard = wildcard, style = wx.OPEN) dlg.GetDirectory () self.fileName = dlg.GetFilename () # verificăm dacă avem un script Nuke self.extension = os.path.splitext (self.fileName) dacă self.extension [1] == ".nk": auto.NukeScripts.append (auto.dirName + "\\" + self.fileName) auto.updateList () excepție: print "nu poate citi acest fișier" dlg.Destroy () def onClearList : self.NukeScriptsList.Clear () self.NukeScripts = [] # incepe procesul de redare pentru fiecare defect de script Nuke peRender (auto, eveniment): #pentru a implementa returnarea # închide programul def onExit (auto, eveniment) .Close (True) app = wx.App (Fals) mainWindow = mainWindow () app.MainLoop ()
Un alt instantaneu al editorului.

3. Scrierea fișierului exeNuke.bat

Descriere

Un fișier bat este recunoscut de sistemul de operare Windows ca o colecție de comenzi. Puteți scrie orice fel de comandă doriți, puteți lansa, de asemenea, programe, și aceasta este o caracteristică pe care o vom folosi. Dacă sunteți familiarizat cu instrucțiunile prompte, veți găsi acest proces ușor.

 Mai întâi trebuie să deschideți un fișier text gol (recomandă Notepad) și să îl salvați ca exeNuke.bat. După cum am menționat în secțiunea anterioară, ar trebui să evităm plasarea acestor fișiere într-o locație care are o cale foarte lungă, deoarece pentru că promptul nu este capabil să o facă, plasați toate cele trei fișiere pe care le scriem pe unitatea dvs., cu doar câteva subfoldere, cum ar fi c: \ NukeRenderingManager sau c: \ myProjects \ NukeRenderingManager. 

Această regulă se aplică și scripturilor Nuke, acestea ar putea fi situate într-un alt loc, dar asigurați-vă că calea nu este prea lungă.

Punerea în aplicare

Vreau să explic pe scurt ce funcționează Nuke. De obicei lucrăm în Nuke prin interfața grafică a utilizatorului, dar pentru anumite sarcini specifice am putea să-l rulam în modul terminal. Asta înseamnă că scriem doar comenzi pentru a efectua orice operație obișnuită, seamănă cu un prompt Windows:

Modul în care trimitem instrucțiuni către Nuke în modul terminal este prin scrierea unui cod Python. Să presupunem că doriți să creați un nod Blur, puteți tasta nuke.createNode ( 'Blur') si asa mai departe. Ceea ce vom face este să lăsați fișierul bat să deschidă Nuke în modul terminal și să pornească redarea unui proiect, făcând totul prin trimiterea de comenzi și fără nicio interfață grafică de utilizator.

Prima instrucțiune sunt:

C: \ C:

 Aceasta este pentru a ne asigura că putem începe să tastăm calea Nuke pentru ao lansa:

cd Programmi \ Nuke6.2v6 Nuke6.2 -t

Desigur, aceste linii ar putea fi diferite, scrieți locația mașinii dvs. -T înseamnă modul terminal. Dacă faceți dublu clic pe fișierul exeNuke.bat, ar trebui să vedeți Nuke în modul terminal. Dacă doriți să renunțați, doar tastați părăsi() și lovit introduce. Pentru a efectua redarea, trebuie să executăm și Rendering.py fișier, pentru a putea actualiza codul nostru:

cd \ c: cd Programmi \ Nuke6.2v6 Nuke6.2 -t C: \ NukeRenderingManager \ Rendering.py

Prin adăugarea locației Rendering.py fișier, vă rugăm să deschideți Nuke în modul terminal și executați Rendering.py care conține întregul cod pentru a efectua redarea, și așa cum am spus înainte ca modul terminal să necesite limba Python, așa că folosim Rendering.py cod. Dar avem încă nevoie de o singură informație, fișierul Rendering.py trebuie să știe unde sunt situate scripturile Nuke. 

Amintiți-vă că exeNuke.bat și Rendering.py va fi apelat pentru fiecare script Nuke, deci Dacă trebuie să redați trei proiecte, acestea vor fi lansate de trei ori. Dar de fiecare dată când sunt numiți Rendering.py trebuie să știe unde este localizat scutul, pentru a atinge această sarcină, trebuie să obținem aceste informații de la cele de mai sus NukeRenderingManager.py.

Snapshot a editorului de fișiere batch .

Completați NukeRenderingManagerFile.py

Singura metodă pe care trebuie să o implementăm este onRender (). Ceea ce facem este sa bifam prin NukeScripts si sa sunam de fiecare data fisierul bat:

# începe procesul de redare pentru fiecare defect de script Nuke peRender (auto, eveniment): pentru i în auto.NukeScripts: os.system ("C: /exeNuke.bat" + "" + i)

Noi folosim os.system pentru a executa fișierul. După cum ați observat, trecem și noi eu ca argument după un spațiu. În principiu trimitem calea NukeScript în fișierul lot. Faptul că putem trimite cu ușurință aceste informații în fișierul lot ne oferă o mare flexibilitate.

Completați fișierul exeNuke.bat

Modul în care un fișier batch obține argumente este prin utilizarea simbolului % urmat de un număr, deoarece am trecut o informație pe care o vom scrie % 1. Aici codul complet:

cd \ c: cd Programmi \ Nuke6.2v6 Nuke6.2 -t C: \ Rendering.py% 1

 Lansăm Nuke și sunăm Rendering.py oferindu-i calea scenariului ca argument.

Înainte de a încheia această secțiune, vreau să recapitalizez procesul descris până acum. NukeRenderingManager.py ne oferă interfața grafică de utilizator și organizează lista scrierilor Nuke care trebuie redactate. Pentru fiecare scenariu exeNuke.bat și Rendering.py va fi numit. Primul este responsabil de rularea lui Nuke în modul terminal, prinsă calea scriptului care urmează să fie procesată și trecând-o către Rendering.py care va efectua renderul în sine. Acum trebuie să implementăm Rendering.py.

4. Scrierea fișierului Rendering.py

Punerea în aplicare

Primul lucru pe care trebuie să-l facem este să luăm calea scriptului pe care l-am trecut în fișierul lot. Pentru a realiza acest lucru, pur și simplu folosim următoarea declarație sys.argv [1]. Apoi transformăm aceste informații în șir:

prj = str (sys.argv [1])

Instrucțiunea de deschidere a unui proiect Nuke este următoarea:

nuke.scriptOpen (prj)

Acum avem scenariul gata de utilizare. Ceea ce trebuie să facem acum este să căutăm nodul de scriere pe care îl dorim și îl facem. În exemplul meu, se numește nodul de scriere de care am nevoie Write1, dar puteți folosi orice nume doriți. Iată codul complet:

\ n "" Scrieți un fișier cu numele de fișier, = "Write1": first_frame = nuke.Root (), butonul ('first_frame') .valoarea () last_frame = nuke.Root () knob ('last_frame' )

Ceea ce facem este să buclem prin toate nodurile din script, să verificăm dacă nodul este unul de scriere, să controlam că numele este Write1, primim primul și ultimul cadru al proiectului și îl folosim nuke.execute funcția de a executa randa.

Snapshot-ul fișierului rendering.py.

Concluzie

Pentru a lansa programul, faceți dublu clic pe NukeRenderingManager.py. se bucura!