From BlenderWiki

Jump to: navigation, search
Blender3D FreeTip.gif
IMPORTANT! Do not update this page!
We have moved the Blender User Manual to a new location. Please do not update this page, as it will be locked soon.

Traduction effectuée d’après cette révision de la version anglaise.

Un exemple fonctionnel de script Python

Maintenant que vous avez vu que Blender est extensible via le scripting Python et que vous avez acquis les bases de la gestion et de l’exécution des scripts, et avant que vous ne vous plongiez dans la documentation de l’API Python, voyons un exemple simple et fonctionnel.

Nous vous proposons un petit script qui produit des polygones. Il fait de fait quelque peu doublon avec l’action Space → Add → Mesh → Circle, mais il créera des polygones “pleins”, pas seulement des contours.

Pour rendre le script simple et complet, il contiendra une interface utilisateur graphique (GUI) totalement écrite avec l’API fournie par Blender.

NdT
J’ai choisi de ne pas traduire les exemples de code, même pas les commentaires ! En effet, j’ai remarqué (dans mes manuels de programmation, par ex.) que cela mène presque toujours à des incohérences : noms de variables traduits dans le commentaire mais pas dans le code lui-même… De plus, je crois qu’il vaut mieux maîtriser un minimum la langue de Shakespeare (ou de Turing, par exemple !) pour se lancer sérieusement dans la programmation… ne serait-ce que parce que (presque) tous les langages (ainsi que les APIs, comme celle de Blender) utilisent l’anglais comme “base”, et que leur documentation est rarement traduite !
Essayez donc d’écrire votre code (noms des fichiers, variables, constantes, fonctions…) et vos commentaires en anglais : c’est la meilleure façon de les rendre accessibles au plus grand nombre… même pour l’interface utilisateur : si vous employez un système d’i18n comme gettext, vous aurez plus de chance de trouver des traducteurs anglais → japonais, que français → japonais, par exemple !


En-tête, importer les modules et définir les variables globales

Les premières 32 lignes de code sont données ci-dessous :

En-tête du script

  1. ######################################################
  2. #
  3. # Demo Script for Blender 2.3 Guide
  4. #
  5. ###################################################S68
  6. # This script generates polygons. It is quite useless
  7. # since you can do polygons with ADD->Mesh->Circle
  8. # but it is a nice complete script example, and the
  9. # polygons are 'filled'
  10. ######################################################
  11.  
  12. ######################################################
  13. # Importing modules
  14. ######################################################
  15.  
  16. import Blender
  17. from Blender import NMesh
  18. from Blender.BGL import *
  19. from Blender.Draw import *
  20.  
  21. import math
  22. from math import *
  23.  
  24. # Polygon Parameters
  25. T_NumberOfSides = Create(3)
  26. T_Radius = Create(1.0)
  27.  
  28. # Events
  29. EVENT_NOEVENT = 1
  30. EVENT_DRAW = 2
  31. EVENT_EXIT = 3

Après les commentaires indispensables décrivant ce que fait le script, il y a (lignes [016-022]) l’importation des modules Python. Blender est le module principal de l’API Python de Blender. NMesh est le module fournissant l’accès aux meshes de Blender, alors que BGL et Draw donnent accès respectivement aux constantes et fonctions OpenGL, et aux fonctions d’interface graphique de Blender.

Le module math offre l’accès aux fonctions mathématiques de Python, mais, puisqu’aussi bien les modules math que os sont inclus dans Blender, vous n’avez pas besoin d’une installation externe de Python pour les utiliser !

Les polygones sont définis par leur nombre de côtés et leur rayon. Les valeurs de ces paramètres sont définies par l’utilisateur via la GUI, donc les lignes [025-026] définissent deux objets “generic button” (“bouton générique”), avec leurs valeurs par défaut.

Pour finir, les objets GUI travaillent avec, et génèrent, des événements (events en anglais). Les identifiants d’événements (events identifiers, ou events ID pour faire court) sont des entiers (inttegers) dont les valeurs – toutes différentes, sauf cas particulier ! – sont définies par le programmeur. Il vaut généralement mieux définir des noms “parlant” pour ces événements, comme cela est fait ici aux lignes [029-031].

