Commandes de base (Nuke) : Différence entre versions

De FdWiki
Aller à : navigation, rechercher
m (add delete node)
(petites corrections)
 
(30 révisions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
== Principe ==
 
 
Cette page a pour but de donner des exemples simples des commandes python les plus utilisées dans Nuke
 
Cette page a pour but de donner des exemples simples des commandes python les plus utilisées dans Nuke
  
Ligne 19 : Ligne 18 :
  
 
=== Les formats ===
 
=== Les formats ===
Obtenir la liste des formats disponibles.
+
Les formats contiennent la résolution et la taille des pixels.
 +
 
 +
==== Obtenir la liste des formats disponibles ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.formats()
 
nuke.formats()
 
</syntaxhighlight>
 
</syntaxhighlight>
Et le modifier dans le projet:
+
==== Modifier le format du projet ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.root()['format'].value().name() # renvoi le nom du format
 
nuke.root()['format'].value().name() # renvoi le nom du format
 
nuke.root()['format'].value().setName("nomDuFormat")
 
nuke.root()['format'].value().setName("nomDuFormat")
 
</syntaxhighlight>
 
</syntaxhighlight>
Et bien d'autres:
+
==== Et bien d'autres options ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.root()['format'].value().width()
 
nuke.root()['format'].value().width()
 
nuke.root()['format'].value().height()
 
nuke.root()['format'].value().height()
 +
</syntaxhighlight>
 +
 +
==== Obtenir le format d'un node ====
 +
<syntaxhighlight lang="python">
 +
nodeFormat = muNode.format()
 +
nodeFormat.name() # renvoi le nom du format de l'image en entrée.
 +
nodeFormat.width() # renvoi la largeur, en pixel, de l'image en entrée.
 +
nodeFormat.height() # renvoi la heuteur, en pixel, de l'image en entrée.
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Ligne 59 : Ligne 68 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Setter les knobs d'un node a la creation:
+
Setter les knobs d'un node a la création:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.nodes.Blur(size=10)
 
nuke.nodes.Blur(size=10)
Ligne 69 : Ligne 78 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== La selection ===
+
=== La sélection ===
Eviter:
+
Éviter:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.selectedNode()
 
nuke.selectedNode()
Ligne 80 : Ligne 89 :
 
Qui revoit une bête liste dans l'ordre inversé de la sélection.
 
Qui revoit une bête liste dans l'ordre inversé de la sélection.
  
Savoir si un node est sélectionné:
+
==== Savoir si un node est sélectionné ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.isSelected() # True/False
 
myNode.isSelected() # True/False
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Ajouter/Enlever le node a la sélection:
+
==== Ajouter/Enlever le node a la sélection ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.setSelected(True)
 
myNode.setSelected(True)
Ligne 91 : Ligne 100 :
  
 
=== Depuis le projet ===
 
=== Depuis le projet ===
Recupérer tout les nodes:
+
 
 +
==== Récupérer tout les nodes ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.allNodes() # list tout les nodes du projet en cours
 
nuke.allNodes() # list tout les nodes du projet en cours
Ligne 97 : Ligne 107 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Récupérer un node depuis sont nom:
+
==== Récupérer un node depuis son nom ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.toNode("Blur1")
 
nuke.toNode("Blur1")
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Nom d'un node:
+
==== Récupérer le nom d'un node ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.name() # renvoit le nom du node "Blur1"
 
myNode.name() # renvoit le nom du node "Blur1"
Ligne 108 : Ligne 118 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Positionnement dans le graph:
+
==== Récupérer le positionnement d'un node dans le graph ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.xpos()
 
myNode.xpos()
Ligne 117 : Ligne 127 :
  
 
=== Paramètre des nodes ===
 
=== Paramètre des nodes ===
Lister les dict des attributs d'un node:
+
 
 +
==== Lister les dict des attributs d'un node ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.knobs()
 
myNode.knobs()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Methode de base pour get/set:
+
==== Méthode de base pour get/set de variable d'un node ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.knob("size").value() # get value
 
myNode.knob("size").value() # get value
 
myNode.knob("size").setValue(2) # set value
 
myNode.knob("size").setValue(2) # set value
 +
</syntaxhighlight>
 +
Et une autre façon:
 +
<syntaxhighlight lang="python">
 +
myNode["translate"].value() # get value [2.0, 0.0, 32.0]
 +
myNode["translate"].setValue([1.0, 0.0, 16.0]) # set array value
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Pour ajouter un paramètre a un node, la convention est la suivante:
+
==== Ajouter un paramètre a un node ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myControl = nuke.Array_Knob("name", "label") # "name" est simplement le nom du knob et "label" est ce qui sera affiché dans l'UI. Ce dernier est optionnel.
 
myControl = nuke.Array_Knob("name", "label") # "name" est simplement le nom du knob et "label" est ce qui sera affiché dans l'UI. Ce dernier est optionnel.
Ligne 135 : Ligne 151 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Il y a différents types de knobs:
+
==== Les différents types de knobs ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
textControl = nuke.Text_Knob("divider") # Juste une barre de separation
 
textControl = nuke.Text_Knob("divider") # Juste une barre de separation
Ligne 159 : Ligne 175 :
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
for myNode in nuke.allNodes("Read") :
 
for myNode in nuke.allNodes("Read") :
myNode.knob("reload").execute()
+
myNode["reload"].execute()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Ligne 182 : Ligne 198 :
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.canSetInput(0, anotherNode) # Vérifie que la connection de anotherNode sur myNode a l'index 0 est possible
 
myNode.canSetInput(0, anotherNode) # Vérifie que la connection de anotherNode sur myNode a l'index 0 est possible
myNode.setInput(0, anotherNode) # Connecter un node a un autre sur l'index 0
+
myNode.setInput(0, anotherNode) # Connecter un node a un autre sur l'index 0 (myNode prend anotherNode en input, anotherNode se connecte a myNode)
 
myNode.setInput(0, None) # Déconnecter un input
 
myNode.setInput(0, None) # Déconnecter un input
 
myNode.connectInput(0, anotherNode) # connect l'output de anotherNode a l'input 0 de myNode
 
myNode.connectInput(0, anotherNode) # connect l'output de anotherNode a l'input 0 de myNode
Ligne 188 : Ligne 204 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Lister les dépendances montantes et descendantes:
+
==== Lister les dépendances montantes et descendantes ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
myNode.dependent() # Renvoi la liste des nodes dépendants (enfant) de myNode
 
myNode.dependent() # Renvoi la liste des nodes dépendants (enfant) de myNode
 
myNode.dependencies() # Renvoi la liste des nodes dont dépendent myMode (ces parents)
 
myNode.dependencies() # Renvoi la liste des nodes dont dépendent myMode (ces parents)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== Les metadatas ===
 +
Lire les metadatas:
 +
<syntaxhighlight lang="python">
 +
node = nuke.toNode("Read1")
 +
print node.metadata() # un dict de metadata
 +
 +
# Result:
 +
{'exr/displayWindow': [0, 0, 2047, 1555], 'input/width': 2048, 'exr/nuke/camera/vaperture': '18.672', 'input/bitsperchannel': '16-bit half float'...
 +
</syntaxhighlight>
 +
 +
Source: [http://docs.thefoundry.co.uk/nuke/63/pythondevguide/metadata.html Reading Metadata].
  
 
=== Label des nodes ===
 
=== Label des nodes ===
Ligne 202 : Ligne 230 :
 
[date %d]/[date %m]/[date %y] # Affiche la date de l'image
 
[date %d]/[date %m]/[date %y] # Affiche la date de l'image
 
</syntaxhighlight>
 
</syntaxhighlight>
Le langage utilisé semble être [http://tmml.sourceforge.net/doc/tcl/ du tcl].
+
Le langage utilisé est le [http://tmml.sourceforge.net/doc/tcl/ tcl].
 +
 
 +
D'autres commandes utiles ici: [http://www.nukepedia.com/tcl/value-vs-knob-command/ Value vs knob command]
 +
 
 +
== Animation ==
 +
 
 +
==== Récupérer la valeur d'une animation a une image donnée, pour une vue donnée ====
 +
<syntaxhighlight lang="python">
 +
myNode["translate"].valueAt(25, view='R')
 +
# Result: [-26.308155060000001, 2.3234429360000002, 72.413200380000006]
 +
</syntaxhighlight>
 +
 
 +
On peut ajouter l'index du tableau (ici: 0):
 +
<syntaxhighlight lang="python">
 +
myNode["translate"].valueAt(25, 0, view='R')
 +
# Result: -26.308155060000001
 +
</syntaxhighlight>
  
 
== Interface ==
 
== Interface ==
Ligne 209 : Ligne 253 :
  
 
=== Menus ===
 
=== Menus ===
Customiser le menu:
+
 
 +
==== Customiser le menu ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
menuBar = nuke.menu("Nuke") # La barre de menu principale
 
menuBar = nuke.menu("Nuke") # La barre de menu principale
Ligne 226 : Ligne 271 :
  
 
=== Dialog ===
 
=== Dialog ===
Une fileDialog, pour les clips. Un seul/plusieurs fichiers:
+
 
 +
==== Une fileDialog, pour les clips. Un seul/plusieurs fichiers ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.getClipname( "fileDialogName" )
 
nuke.getClipname( "fileDialogName" )
Ligne 234 : Ligne 280 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Une autre avec pattern et defaultPath:
+
==== Une fileDialog avec pattern et defaultPath ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.getFilename("fileDialogName", pattern="*.png;*.jpeg", default="/path/to/a/file" )
 
nuke.getFilename("fileDialogName", pattern="*.png;*.jpeg", default="/path/to/a/file" )
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Yes/No dialog
+
==== Yes/No dialog ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.ask("Ça roule?") # revoit True/False
 
nuke.ask("Ça roule?") # revoit True/False
Ligne 245 : Ligne 291 :
  
 
=== Icones ===
 
=== Icones ===
Appliquer une icone à un node:
+
 
 +
==== Appliquer une icône à un node ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
myNode.knob("icon").setValue("/path/to/an/icon.png")
+
myNode["icon"].setValue("/path/to/an/icon.png")
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
=== Autres ===
 
=== Autres ===
Overrider la fonction de création d'un node:
+
 
 +
==== Overrider la fonction de création d'un node ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
def myCreateNode() :
 
def myCreateNode() :
Ligne 258 : Ligne 306 :
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Divers ==
+
==== Désactiver le thumbnail d'un node ====
 +
<syntaxhighlight lang="python">
 +
myNode["postage_stamp"].setValue(False)
 +
</syntaxhighlight>
 +
 
 +
=== PySide ===
 +
Des bouts de codes trouvé par ci par la.
 +
 
 +
==== Une fenêtre qui reste toujours "devant" Nuke, même si elle n'a plus le focus (ala Maya) ====
 +
Trouvé sur la mailing list nuke-python@support.thefoundry.co.uk.
 +
<syntaxhighlight lang="python">
 +
from PySide import QtCore, QtGui
 +
 
 +
class TestWindow(QtGui.QDialog):
 +
def __init__(self, parent=QtGui.QApplication.activeWindow()):
 +
QtGui.QDialog.__init__(self, parent)
 +
self.hbox=QtGui.QHBoxLayout()
 +
self.button=QtGui.QPushButton("TEST")
 +
self.hbox.addWidget(self.button)
 +
self.setLayout(self.hbox)
 +
 
 +
tw = TestWindow()
 +
tw.show()
 +
</syntaxhighlight>
 +
 
 +
Pour avoir la possibilité de la faire passer "derrière" Nuke il suffit de remplacer:
 +
<syntaxhighlight lang="python">
 +
QtGui.QApplication.activeWindow()
 +
</syntaxhighlight>
 +
Par:
 +
<syntaxhighlight lang="python">
 +
QtGui.QApplication.desktop()
 +
</syntaxhighlight>
 +
Dans tout les cas, il faut lui donner un parent. Sans parent, Nuke vous gratifiera d'un ''Segmentation fault'' lorsque vous quittez.
 +
 
 +
== Debug ==
  
Lancer nuke en mode terminal (pas de GUI):
+
==== Afficher les plugin path ====
<syntaxhighlight lang="bash">
+
<syntaxhighlight lang="python">
nuke -t
+
nuke.pluginPath()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Obtenir des statistiques (performance metrics) en fin de session sur les nodes calculés (en mode terminal ou GUI, uniquement sous Linux):
+
==== Obtenir des statistiques (performance metrics) sur les nodes calculés ====
 +
En mode terminal ou GUI, uniquement sous Linux
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
 
nuke -P
 
nuke -P
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Faire un print dans le terminal qui a lancé Nuke:
+
==== Afficher tout les callbacks de Nuke dans le terminal ====
 +
Dans votre ''.nuke/init.py'', ajoutez:
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
nuke.tprint("Hello World!")
+
import callbacksTrace
 +
</syntaxhighlight>
 +
 
 +
==== Obtenir un debug des déchargements de la mémoire de Nuke ====
 +
Lancer le Nuke avec la variable d’environnement ''NUKE_DEBUG_MEMORY'' à ''1'' (voir page 9 [https://thefoundry.s3.amazonaws.com/downloads/Nuke5.2v1_ReleaseNotes.pdf de la doc]).
 +
 
 +
Combiné à ''-P'' cette option est très interessante.
 +
 
 +
==== Connaître l'état de Nuke lors d'un crash ====
 +
Il faut récupérer le PID de Nuke avec la commande:
 +
<syntaxhighlight lang="bash">
 +
ps aux | grep nuke
 +
</syntaxhighlight>
 +
 
 +
Puis lancer:
 +
<syntaxhighlight lang="bash">
 +
gdb -p <PID>
 +
</syntaxhighlight>
 +
 
 +
* ''gdb'' s'initialisera et Nuke s’arrêtera.
 +
* tapez ''continue'' pour que Nuke reprenne son travail.
 +
* Quand Nuke crash, ''gdb'' reprend la main.
 +
* Tapez ''bt'' (pour backtrace) et ainsi voir la liste des fonction et celle ou Nuke plante.
 +
 
 +
Vous aurez quelque hose qui ressemble a ça:
 +
 
 +
<syntaxhighlight lang="bash">
 +
(gdb) c
 +
Continuing.
 +
Program received signal SIGINT, Interrupt.
 +
0x00007f991ca63672 in select () from /lib64/libc.so.6
 +
(gdb) bt
 +
#0  0x00007f991ca63672 in select () from /lib64/libc.so.6
 +
#1  0x0000000001296115 in ?? ()
 +
#2  0x00000000012965bf in ?? ()
 +
#3  0x00000000012976d6 in ?? ()
 +
#4  0x0000000001275457 in ?? ()
 +
#5  0x0000000000714b58 in ?? ()
 +
#6  0x00000000005dabf0 in ?? ()
 +
#7  0x00000000005d846f in ?? ()
 +
#8  0x00000000005d7cbc in ?? ()
 +
#9  0x0000000000b703d8 in ?? ()
 +
#10 0x00007f991a8d2041 in PyEval_EvalFrameEx (f=0x11029010, throwflag=<value optimized out>) at Python/ceval.c:3750
 +
#11 0x00007f991a8d3e91 in PyEval_EvalCodeEx (co=0x20f0b70, globals=<value optimized out>, locals=<value optimized out>, args=0xb, argcount=1, kws=0x10a645d8, kwcount=10, defs=0x2125770, defcount=8, closure=0x0) at Python/ceval.c:3000
 +
#12 0x00007f991a8d2289 in PyEval_EvalFrameEx (f=0x10a64300, throwflag=<value optimized out>) at Python/ceval.c:3846
 +
#13 0x00007f991a8d2780 in PyEval_EvalFrameEx (f=0x21629d0, throwflag=<value optimized out>) at Python/ceval.c:3836
 +
#14 0x00007f991a8d3e91 in PyEval_EvalCodeEx (co=0x2125300, globals=<value optimized out>, locals=<value optimized out>, args=0xe, argcount=0, kws=0x2162870, kwcount=14, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3000
 +
#15 0x00007f991a8d2289 in PyEval_EvalFrameEx (f=0x21626f0, throwflag=<value optimized out>) at Python/ceval.c:3846
 +
#16 0x00007f991a8d3e91 in PyEval_EvalCodeEx (co=0x213aaf8, globals=<value optimized out>, locals=<value optimized out>, args=0x0, argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3000
 +
#17 0x00007f991a8d4182 in PyEval_EvalCode (co=0x7, globals=0x1da48e8, locals=0x1da4b80) at Python/ceval.c:541
 +
#18 0x00007f991a8f7d51 in PyRun_FileExFlags (fp=0x1ebee90, filename=0x7fffb1933004 "/tmp/InKExe-20111007-61dtGE/nukeRenderer.py", start=<value optimized out>, globals=0x1e07dc0, locals=0x1e07dc0, closeit=1, flags=0x0) at Python/pythonrun.c:1339
 +
#19 0x0000000000b653bc in scriptFile(char const*) ()
 +
#20 0x0000000000b8b202 in ?? ()
 +
#21 0x00007f991c9b5586 in __libc_start_main () from /lib64/libc.so.6
 +
#22 0x00000000004a767a in ?? ()
 +
#23 0x00007fffb1930818 in ?? ()
 +
#24 0x000000000000001c in ?? ()
 +
#25 0x0000000000000006 in ?? ()
 +
</syntaxhighlight>
 +
 
 +
Ici, Nuke c'est planté sur la fonction ''select()'' de la ''libc.so.6''.
 +
 
 +
Plus de commandes ici: [http://brouits.free.fr/doc/gdb_howto.html Utiliser le debuger GDB]
 +
 
 +
== Messages d'erreur connus ==
 +
 
 +
Voici une liste des message d'erreur et leur significations/solutions.
 +
 
 +
=== "ValueError: not attached to a node" ===
 +
 
 +
Ce message:
 +
<syntaxhighlight lang="bash">
 +
"ValueError: not attached to a node"
 +
</syntaxhighlight>
 +
Arrive souvent quand on appel un node supprimé (plus haut dans le script la plupart du temps).
 +
 
 +
== Divers ==
 +
 
 +
==== Lancer nuke en mode terminal (pas de GUI) ====
 +
<syntaxhighlight lang="bash">
 +
nuke -t
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Afficher les plugin path:
+
==== Faire un print dans le terminal qui a lancé Nuke ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
nuke.pluginPath()
+
nuke.tprint("Hello World!")
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Vider le cache:
+
==== Vider le cache mémoire ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.memory("free")
 
nuke.memory("free")
Ligne 288 : Ligne 453 :
 
[[Fichier:Nuke cache clearBuffers.png]]
 
[[Fichier:Nuke cache clearBuffers.png]]
  
Savoir si le script s'execute en mode terminal ou en mode GUI:
+
==== Vider le cache disque ====
 +
<syntaxhighlight lang="python">
 +
nuke.clearDiskCache()
 +
</syntaxhighlight>
 +
Reviens a cliquer sur ''Clear Disk Cache''.
 +
 
 +
==== Savoir si le script s’exécute en mode terminal ou en mode GUI ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.GUI
 
nuke.GUI
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Connaitre le nombre de CPU:
+
==== Connaître le nombre de CPU ====
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
nuke.NUM_CPUS
 
nuke.NUM_CPUS
Ligne 304 : Ligne 475 :
  
 
[[Category:Nuke]]
 
[[Category:Nuke]]
 +
[[Category:Python]]

Version actuelle datée du 1 avril 2013 à 15:38

Cette page a pour but de donner des exemples simples des commandes python les plus utilisées dans Nuke

Sommaire

Préférences

Modifier les préférences de Nuke

nuke.toNode('preferences')['CacheLimit'].value()
nuke.toNode('preferences')['CacheLimit'].setValue(75)

Le nom du knob peut être obtenu en plaçant le curseur sur dessus:

Nuke preferences cachelimit.png

Modifier les préférences du projet

nuke.root()['first_frame'].value()	# renvoi le numéro de la frame
nuke.root()['first_frame'].setValue(101)

Les formats

Les formats contiennent la résolution et la taille des pixels.

Obtenir la liste des formats disponibles

nuke.formats()

Modifier le format du projet

nuke.root()['format'].value().name()	# renvoi le nom du format
nuke.root()['format'].value().setName("nomDuFormat")

Et bien d'autres options

nuke.root()['format'].value().width()
nuke.root()['format'].value().height()

Obtenir le format d'un node

nodeFormat = muNode.format()
nodeFormat.name()	# renvoi le nom du format de l'image en entrée.
nodeFormat.width()	# renvoi la largeur, en pixel, de l'image en entrée.
nodeFormat.height()	# renvoi la heuteur, en pixel, de l'image en entrée.

Faire un echo des commandes Python lancé par Nuke (à la Maya)

Aller dans:

  • Edit/Preferences
  • Onglet Script Editor
  • Cocher echo python commands to output window

Les nodes

Voir la doc de la classe Node pour plus d'informations:

Créer un node

Deux méthodes pour faire la même chose:

nuke.createNode("Blur")
nuke.nodes.Blur()

D’après la doc officielle:

  • La première version créé un node comme si l'utilisateur l'avait créé. En utilisant le "contexte". Exemple: Si un node est sélectionné, le nouveau node sera connecté au premier. Son panel sera affiché, etc...
  • La seconde méthode créé un node "dans le vide". Connecté a rien, pas de comportement particulier, juste un node.

Ne pas ouvrir le panel du node créé:

nuke.createNode("Blur", inpanel=False )

Setter les knobs d'un node a la création:

nuke.nodes.Blur(size=10)

Supprimer un node

nuke.delete(myNode)

La sélection

Éviter:

nuke.selectedNode()

Comportement complexe, préférer:

nuke.selectedNodes()

Qui revoit une bête liste dans l'ordre inversé de la sélection.

Savoir si un node est sélectionné

myNode.isSelected()	# True/False

Ajouter/Enlever le node a la sélection

myNode.setSelected(True)

Depuis le projet

Récupérer tout les nodes

nuke.allNodes()	# list tout les nodes du projet en cours
nuke.allNodes("Blur")	# list tout les nodes du projet en cours de class Blur

Récupérer un node depuis son nom

nuke.toNode("Blur1")

Récupérer le nom d'un node

myNode.name()	# renvoit le nom du node "Blur1"
myNode.fullName()	# renvoi le nom complet du node

Récupérer le positionnement d'un node dans le graph

myNode.xpos()
myNode.ypos()
myNode.setXpos(30)
myNode.setYpos(30)

Paramètre des nodes

Lister les dict des attributs d'un node

myNode.knobs()

Méthode de base pour get/set de variable d'un node

myNode.knob("size").value()	# get value
myNode.knob("size").setValue(2)	# set value

Et une autre façon:

myNode["translate"].value()	# get value [2.0, 0.0, 32.0]
myNode["translate"].setValue([1.0, 0.0, 16.0])	# set array value

Ajouter un paramètre a un node

myControl = nuke.Array_Knob("name", "label")	# "name" est simplement le nom du knob et "label" est ce qui sera affiché dans l'UI. Ce dernier est optionnel.
myControl.setTooltip('Mon tooltip')	# Ajoute un tooltip au knob
myNode.addKnob(myControl)

Les différents types de knobs

textControl = nuke.Text_Knob("divider")	# Juste une barre de separation
colorControl = nuke.Color_Knob("color")	# Un knob de couleur
doubleControl = nuke.Double_Knob("value")	# Un knob de valeur a virgule flottante
sliderControl = nuke.WH_Knob("value")	# Un knob de deux valeurs: W et H
myNode.addKnob(textControl)
myNode.addKnob(colorControl)
myNode.addKnob(doubleControl)
myNode.addKnob(sliderControl)

Ajouter un bouton qui exécute du Python:

pyButton = nuke.PyScript_Knob("Do something")
pyButton.setCommand("print 'Toto'")
myNode.addKnob(pyButton)

Les autres type de knob sont disponible dans les sous-classe de la classe Knob.

Certains paramètres peuvent être "exécuté" (comme si on cliquait sur le bouton en fait):

for myNode in nuke.allNodes("Read") :
	myNode["reload"].execute()

Connections des nodes

Toute les connections se font par les index des inputs/output:

myNode.minInputs()	# 3 pour un node de merge: A, B, et Mask
myNode.maxInputs()	# 101 pour un node de merge: A2, B2, etc...
myNode.maxOutputs()	# Pas le nombre de connections, en output, du node mais le nombre d’élément que sort le node (un seul la plupart du temps)
myNode.optionalInput()	# Index de l'input optionnel (souvent le mask). 2 pour le node de merge

La taille du tableau des inputs:

myNode.inputs()	# La taille du tableau des inputs

Si mask (index 2) est connecté, la taille est de 3 (0,1,2).

Si A est connecté, la taille est de... 2 (0,1). (Apparemment, A est la seconde entrée du tableau et B la première... Allez savoir pourquoi...)

Si B est connecté, la taille est de... 1 (Juste 0).

myNode.canSetInput(0, anotherNode)	# Vérifie que la connection de anotherNode sur myNode a l'index 0 est possible
myNode.setInput(0, anotherNode)	# Connecter un node a un autre sur l'index 0 (myNode prend anotherNode en input, anotherNode se connecte a myNode)
myNode.setInput(0, None)	# Déconnecter un input
myNode.connectInput(0, anotherNode)	 # connect l'output de anotherNode a l'input 0 de myNode
myNode.channels()	# ['rgba.red', 'rgba.green', 'rgba.blue', 'rgba.alpha', 'depth.Z']

Lister les dépendances montantes et descendantes

myNode.dependent()	# Renvoi la liste des nodes dépendants (enfant) de myNode
myNode.dependencies()	# Renvoi la liste des nodes dont dépendent myMode (ces parents)

Les metadatas

Lire les metadatas:

node = nuke.toNode("Read1")
print node.metadata()	# un dict de metadata

# Result:
{'exr/displayWindow': [0, 0, 2047, 1555], 'input/width': 2048, 'exr/nuke/camera/vaperture': '18.672', 'input/bitsperchannel': '16-bit half float'...

Source: Reading Metadata.

Label des nodes

On peut modifier le label d'un node (ce qui est affiché dans l'interface, sous le nom du fichier) avec un syntaxe particulière:

[ lindex [split [filename] /] end-1]	# le nom du dossier qui contient l'image ("p099" si "s002/p099/diffuse.0001.exr")
[ lindex [split [filename] /] end-2][ lindex [split [filename] /] end-1]	# Variante du dessus ("s002p099" si "s002/p099/diffuse.0001.exr")
[ lindex [split [lindex [split [knob [topnode].file] .] 0] /] end]	# Le nom du fichier sans l'extension
[date %d]/[date %m]/[date %y]	# Affiche la date de l'image

Le langage utilisé est le tcl.

D'autres commandes utiles ici: Value vs knob command

Animation

Récupérer la valeur d'une animation a une image donnée, pour une vue donnée

myNode["translate"].valueAt(25, view='R')
# Result: [-26.308155060000001, 2.3234429360000002, 72.413200380000006]

On peut ajouter l'index du tableau (ici: 0):

myNode["translate"].valueAt(25, 0, view='R')
# Result: -26.308155060000001

Interface

Liens intéressants:

Menus

Customiser le menu

menuBar = nuke.menu("Nuke")	# La barre de menu principale
myMenu = menuBar.addMenu("&myMenu")	# Ajoute un menu custom
myMenuCommand = myMenu.addCommand("Do Something", "doSomething()")	# Ajoute une commande

mySubMenu = myMenu.addMenu("mySubMenu")	# Ajoute un sous menu a notre menu custom
mySubMenu.addCommand("Do Something", "doSomething()")	# Ajoute une commande

editMenu = menuBar.findItem("&Edit")	# Cherche un menu existant
editMenu.addCommand("Do Something", "doSomething()")	# Et y ajoute une commande
nodeSubMenu = editMenu.findItem("Node")	# Cherche le sous menu "Node"
nodeSubMenu.addSeparator()	# Y ajoute un separator
nodeSubMenu.addCommand("Do Something", "doSomething()")	# Et une commande

Dialog

Une fileDialog, pour les clips. Un seul/plusieurs fichiers

nuke.getClipname( "fileDialogName" )
# Result: '/path/to/my/file'
nuke.getClipname( "fileDialogName", multiple=True )
# Result: [/path/to/my/file1', '/path/to/my/file2', '/path/to/my/file3']

Une fileDialog avec pattern et defaultPath

nuke.getFilename("fileDialogName", pattern="*.png;*.jpeg", default="/path/to/a/file" )

Yes/No dialog

nuke.ask("Ça roule?")	# revoit True/False

Icones

Appliquer une icône à un node

myNode["icon"].setValue("/path/to/an/icon.png")

Autres

Overrider la fonction de création d'un node

def myCreateNode() :
	print "coucou"
nukescripts.create_read = myCreateNode

Désactiver le thumbnail d'un node

myNode["postage_stamp"].setValue(False)

PySide

Des bouts de codes trouvé par ci par la.

Une fenêtre qui reste toujours "devant" Nuke, même si elle n'a plus le focus (ala Maya)

Trouvé sur la mailing list nuke-python@support.thefoundry.co.uk.

from PySide import QtCore, QtGui

class TestWindow(QtGui.QDialog):
	def __init__(self, parent=QtGui.QApplication.activeWindow()):
		QtGui.QDialog.__init__(self, parent)
		self.hbox=QtGui.QHBoxLayout()
		self.button=QtGui.QPushButton("TEST")
		self.hbox.addWidget(self.button)
		self.setLayout(self.hbox)

tw = TestWindow()
tw.show()

Pour avoir la possibilité de la faire passer "derrière" Nuke il suffit de remplacer:

QtGui.QApplication.activeWindow()

Par:

QtGui.QApplication.desktop()

Dans tout les cas, il faut lui donner un parent. Sans parent, Nuke vous gratifiera d'un Segmentation fault lorsque vous quittez.

Debug

Afficher les plugin path

nuke.pluginPath()

Obtenir des statistiques (performance metrics) sur les nodes calculés

En mode terminal ou GUI, uniquement sous Linux

nuke -P

Afficher tout les callbacks de Nuke dans le terminal

Dans votre .nuke/init.py, ajoutez:

import callbacksTrace

Obtenir un debug des déchargements de la mémoire de Nuke

Lancer le Nuke avec la variable d’environnement NUKE_DEBUG_MEMORY à 1 (voir page 9 de la doc).

Combiné à -P cette option est très interessante.

Connaître l'état de Nuke lors d'un crash

Il faut récupérer le PID de Nuke avec la commande:

ps aux | grep nuke

Puis lancer:

gdb -p <PID>
  • gdb s'initialisera et Nuke s’arrêtera.
  • tapez continue pour que Nuke reprenne son travail.
  • Quand Nuke crash, gdb reprend la main.
  • Tapez bt (pour backtrace) et ainsi voir la liste des fonction et celle ou Nuke plante.

Vous aurez quelque hose qui ressemble a ça:

(gdb) c
Continuing.
Program received signal SIGINT, Interrupt.
0x00007f991ca63672 in select () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f991ca63672 in select () from /lib64/libc.so.6
#1  0x0000000001296115 in ?? ()
#2  0x00000000012965bf in ?? ()
#3  0x00000000012976d6 in ?? ()
#4  0x0000000001275457 in ?? ()
#5  0x0000000000714b58 in ?? ()
#6  0x00000000005dabf0 in ?? ()
#7  0x00000000005d846f in ?? ()
#8  0x00000000005d7cbc in ?? ()
#9  0x0000000000b703d8 in ?? ()
#10 0x00007f991a8d2041 in PyEval_EvalFrameEx (f=0x11029010, throwflag=<value optimized out>) at Python/ceval.c:3750
#11 0x00007f991a8d3e91 in PyEval_EvalCodeEx (co=0x20f0b70, globals=<value optimized out>, locals=<value optimized out>, args=0xb, argcount=1, kws=0x10a645d8, kwcount=10, defs=0x2125770, defcount=8, closure=0x0) at Python/ceval.c:3000
#12 0x00007f991a8d2289 in PyEval_EvalFrameEx (f=0x10a64300, throwflag=<value optimized out>) at Python/ceval.c:3846
#13 0x00007f991a8d2780 in PyEval_EvalFrameEx (f=0x21629d0, throwflag=<value optimized out>) at Python/ceval.c:3836
#14 0x00007f991a8d3e91 in PyEval_EvalCodeEx (co=0x2125300, globals=<value optimized out>, locals=<value optimized out>, args=0xe, argcount=0, kws=0x2162870, kwcount=14, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3000
#15 0x00007f991a8d2289 in PyEval_EvalFrameEx (f=0x21626f0, throwflag=<value optimized out>) at Python/ceval.c:3846
#16 0x00007f991a8d3e91 in PyEval_EvalCodeEx (co=0x213aaf8, globals=<value optimized out>, locals=<value optimized out>, args=0x0, argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3000
#17 0x00007f991a8d4182 in PyEval_EvalCode (co=0x7, globals=0x1da48e8, locals=0x1da4b80) at Python/ceval.c:541
#18 0x00007f991a8f7d51 in PyRun_FileExFlags (fp=0x1ebee90, filename=0x7fffb1933004 "/tmp/InKExe-20111007-61dtGE/nukeRenderer.py", start=<value optimized out>, globals=0x1e07dc0, locals=0x1e07dc0, closeit=1, flags=0x0) at Python/pythonrun.c:1339
#19 0x0000000000b653bc in scriptFile(char const*) ()
#20 0x0000000000b8b202 in ?? ()
#21 0x00007f991c9b5586 in __libc_start_main () from /lib64/libc.so.6
#22 0x00000000004a767a in ?? ()
#23 0x00007fffb1930818 in ?? ()
#24 0x000000000000001c in ?? ()
#25 0x0000000000000006 in ?? ()

Ici, Nuke c'est planté sur la fonction select() de la libc.so.6.

Plus de commandes ici: Utiliser le debuger GDB

Messages d'erreur connus

Voici une liste des message d'erreur et leur significations/solutions.

"ValueError: not attached to a node"

Ce message:

"ValueError: not attached to a node"

Arrive souvent quand on appel un node supprimé (plus haut dans le script la plupart du temps).

Divers

Lancer nuke en mode terminal (pas de GUI)

nuke -t

Faire un print dans le terminal qui a lancé Nuke

nuke.tprint("Hello World!")

Vider le cache mémoire

nuke.memory("free")

Reviens a cliquer sur Clear Buffers F12:

Nuke cache clearBuffers.png

Vider le cache disque

nuke.clearDiskCache()

Reviens a cliquer sur Clear Disk Cache.

Savoir si le script s’exécute en mode terminal ou en mode GUI

nuke.GUI

Connaître le nombre de CPU

nuke.NUM_CPUS

Pour une liste complète:

help(nuke)