Tutoriel sur les add-ons¶
Audience visée¶
Ce tutoriel est conçu pour aider les artistes techniciens ou les développeurs à apprendre à étendre Blender. Une compréhension des bases de Python est exigée de ceux qui mettent en œuvre ce tutoriel.
Prérequis¶
Avant de poursuivre ce tutoriel, vous devriez…
Avoir une connaissance des bases de travail dans Blender.
Savoir comment lancer un script dans l’Éditeur de texte de Blender.
Avoir une compréhension des types de primitives de Python (int, boolean, string, list, tuple, dictionary, et set).
Avoir une connaissance du concept des modules Python.
Avoir une compréhension de base des classes (orientation objet) dans Python.
Lectures suggérées avant de commencer ce tutoriel.
Dive Into Python sections (1, 2, 3, 4, et 7).
:ref:`Blender API Quickstart <https://docs.blender.org/api/blender_python_api_current/info_quickstart.html>`__ pour se familiariser avec les bases de Blender/Python.
Pour mieux trouver des solutions à tout message d’erreur qu’envoie Python pendant l’écriture des scripts, vous lancez Blender depuis un terminal. Voir :ref:`Utilisation du Terminal <https://docs.blender.org/api/blender_python_api_current/info_tips_and_tricks.html#use-the-terminal>`__.
Liens de documentation¶
Pendant le parcours de ce tutoriel, il se peut que vous vouliez étudier notre documentation de référence.
Blender/Python API Overview: ce document est plutôt détaillé mais utile si vous voulez mieux connaître un sujet.
bpy.context
API reference – Il est pratique d’avoir une liste d’éléments disponibles sur lesquels votre script peut opérer.bpy.types.Operator
– Les add-ons suivants définissent des opérateurs, ces docs donnent des détails et plus d’exemples d’opérateurs.
Qu’est-ce qu’un add-on ?¶
Un add-on est un module Python avec quelques exigences supplémentaires, ainsi Blender peut l’afficher dans une liste avec des informations utiles.
En guise d’exemple, voici l’add-on le plus simple possible
bl_info = {
"name": "My Test Add-on",
"blender": (2, 80, 0),
"category": "Object",
}
def register():
print("Hello World")
def unregister():
print("Goodbye World")
bl_info
is a dictionary containing add-on metadata such as the title, version and author to be displayed in the Preferences add-on list. It also specifies the minimum Blender version required to run the script; older versions won’t display the add-on in the list.
register
est une fonction qui se lance seulement une fois l’add-on activé, ce qui signifie que le module peut être chargé sans activation de l’add-on.
unregister
est une fonction pour décharger tout ce qui a été installé par
register
, celle-ci est appelée quand l’add-on est désactivé.
Notez que cet add-on ne fait rien concernant Blender (le module bpy
n’est pas importé par exemple).
Ceci est un exemple artificiel d’un add-on qui sert à illustrer le fait que les exigences de base d’un add-on sont simples.
Un add-on typiquement enregistrera des opérateurs, des panneaux, des éléments de menu, etc, mais il convient de noter que n’importe quel script peut faire cela, quand il a été exécuté depuis l’éditeur texte ou même depuis la console interactive – il y a intrinsèquement aucune différence avec un add-on qui s’autorise à s’intégrer dans Blender, une telle fonctionnalité est simplement offerte par le module bpy
pour que n’importe quel script puisse y accéder.
Aussi un add-on est simplement une manière d’encapsuler un module Python de manière à ce qu’un utilisateur puisse aisément l’utiliser.
Note
L’exécution de ce script dans l’éditeur texte n’affichera rien, pour voir le résultat il doit être installé via les Preferences. Des messages seront affichés à son activation et à son désactivation.
Votre premier add-on¶
L’add-on le plus simple possible ci-dessus est utile comme exemple mais pas plus. L’add-on suivant est simple mais montre comment intégrer un script dans Blender en utilisant un Operator
qui est la manière typique de définir un outil accessible depuis les menus, boutons et raccourcis clavier.
Pour le premier exemple, nous allons écrire un script qui déplace simplement tous les objets dans une scène.
Écrire le script¶
Ajoutez le script suivant à l’éditeur de texte de Blender
import bpy
scene = bpy.context.scene
for obj in scene.objects:
obj.location.x += 1.0
Cliquez sur le bouton Run Script, tous les objets dans la scène active sont déplacés de 1.0 nité.
Écrire l’add-on (simple)¶
Cet add-on prend le corps du script ci-dessus, et l’ajoute à la fonction execute()
d’un opérateur.
bl_info = {
"name": "Move X Axis",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
class ObjectMoveX(bpy.types.Operator):
"""My Object Moving Script""" # Use this as a tooltip for menu items and buttons.
bl_idname = "object.move_x" # Unique identifier for buttons and menu items to reference.
bl_label = "Move X by One" # Display name in the interface.
bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
def execute(self, context): # execute() is called when running the operator.
# The original script
scene = context.scene
for obj in scene.objects:
obj.location.x += 1.0
return {'FINISHED'} # Lets Blender know the operator finished successfully.
def register():
bpy.utils.register_class(ObjectMoveX)
def unregister():
bpy.utils.unregister_class(ObjectMoveX)
# This allows you to run the script directly from Blender's Text editor
# to test the add-on without having to install it.
if __name__ == "__main__":
register()
Note
bl_info
est réparti entre plusieurs lignes. C’est simplement une convention de style pour ajouter plus facilement des éléments.
Note
Plutôt que d’utiliser``bpy.context.scene``, nous utilisons l’argument context.scene
passé à``execute()``. Dans la plupart des cas, ceux-ci seront les mêmes. Cependant, dans certains cas, un contexte personnalisé sera passé aux opérateurs aussi les auteurs de scripts devraient préférer l’argument context
passé aux opérateurs.
Pour tester le script, vous pouvez le copier et le coller dans l’éditeur Texte de Blender et le lancer. Ceci va exécuter le script directement et appeler register immédiatement.
Cependant le lancement du script ne va pas déplacer les objets. Pour cela, vous devez exécuter l’opérateur nouvellement enregistré.
Faites cela en pressant F3 pour afficher le menu operator search et tapez « Move X by One » (le bl_label
), puis Entrée.
Les objets devraient se déplacer comme auparavant.
Gardez cet add-on ouvert dans Blender pour la prochaine étape - installer.
Installer l’add-on¶
Une fois que vous avez votre add-on dans l’Éditeur de texte de Blender, vous allez souhaiter l’installer de sorte qu’il puisse être activé dans les Preferences pour se lancer au démarrage.
Même si l’add-on ci-dessus est un test, parcourons néanmoins les étapes et ainsi vous saurez comment faire pour plus tard.
To install the Blender text as an add-on, you will first have to save it on drive. Take care to obey the naming
restrictions that apply to Python modules and end with a .py
extension.
Once the file is on drive, you can install it as you would for an add-on downloaded online.
Ouvrez le
et sélectionnez le fichier.À présent l’add-on sera listé et vous pourrez l’activer en pressant la case à cocher, si vous voulez l’activer au redémarrage, pressez Save as Default. L’opérateur peut être lancé de la même manière que celle décrite dans la section précédente.
When the add-on is enabled, Blender executes the code and runs the register()
function.
When the add-on is disabled, Blender runs the unregister()
function.
Note
La destination d’un add-on dépend de votre configuration de Blender. Pendant l’installation d’un add-on les chemins de la source et de la destination sont affichés sur la console. Vous pouvez aussi trouver les emplacements des chemins de l’add-on en lançant ceci dans la console Python.
import addon_utils
print(addon_utils.paths())
Plus sur ce sujet ici structure des dossiers.
Votre second add-on¶
Pour notre second add-on, nous nous focaliserons sur l’instanciation d’objet – ceci est – pour faire des copies liées d’un objet d’une façon semblable à ce que vous avez pu voir avec le modificateur Array.
Écrire le script¶
Comme précédemment, d’abord nous allons commencer par un script, le développer, puis le convertir en un add-on.
import bpy
from bpy import context
# Get the current scene
scene = context.scene
# Get the 3D cursor location
cursor = scene.cursor.location
# Get the active object (assume we have one)
obj = context.active_object
# Now make a copy of the object
obj_new = obj.copy()
# The new object has to be added to a collection in the scene
scene.collection.objects.link(obj_new)
# Now we can place the object
obj_new.location = cursor
Maintenant essayons de copier ce script dans Blender et le lancer sur le Cube par défaut. Assurez-vous que vous avez déplacé le curseur 3D avant le lancement, étant donné que la copie va apparaître à l’emplacement du curseur.
Après le lancement, notez que lorsque vous passez en Mode Édition pour modifier le Cube – toutes les copies changent. Dans Blender, ce point est connu comme Copies liées.
Ensuite nous allons faire cela dans une boucle, pour faire un tableau (array) d’objets entre l’objet actif et le curseur.
import bpy
from bpy import context
scene = context.scene
cursor = scene.cursor.location
obj = context.active_object
# Use a fixed value for now, eventually make this user adjustable
total = 10
# Add 'total' objects into the scene
for i in range(total):
obj_new = obj.copy()
scene.collection.objects.link(obj_new)
# Now place the object in between the cursor
# and the active object based on 'i'
factor = i / total
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
Essayez de lancer ce script avec l’objet actif et le curseur à distance l’un de l’autre pour voir le résultat.
Avec ce script vous allez remarquer que nous sommes en train de faire des maths avec la position de l’objet et le curseur, ceci fonctionne car les deux sont des instances 3D de mathutils.Vector
, une classe pratique fournie par le module mathutils
qui permet la multiplication des vecteurs par de nombres et des matrices.
Si vous êtes intéressé par ce point, lisez mathutils.Vector
– il y a beaucoup de fonctions utilitaires pratiques telles que l’obtention de l’angle entre deux vecteurs, le produit vectoriel, le produit scalaire ainsi que des fonctions plus avancées dans mathutils.geometry
telles que l’interpolation de courbe de Bézier et l’intersection rayon/triangle.
Pour l’instant nous allons nous focaliser à faire de ce script un add-on, mais il est bon de savoir que ce module de math 3D est disponible et peut vous aider avec une fonctionnalité plus avancée plus tard.
Écrire l’add-on¶
La première étape est de convertir le script tel quel en un add-on
bl_info = {
"name": "Cursor Array",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
class ObjectCursorArray(bpy.types.Operator):
"""Object Cursor Array"""
bl_idname = "object.cursor_array"
bl_label = "Cursor Array"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scene = context.scene
cursor = scene.cursor.location
obj = context.active_object
total = 10
for i in range(total):
obj_new = obj.copy()
scene.collection.objects.link(obj_new)
factor = i / total
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
return {'FINISHED'}
def register():
bpy.utils.register_class(ObjectCursorArray)
def unregister():
bpy.utils.unregister_class(ObjectCursorArray)
if __name__ == "__main__":
register()
Tout ici a été couvert dans les étapes précédentes, il se peut que vous vouliez encore essayer de lancer l’add-on et considérer ce qui pourrait être fait pour le rendre plus utile.
Les deux choses les plus évidentes qui manquent sont – avoir le total fixé à 10, et avoir accès à l’opérateur avec Recherche d’opérateur n’est pas très pratique.
Ces deux ajouts sont expliqués ci-après, avec le script final après.
Propriété d’opérateur¶
Il y a une diversité de types de propriétés qui sont utilisés pour les réglages d’outils, les types de propriété habituels comprennent : int, float, vector, color, boolean et string.
Ces propriétés sont gérées différemment des attributs de classe Python typiques parce que Blender a besoin de les afficher dans l’interface, d’enregistrer leurs réglages dans les configurations de clavier et de conserver les réglages pour une réutilisation.
Bien que ceci soit géré de manière clairement Pythonique, soyez conscient que vous êtes en fait en train de définir des réglages d’outils qui sont chargés dans Blender et accessibles par d’autres parties de Blender, en dehors de python.
Pour nous passer du littéral 10 pour total
, nous allons utiliser une propriété d’opérateur. Les propriétés d’opérateur sont définies via le module bpy.props, ceci est ajouté au corps de la classe:
# moved assignment from execute() to the body of the class...
total: bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
# and this is accessed on the class
# instance within the execute() function as...
self.total
Ces propriétés de bpy.props
sont gérées spécialement par Blender quand la classe est enregistrée de sorte qu’elles s’affichent comme des boutons dans l’interface utilisateur. Il y a un grand nombre d’arguments que vous pouvez passer aux propriétés pour définir des limites, modifier les valeurs par défaut et afficher une info-bulle.
Voir aussi
bpy.props.IntProperty
Ce document n’entre pas dans les détails sur l’utilisation d’autres types de propriétés. Cependant le lien ci-dessus comprend des exemples plus avancés d’utilisation de propriété .
Configuration de clavier¶
Dans Blender, les add-ons ont leur propre configuration de clavier de façon à ne pas interférer avec les configurations de clavier intégrées de Blender.
In the example below, a new object mode bpy.types.KeyMap
is added,
then a bpy.types.KeyMapItem
is added to the keymap which references
our newly added operator, using Shift-Ctrl-T as the key shortcut to activate it.
# store keymaps here to access after registration
addon_keymaps = []
def register():
# handle the keymap
wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'T', 'PRESS', ctrl=True, shift=True)
kmi.properties.total = 4
addon_keymaps.append((km, kmi))
def unregister():
# handle the keymap
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
Remarquez comment l’élément de configuration de clavier peut avoir un réglage total
différent de celui par défaut défini par l’opérateur. Ceci vous permet d’avoir de multiples clés d’accès au même opérateur avec des réglages différents.
Note
Alors que Shift-Ctrl-T n’est pas une touche de raccourci de Blender par défaut, il est difficile de s’assurer que les add-ons ne vont pas remplacer leurs configurations de touches de clavier respectives. Au moins soyez attentifs à l’assignation des touches de sorte qu’elles ne rentrent pas en conflit avec une fonctionnalité importante dans Blender.
Pour la documentation de l’API sur les fonctions listées ci-dessus, voir :
bpy.types.KeyMaps.new
,bpy.types.KeyMapItems.new
,
En les combinant tous ensemble¶
bl_info = {
"name": "Cursor Array",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
class ObjectCursorArray(bpy.types.Operator):
"""Object Cursor Array"""
bl_idname = "object.cursor_array"
bl_label = "Cursor Array"
bl_options = {'REGISTER', 'UNDO'}
total: bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
def execute(self, context):
scene = context.scene
cursor = scene.cursor.location
obj = context.active_object
for i in range(self.total):
obj_new = obj.copy()
scene.collection.objects.link(obj_new)
factor = i / self.total
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
return {'FINISHED'}
def menu_func(self, context):
self.layout.operator(ObjectCursorArray.bl_idname)
# store keymaps here to access after registration
addon_keymaps = []
def register():
bpy.utils.register_class(ObjectCursorArray)
bpy.types.VIEW3D_MT_object.append(menu_func)
# handle the keymap
wm = bpy.context.window_manager
# Note that in background mode (no GUI available), keyconfigs are not available either,
# so we have to check this to avoid nasty errors in background case.
kc = wm.keyconfigs.addon
if kc:
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'T', 'PRESS', ctrl=True, shift=True)
kmi.properties.total = 4
addon_keymaps.append((km, kmi))
def unregister():
# Note: when unregistering, it's usually good practice to do it in reverse order you registered.
# Can avoid strange issues like keymap still referring to operators already unregistered...
# handle the keymap
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
bpy.utils.unregister_class(ObjectCursorArray)
bpy.types.VIEW3D_MT_object.remove(menu_func)
if __name__ == "__main__":
register()
Lancer le script (ou enregistrez-le et ajoutez-le aux Preferences comme auparavant) et il apparaîtra dans le menu Object.
Après l’avoir sélectionné dans le menu, vous pouvez choisir combien d’instances du cube vous voulez créer.
Note
L’exécution directe du script à plusieurs reprises va également ajouter le menu à chaque fois. Bien que ce ne soit pas un comportement utile, il n’y a rien à craindre puisque les add-ons ne vont pas enregistrer eux-mêmes plusieurs fois une fois activé via les Preferences.
Conclusions¶
Les add-ons peuvent encapsuler certaines fonctionnalités pour l’écriture d’outils pour améliorer votre flux de travail ou pour écrire des utilitaires pour les autres.
Bien qu’il y ait des limites à ce que Python peut faire dans Blender, il y a certainement beaucoup de choses qui peuvent être réalisées sans avoir à plonger dans le code C/C++ de Blender.
L’exemple du tutoriel est limité, mais montre l’utilisation de l’API Blender dans des tâches courantes que vous pouvez étendre pour écrire vos propres outils.
Lectures recommandées¶
Blender est fourni avec des modèles commentés qui sont accessibles dans l’entête de l’éditeur de texte. Si vous avez des domaines spécifiques dont vous voulez voir le code exemple, c’est un bon point de départ.
Voici quelques sites que vous pourriez vouloir consulter après la lecture de ce manuel.
:ref:`Blender/Python API Overview <https://docs.blender.org/api/blender_python_api_current/info_overview.html>`__– pour plus de détails de fond sur l’intégration Blender/Python.
How to Think Like a Computer Scientist – Très bonnes informations pour ceux qui apprennent encore Python.
Blender Development (Wiki) – Développement de Blender, informations générales et liens utiles.
DevTalk – Forum où les gens posent des questions sur le développement de Python.