Dessiner l’interface graphique

Le code responsable du dessin de la GUI devrait résider dans une fonction draw :

Dessiner la GUI

  1. ######################################################
  2. # GUI drawing
  3. ######################################################
  4. def draw():
  5.         global T_NumberOfSides
  6.         global T_Radius
  7.         global EVENT_NOEVENT,EVENT_DRAW,EVENT_EXIT
  8.  
  9.         ########## Titles
  10.         glClear(GL_COLOR_BUFFER_BIT)
  11.         glRasterPos2d(8, 103)
  12.         Text("Demo Polygon Script")
  13.  
  14.         ######### Parameters GUI Buttons
  15.         glRasterPos2d(8, 83)
  16.         Text("Parameters:")
  17.         T_NumberOfSides = Number("No. of sides: ", EVENT_NOEVENT, 10, 55, 210, 18,
  18.                 T_NumberOfSides.val, 3, 20, "Number of sides of out polygon");
  19.         T_Radius = Slider("Radius: ", EVENT_NOEVENT, 10, 35, 210, 18,
  20.                 T_Radius.val, 0.001, 20.0, 1, "Radius of the polygon");
  21.  
  22.         ######### Draw and Exit Buttons
  23.         Button("Draw",EVENT_DRAW, 10, 10, 80, 18)
  24.         Button("Exit",EVENT_EXIT, 140, 10, 80, 18)

Les lignes [037-039] donnent simplement accès aux variables globales à l’intérieur de cette fonction. Les choses intéressantes commencent aux lignes [042-044]. La fenêtre OpenGL est initialisée, et on place le “curseur” (ou “position courante”, c-à-d la position – dans la fenêtre, depuis le coin inférieur gauche – où sera inséré le prochain élément) en (x=8, y=103). Puis le titre “Demo Polygon Script” est affiché. Une autre ligne de texte est écrite, après déplacement du “curseur” (ligne [047-048]).

Les contrôles pour les paramètres sont ensuite créés. Le premier (lignes [049-050]) est un bouton numérique, exactement comme ceux présents un peu partout dans Blender. Pour la signification de tous les paramètres de ce constructeur (c-à-d la fonction qui construit un objet), voyez la référence de l’API Python de Blender. Pour faire simple, il y a l’étiquette du bouton, l’événement par lui généré, sa position (x, y) et ses dimensions (largeur, hauteur), sa valeur – une variable appartenant à l’objet lui-même –, les valeurs maximales et minimales autorisées, et un texte qui apparaîtra dans l’info-bulle du contrôle. Les lignes [051-052] définissent un bouton numérique avec curseur, avec une syntaxe très semblable. Pour finir, les lignes [055-056] créent deux boutons, un Draw pour créer le polygone, et un Exit, pour quitter.

Gérer les événements

L’interface ne sera pas affichée et ne fonctionnera pas, tant qu’un gestionnaire d’événements approprié ne sera pas écrit et enregistré :

Gérer les événements

  1. def event(evt, val):
  2.         if (evt == QKEY and not val):
  3.                 Exit()
  4.  
  5. def bevent(evt):
  6.         global T_NumberOfSides
  7.         global T_Radius
  8.         global EVENT_NOEVENT,EVENT_DRAW,EVENT_EXIT
  9.  
  10.         ######### Manages GUI events
  11.         if (evt == EVENT_EXIT):
  12.                 Exit()
  13.         elif (evt== EVENT_DRAW):
  14.                 Polygon(T_NumberOfSides.val, T_Radius.val)
  15.                 Blender.Redraw()
  16.  
  17. Register(draw, event, bevent)

Les lignes [058-060] définissent le gestionnaire d’événements clavier, ici il ne répond qu’à la touche Q, par l’arrêt du script (appel à Exit()).

Plus intéressantes sont les lignes [062-072], chargées de gérer les événements de l’interface graphique. À chaque fois qu’un contrôle de la GUI est utilisé, cette fonction est appelée, avec le numéro d’événement défini lors de la création du contrôle. Le cœur de cette fonction est donc une structure “if/elif” (si/sinon), qui effectuera des actions différentes en fonction de l’événement reçu.

