Leer hoe u een aangepaste rendermanager voor Nuke kunt maken met Python, zodat u een of meer Nuke-projecten kunt renderen zonder de software te hoeven openen.
Het doel van deze tutorial is om uit te leggen hoe je een software schrijft waarmee je het weergaveproces in Nuke kunt beheren. Je hebt mogelijk meerdere Nuke-composities die moeten worden gerenderd, dus door een dergelijk programma te gebruiken, kun je ze allemaal tegelijk weergeven zonder Nuke zelf te openen. Dit betekent dat het systeem de grafische interface van Nuke niet laadt, zodat het meer geheugen kan reserveren voor de rendering. werkwijze. Hier kun je een voorbeeld zien van het programma dat je gaat bouwen:
Grafische gebruikers-interface.Het programma geeft drie projecten weer.Het programma heeft een duidelijke gebruikersinterface waarmee u zoveel renders als nodig kunt organiseren en in de wachtrij kunt plaatsen.
In deze tutorial neem ik aan dat je een basiskennis hebt van Python en enkele dos-opdrachten. Deze software is bedoeld voor gebruik op het Windows-besturingssysteem. De tools die u nodig hebt, zijn de volgende:
Python 2.x geïnstalleerd (https://www.python.org) Gebruik de 3.x-versie niet omdat Nuke het niet ondersteunt.
wxPython-bibliotheek (http://www.wxpython.org) Hiermee kunt u een gebruikersinterface maken. U kunt ook Tkinter, Qt gebruiken, maar dit wordt niet behandeld in deze zelfstudie.
We zullen deze software NukeRenderManager noemen. Het programma bestaat uit drie bestanden:
NukeRenderingManager.py
exeNuke.bat
Rendering.py
NukeRenderingManager.py: het bevat alles over de grafische gebruikersinterface en alle informatie over de locatie van de Nuke-projecten en alle frame-ranges.
exeNuke.bat: het is verantwoordelijk voor de lancering van Nuke in terminal-modus door alle informatie uit het NukeRenderingManager.py-bestand door te geven. Dit bestand wordt voor elke render aangeroepen, dus als drie Nuke-comps moeten worden gerenderd, wordt dit bestand drie keer uitgevoerd.
Rendering.py: het krijgt alle informatie van exeNuke.bat en voert de rendering uit. Dit bestand wordt voor elk Nuke-project uitgevoerd.
De NukeRenderingManager.py beheert de gebruikersinterface en organiseert de lijst met te renderen projecten.
Om onze gebruikersinterface te bouwen gebruiken we de wxPython-bibliotheek. Zoals ik al eerder zei, kun je een andere bibliotheek gebruiken, maar voor het doel van deze tutorial zal ik wxPython uitleggen. Om het te installeren hoef je alleen maar het installatieprogramma te downloaden, het te starten en alles is klaar (je kunt de link hierboven vinden). Nadat de bibliotheek is geïnstalleerd, moet je Python 2.x IDLE starten en dit geeft je de Python-shell. Van de het dossier menu kiezen Nieuw bestand, nu heb je een lege editor. Als u wilt, kunt u elke andere editor gebruiken waarmee u zich misschien op uw gemak voelt.
Lege Python-editor.Sla het bestand op als NukeRenderingManager.py en zet het in elke gewenste map.
Het eerste dat u hoeft te doen, is de modules importeren die we nodig hebben. De eerste is os waarmee we de functies van het besturingssysteem kunnen gebruiken, de tweede is de wx die nuttig zal zijn om een grafische gebruikersinterface te bouwen:
import os import wx
We gaan een venster maken dat alles bevat wat we nodig hebben, dus we bereiken dit doel door een aangepaste klasse te maken die is afgeleid van wx.Frame:
Class mainWindow (wx.Frame):
Vervolgens implementeren we de constructor door het wx.Frame aan te roepen .__ init__:
def __init __ (self): #constructor wx.Frame .__ init __ (self, None, title = "Nuke Rendering Manager", size = (600,300), style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
Vervolgens maken we een statusbalk:
self.CreateStatusBar ()
We voegen een tekstcontrole toe om te tonen welke Nuke-projecten worden verwerkt:
# bereid de Nuke-scriptlijst voor op het scherm zelf. 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 ('Nuke-scripts: \ n')
De wx.TextCtrl geef ons een gebied waar we de lijst kunnen schrijven, we hebben het nodig als multiline, dus we verklaren het wx.TE_MULTILINE. We hebben het niet nodig om te worden bewerkt, dus gebruiken we het SetEditable (Valse), dan definiëren we enkele kleuren en uiteindelijk laten we een tekst zien.
Vervolgens maken we een weergaveknop:
# het maakt de renderknop self.RenderButton = wx.Button (self, label = "Render", pos = (8,200))
Een heel belangrijk ding is de sizer. Met de sorteerder kunnen we een lay-out definiëren, we zullen de BoxSizer gebruiken die elementen horizontaal en verticaal plaatst, we kiezen een verticale plaatsing voor het tekstbeheer en de knop:
self.layout = wx.BoxSizer (wx.VERTICAL) self.layout.Add (self.NukeScriptsList, 1, wx.EXPAND) self.layout.Add (self.RenderButton, 0, wx.EXPAND) self.SetSizer (self. lay-out)
De tweede parameter in de Toevoegen methode is een cijfer dat beschrijft hoe mespatroon elk element in beslag neemt, 0 betekent dat de minimale grootte wordt gebruikt, 1 betekent dat beschikbare ruimte bezet zal zijn, in ons geval willen we dat de knop wordt geminimaliseerd en dat de tekstcontrole de resterende ruimte heeft.
We bereiden enkele variabelen voor:
self.NukeScripts = [] self.dirName = "" self.fileName = ""
Daarna bereiden we het menu voor. We beginnen met het maken van een menubalk wx.MenuBar (), we maken e-menu genaamd filemenu als wx.Menu (), we voegen het toe Nuke-scripts toevoegen en Uitgang items en voeg ze toe aan het filmenu. En als laatste voegen we filemenu toe aan menuBar:
# het maakt menu-items menuBar = wx.MenuBar () filemenu = wx.Menu () addNukeScript = filemenu.Append (wx.ID_ANY, "Nuke-script toevoegen", "Nukeerscript toevoegen") ClearList = filemenu.Append (wx.ID_ANY , "Lijst wissen", "Lijst wissen") exitEvt = filemenu.Append (wx.ID_EXIT, "Exit", "Exit") menuBar.Append (filemenu, "File") self.SetMenuBar (menuBar)
wx.ID_ANY wx.ID_EXIT worden gebruikt om een ID kaart naar de elementen, in het eerste geval krijgen we een ID voor het item, maar in het tweede geval hebben we een ID_EXIT dat creëert een speciale ID voor de exit-actie.
De volgende stap is om deze elementen een bepaalde bewerking te laten uitvoeren, daarvoor gebruiken we de wx.Bind functie waarmee we het element aan een specifieke functie kunnen binden:
self.Bind (wx.EVT_MENU, self.onAdd, addNukeScript)
Het eerste argument zegt dat het om een menugebeurtenis gaat, de tweede om de functie die we aan dit element willen koppelen en de derde om het element zelf. In dit geval is het addNukeScritp item in het menu. We moeten nog steeds het self.onAdd functie, we zullen dat later doen:
self.Bind (wx.EVT_MENU, self.onClearList, ClearList)
De Duidelijke lijst actie is gebonden aan de onClearList methode:
self.Bind (wx.EVT_BUTTON, self.onRender, self.RenderButton)
Hier binden we de self.RenderButton naar de self.onRender functie die we moeten implementeren:
self.Bind (wx.EVT_MENU, self.onExit, exitEvt)
Uiteindelijk kennen we de self.onExit functie naar de exitEvt element.
Om de constructor te voltooien, laten we de hoofd venster:
# het toont het hoofdvenster zelf.Show (True)
Tot nu toe hebben we onze constructor:
import os import wx class mainWindow (wx.Frame): def __init __ (self): #constructor wx.Frame .__ init __ (self, None, title = "Nuke Rendering Manager", size = (600,300), style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) # het maakt zelf een statusbalk.CreateStatusBar () # bereid de Nuke-scriptslijst voor op het scherm zelf. 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 ('Nuke scripts: \ n') # het maakt de renderknop self.RenderButton = wx.Button (self, label = "Render", pos = (8,8)) # layout self.layout = wx.BoxSizer (wx.VERTICAL) self.layout.Add (self.NukeScriptsList, 1, wx.EXPAND) self.layout . Add (self.RenderButton, 0, wx.EXPAND) self.SetSizer (self.layout) #variables self.NukeScripts = [] self.dirName = "" self.fileName = "" # het maakt menu-items menuBar = wx. MenuBar () filemenu = wx.Menu () addNukeScript = filemenu.Append (wx.ID_ANY, "Nuke-script toevoegen", " Nuke-script toevoegen ") ClearList = filemenu.Append (wx.ID_ANY," Lijst wissen "," Lijst wissen ") exitEvt = filemenu.Append (wx.ID_EXIT," Exit "," Exit ") menuBar.Append (filemenu," Bestand ") self.SetMenuBar (menubalk) # het bindt elementen aan evenementen zelf. Bind (wx.EVT_MENU, self.onAdd, addNukeScript) self.Bind (wx.EVT_MENU, self.onClearList, ClearList) self.Bind (wx.EVT_BUTTON , self.onRender, self.RenderButton) self.Bind (wx.EVT_MENU, self.onExit, exitEvt) # toont het hoofdvenster zelf.Show (True)Snapshot van de editor.
Laten we de functies eens bekijken. Het eerste wat ik wil uitleggen is onAdd dat wordt uitgevoerd wanneer de menu-gebeurtenis addNukeScript wordt genoemd. Het doel van deze functie is om de Nuke-scriptinformatie in een lijst toe te voegen:
# het voegt Nuke-scripts toe aan de lijst def onAdd (self, event): wildcard = "Nuke-scripts * .nk | * .nk" dlg = wx.FileDialog (self, message = "Nuke-script toevoegen", wildcard = wildcard, stijl = wx.OPEN) als dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () self.fileName = dlg.GetFilename () self.NukeScripts.append (self.dirName + self.fileName) self .updateList () dlg.Destroy ()
Omdat deze functie wordt aangeroepen als een gebeurtenis optreedt, zoals we deze definiëren, moeten we een extra parameter opnemen die in dit geval we gebeurtenis noemden. We definiëren een jokerteken als een tekenreeks, die handig is om gebruikers te laten weten naar welke extensie ze moeten zoeken:
wildcard = "Nuke-scripts * .nk | * .nk"
Er wordt een dialoogvenster voor bestands openen gemaakt en als de gebruiker op OK klikt, onthouden we de map en de bestandsnaam in onze variabelen en bellen we updateList om het scherm bij te werken:
if dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () self.fileName = dlg.GetFilename () self.NukeScripts.append (self.dirName + self.fileName) self.updateList ()
De updateList methode wist het scherm, loopt door de NukeScripts lijst en schrijft opnieuw op het scherm:
#it werkt de Nuke-scriptlijst bij op schermdef updateList (self): self.NukeScriptsList.Clear () voor i in self.NukeScripts: self.NukeScriptsList.AppendText (i + "\ n")
De onClearList functie wist het scherm en de NukeScripts lijst:
def onClearList (self, event): self.NukeScriptsList.Clear () self.NukeScripts = []
Wij hebben onRender () , dat zal in de volgende sectie worden geïmplementeerd, en de OnExit functie die de applicatie afsluit:
# het start het renderingproces def onRender (self, event): print "Rendering ..." # het sluit het programma def onExit (self, event): self.Close (True)
Dit is de mainWindow-klassendefinitie, nu moeten we er een instantie van maken om het te zien en te gebruiken, maar eerst moeten we een wx.App voorwerp:
app = wx.App (False)
Vervolgens maken we onze hoofd venster aanleg:
MainWindow = MainWindow ()
Eindelijk moeten we de Hoofdlus functie om de applicatie te starten:
app.MainLoop ()
Dus op dit punt hebben we de NukeRenderingManager.py-code behalve de onRender-methode die we in het volgende gedeelte gaan implementeren.
Om ons programma robuuster te maken heb ik een paar regels toegevoegd om wat controles uit te voeren. Aangezien we een Nuke-script laden, zou het goed zijn als we controleren of de extensie is .nk, zelfs als het jokerteken onze keuze filtert. We gebruiken de os.path.splitext functie, dan als de extensie is .nk we gaan als normaal verder:
#We controleren of we een Nuke-script self.extension = os.path.splitext (self.fileName) hebben als self.extension [1] == ". nk": self.NukeScripts.append (self.dirName + self.fileName ) self.updateList ()
De os.path.splitext geeft een lijst terug met de naam en de extensie op de [0] en [1] positie. Omdat we externe bestanden laden, is het mogelijk dat sommige ervan beschadigd zijn. Om de kwaliteit van onze applicatie te verbeteren, zullen we de uitzonderingen behandelen:
# het voegt Nuke-scripts toe aan de lijst def onAdd (self, event): wildcard = "Nuke-scripts * .nk | * .nk" dlg = wx.FileDialog (self, message = "Nuke-script toevoegen", wildcard = wildcard, stijl = wx.OPEN) try: if dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () self.fileName = dlg.GetFilename () #we controleren of we een Nuke-script hebben self.extension = os.path.splitext (self.fileName) als self.extension [1] == ". nk": self.NukeScripts.append (self.dirName + "\\" + self.fileName) self.updateList () behalve: print "kan dit bestand niet lezen" dlg.Destroy ()
Zoals je gemerkt hebt dat ik heb gebruikt self.NukeScripts.append (self.dirName +”\\” + self.fileName), Ik moest toevoegen “\\” omdat ik er achter ben gekomen dat er een kernschedel in zit c: \ het komt terug c: \, je moet het toevoegen \ handmatig.
Voor het einde van dit gedeelte wil ik vermelden dat om het hele systeem te laten werken, we moeten voorkomen dat de nuke-scripts, de exeNuke.bat en de Rendering.py bestanden in een map met een heel lang pad. Ik heb het programma getest en om een of andere reden als dit pad te lang is, werkt het niet, misschien omdat de prompt niet in staat is om dergelijke strings aan te kunnen..
Dus onze NukeRenderingManager.py is de volgende:
import os import wx class mainWindow (wx.Frame): def __init __ (self): #constructor wx.Frame .__ init __ (self, None, title = "Nuke Rendering Manager", size = (600,300), style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) # het maakt zelf een statusbalk.CreateStatusBar () # bereid de Nuke-scriptslijst voor op het scherm zelf. 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 ('Nuke scripts: \ n') # het maakt de renderknop self.RenderButton = wx.Button (self, label = "Render", pos = (8,8)) # layout self.layout = wx.BoxSizer (wx.VERTICAL) self.layout.Add (self.NukeScriptsList, 1, wx.EXPAND) self.layout . Toevoegen (self.RenderButton, 0, wx.EXPAND) self.SetSizer (self.layout) # variabelen self.NukeScripts = [] self.dirName = "" self.fileName = "" # het maakt menu-items menuBar = wx. MenuBar () filemenu = wx.Menu () addNukeScript = filemenu.Append (wx.ID_ANY, "Nuke-script toevoegen", "Nuke-script toevoegen") ClearList = filemenu.Append (wx.ID_ANY, "Lijst wissen", "Lijst wissen") exitEvt = filemenu.Append (wx.ID_EXIT, "Exit", "Exit") menuBar.Append (filemenu, "Bestand") self.SetMenuBar (menubalk) # het bindt elementen aan evenementen zelf. Bind (wx.EVT_MENU, self.onAdd, addNukeScript) self.Bind (wx.EVT_MENU, self.onClearList, ClearList) self.Bind (wx. EVT_BUTTON, self.onRender, self.RenderButton) self.Bind (wx.EVT_MENU, self.onExit, exitEvt) # toont het hoofdvenster zelf.Show (True) #it werkt de Nuke-scriptslijst bij op het scherm def updateList (self) : self.NukeScriptsList.Clear () voor i in self.NukeScripts: self.NukeScriptsList.AppendText (i + "\ n") # het voegt Nuke-scripts toe aan de lijst def onAdd (self, event): wildcard = "Nuke-scripts *. nk | * .nk "dlg = wx.FileDialog (self, message =" Voeg Nuke-script toe ", wildcard = jokerteken, style = wx.OPEN) try: if dlg.ShowModal () == wx.ID_OK: self.dirName = dlg.GetDirectory () self.fileName = dlg.GetFilename () #We controleren of we een Nuke-script self.extension = os.path.splitext (self.fileName) hebben als self.extension [1] == ".nk": self.NukeScripts.append (self.dirName + "\\" + self.fileName) self.updateList () behalve: print "niet in staat om dit bestand te lezen" dlg.Destroy () def onClearList (self, event) : self.NukeScriptsList.Clear () self.NukeScripts = [] # het start het rendering proces voor elk Nuke script def onRender (self, event): # om return # te implementeren sluit het programma def onExit (self, event): zelf .Sluiten (Waar) app = wx.App (False) mainWindow = mainWindow () app.MainLoop ()Nog een snapshot van de editor.
Een bat-bestand wordt door het Windows-besturingssysteem herkend als een verzameling opdrachten. Je kunt elk type commando schrijven dat je wilt, je kunt ook programma's starten, en dat is een functie die we gaan gebruiken. Als u bekend bent met snelle instructies, zult u dit proces gemakkelijk vinden.
Allereerst moet je een leeg tekstbestand openen (ik beveel Kladblok aan) en sla het op als exeNuke.bat. Zoals ik in het vorige gedeelte al zei, moeten we voorkomen dat deze bestanden op een locatie met een erg lang pad worden geplaatst, omdat de prompt niet in staat is om het te verwerken, dus plaats alle drie de bestanden die we op je schijf schrijven, met alleen een paar submappen, zoiets als c: \ NukeRenderingManager of c: \ myProjects \ NukeRenderingManager.
Die regel is ook van toepassing op de Nuke-scripts, ze kunnen zich op een andere plaats bevinden, maar zorg ervoor dat het pad niet te lang is.
Ik wil in het kort uitleggen hoe Nuke werkt. We werken meestal in Nuke via de grafische gebruikersinterface, maar voor sommige specifieke taken willen we het misschien in terminal-modus gebruiken. Dat betekent dat we alleen opdrachten schrijven om een normale bewerking uit te voeren, het lijkt op een Windows-prompt:
De manier waarop we instructies sturen naar Nuke in terminal-modus is door wat Python-code te schrijven. Laten we aannemen dat je een Blur-knooppunt wilt maken, je kunt typen nuke.createNode ( 'Blur') enzovoorts. Wat we gaan doen is het bat-bestand Nuke openen in terminal-modus en de weergave van een project starten, alles doen door commando's te verzenden en zonder grafische gebruikersinterface.
De eerste instructie is:
C: \ C:
Dit is om ervoor te zorgen dat we het Nuke-pad kunnen gaan typen om het te starten:
cd Programmi \ Nuke6.2v6 Nuke6.2 -t
Natuurlijk kunnen deze regels verschillen, schrijf de locatie van uw machine op. De -t betekent terminal-modus. Als u dubbelklikt op uw exeNuke.bat-bestand, ziet Nuke in terminal-modus. Als je wilt stoppen, typ je gewoon quit () en druk op invoeren. Om de rendering uit te voeren, moeten we ook de Rendering.py bestand, zodat we onze code kunnen bijwerken:
cd \ c: cd Programmi \ Nuke6.2v6 Nuke6.2 -t c: \ NukeRenderingManager \ Rendering.py
Door de locatie van de. Toe te voegen Rendering.py bestand, vragen we om Nuke te openen in terminal-modus en de Rendering.py die alle code bevat om de rendering uit te voeren, en zoals ik al zei voordat de terminal mode de Python-taal vereist, gebruiken we de Rendering.py code. Maar we hebben nog steeds één stuk informatie nodig, het Rendering.py-bestand moet weten waar de Nuke-scripts zich bevinden.
Vergeet niet dat de exeNuke.bat en Rendering.py zal worden gevraagd voor elk Nuke-script, dus als we drie projecten moeten uitvoeren, worden ze drie keer gelanceerd. Maar elke keer dat ze de Rendering.py moet weten waar de scritp zich bevindt, om deze taak te bereiken moeten we deze informatie van het bovenstaande krijgen NukeRenderingManager.py.
Momentopname van de batch-bestandseditor .De enige methode die we moeten implementeren is onRender (). Wat we doen, loopt door NukeScripts en roept het bat-bestand elke keer op:
# het start het renderingproces voor elk Nuke-script def onRender (self, event): for i in self.NukeScripts: os.system ("C: /exeNuke.bat" + "" + i)
Wij gebruiken de os.system functie om het bestand uit te voeren. Zoals je hebt gemerkt, gaan we ook voorbij ik als het argument na een spatie. We sturen het NukeScript-pad in principe naar het batchbestand. Het feit dat we deze informatie gemakkelijk naar het batchbestand kunnen verzenden, biedt ons een grote flexibiliteit.
De manier waarop een batchbestand argumenten krijgt, is door het symbool te gebruiken % gevolgd door een nummer, omdat we een informatie hebben doorgegeven die we zullen schrijven % 1. Hier de volledige code:
cd \ c: cd Programmi \ Nuke6.2v6 Nuke6.2 -t c: \ Rendering.py% 1
We lanceren Nuke en we bellen met de Rendering.py door het het pad van het script te geven als argument.
Voordat ik deze sectie afsluit, wil ik het proces dat tot nu toe is beschreven, herhalen. NukeRenderingManager.py biedt ons de grafische gebruikersinterface en organiseert de lijst van de Nuke-scripts die moeten worden weergegeven. Voor elk van de scripts exeNuke.bat en Rendering.py zal gebeld worden. De eerste is verantwoordelijk voor het uitvoeren van Nuke in terminal-modus, het pad van het script dat moet worden verwerkt en het doorgeven aan de Rendering.py die de render zelf zal uitvoeren. Nu moeten we Rendering.py implementeren.
Het eerste dat we moeten doen, is het pad van het script pakken dat we hebben doorgegeven aan het batchbestand. Om dit te bereiken, gebruiken we eenvoudig de volgende verklaring sys.argv [1]. Vervolgens transformeren we deze informatie in string:
prj = str (sys.argv [1])
De instructie om een Nuke-project te openen is als volgt:
nuke.scriptOpen (PRJ)
Nu hebben we het script klaar voor gebruik. Wat we nu moeten doen, is zoeken naar het schrijfknooppunt dat we willen en renderen. In mijn voorbeeld wordt het schrijfknooppunt genoemd dat ik nodig heb Write1, maar je kunt elke gewenste naam gebruiken. Hier is de volledige code:
prj = str (sys.argv [1]) nuke.scriptOpen (prj) voor i in nuke.allNodes (): if i.Class () == "Write": if i ['name']. getValue () = = "Write1": first_frame = nuke.Root (). Knob ('first_frame'). Value () last_frame = nuke.Root (). Knob ('last_frame'). Value () nuke.execute (i, first_frame, last_frame )
Wat we doen is door alle knooppunten in het script bladeren, we controleren of het knooppunt een schrijf-exemplaar is, we regelen dat de naam Write1, we krijgen het eerste en laatste frame van het project en we gebruiken de nuke.execute functie om de render uit te voeren.
Momentopname van het rendering.py-bestand.Om het programma te starten dubbelklikt u gewoon op NukeRenderingManager.py. Genieten!