Enfin, à la ligne [074], la fonction Register() est appelée. Cela déclenche l’affichage de la GUI, et démarre la “boucle d’événement” (“event loop”).

Manipuler le Mesh

Pour terminer, reste à écrire la fonction principale, celle qui effectue le travail “utile”, qui crée le polygone. Il s’agit d’une manipulation de mesh relativement simple, mais elle montre beaucoup de points importants sur la structure de données interne de Blender :

Fonction principale

  1. ######################################################
  2. # Main Body
  3. ######################################################
  4. def Polygon(NumberOfSides,Radius):
  5.  
  6.         ######### Creates a new mesh
  7.         poly = NMesh.GetRaw()
  8.  
  9.         ######### Populates it of vertices
  10.         for i in range(0,NumberOfSides):
  11.                 phi = 3.141592653589 * 2 * i / NumberOfSides
  12.                 x = Radius * cos(phi)
  13.                 y = Radius * sin(phi)
  14.                 z = 0
  15.  
  16.                 v = NMesh.Vert(x,y,z)
  17.                 poly.verts.append(v)
  18.  
  19.         ######### Adds a new vertex to the center
  20.         v = NMesh.Vert(0.,0.,0.)
  21.         poly.verts.append(v)
  22.  
  23.         ######### Connects the vertices to form faces
  24.         for i in range(0,NumberOfSides):
  25.                 f = NMesh.Face()
  26.                 f.v.append(poly.verts[i])
  27.                 f.v.append(poly.verts[(i+1)%NumberOfSides])
  28.                 f.v.append(poly.verts[NumberOfSides])
  29.                 poly.faces.append(f)
  30.  
  31.         ######### Creates a new Object with the new Mesh
  32.         polyObj = NMesh.PutRaw(poly)
  33.  
  34.         Blender.Redraw()

La première ligne importante est ici la ligne [082]. On y crée un nouvel objet mesh, appelé poly. L’objet mesh est constitué d’une liste de vertices et d’une liste de faces, entre autres choses, mais pour l’instant, les listes de vertices et de faces nous suffiront.

Bien évidemment, le mesh nouvellement créé est vide. La première boucle (lignes [085-092]) calcule la position (x, y, z) de chacun des NumberOfSides vertices nécessaires au contour du polygone. Puisque l’objet est plat et horizontal, on a toujours z=0. La ligne [091] appelle la méthode Vert() du module NMesh pour créer un nouvel objet vertex de coordonnées (x, y, z). Cet objet est ensuite (ligne [092]) ajouté à la liste verts de l’objet mesh poly.

Enfin, aux lignes [095-096], un dernier vertex est ajouté au centre du polygone.

Les lignes [099-104] relient ensuite ces vertices pour créer des faces. Il n’est pas obligatoire de créer tous les vertices avant de s’occuper des faces : vous pouvez parfaitement créer une nouvelle face dès que tous ses vertices le sont.

La ligne [100] crée un nouvel objet face. Un objet face a sa propre liste des vertices v (jusqu’à 4 vertices) qui la définit.

Les lignes [101-103] ajoutent trois vertices à la liste originellement vide f.v. Les vertices concernés sont deux vertices consécutifs du contour du polygone, et le vertex central. Ils doivent être pris dans la liste verts de l’objet mesh.

Et la ligne [104] ajoute la nouvelle face à la liste faces de notre mesh poly.

Conclusion

L’interface de notre exemple.
Le résultat de notre script d’exemple.

Si vous créez un fichier polygon.py contenant le code décrit ci-dessus, le chargez dans une fenêtre Text de Blender, comme vous l’avez appris dans les pages précédentes, et tapez AltP dans cette fenêtre pour l’exécuter, vous verrez le texte disparaître et la fenêtre devenir grise. Dans le coin inférieur gauche, la GUI du script sera affichée (L’interface de notre exemple).

En choisissant, par exemple, 5 vertices et un rayon (radius) de 0.5, puis en cliquant sur Draw, un pentagone apparaîtra sur le plan xy des vues 3D (Le résultat de notre script d’exemple).