Automatiser La Gestion d'Evènements Blender avec Python

Automatiser La Gestion d'Evènements Blender avec Python
⚙️
Les événements Blender vous permettent d'automatiser vos workflows sans ajouter d'étapes supplémentaires pour les artistes.

A render se termine à 2h, personne ne regarde, et la sortie reste dans un dossier temporaire jusqu’à ce que quelqu’un se rappelle de la déplacer. Un artiste exporte un fichier avec le mauvais nom. Une caméra est laissée sur une mauvaise longueur focale avant une livraison client.

Tous ces problèmes s’accumulent. Heureusement, il existe une solution simple à chacun d’eux : l’API Python de Blender vous donne un accès direct aux événements qui pilotent l’application. Vous pouvez écrire du code qui écoute ces événements et agit automatiquement dessus, sans aucune intervention de la part des artistes. D’ici la fin de cet article, vous aurez deux exemples fonctionnels que vous pourrez adapter dans votre propre pipeline.

3 façons d’écouter des événements dans Blender

Blender expose trois mécanismes principaux pour répondre aux événements via son API Python :

  • app.handlers sont des écouteurs passifs qui se déclenchent lorsque Blender effectue une action spécifique : un rendu se termine, un fichier se charge, une frame change. Votre code enregistre une fonction et Blender l’appelle lorsque le moment arrive. L’artiste n’a rien à faire, donc c’est souvent le bon outil pour automatiser des tâches de pipeline en arrière-plan.
  • Les opérateurs modaux sont des écouteurs actifs. Ils prennent en main la boucle d’événements de Blender pour une fenêtre donnée et interceptent tout ce que l’artiste fait en temps réel : clics de souris, frappes clavier, mouvements du curseur, jusqu’à ce que l’opérateur se termine ou soit annulé. C’est le bon outil lorsque vous voulez construire des outils interactifs qui répondent à ce que l’artiste fait physiquement dans la vue.
  • La troisième façon d’écouter les événements, msgbus, vous permet de vous abonner aux changements de propriétés de données spécifiques, comme l’objet actif ou un paramètre de scène. Utile, mais plus limité dans son périmètre. Cet article ne le couvre pas.

Les deux exemples que cet article construit couvrent les besoins les plus courants en automatisation en studio : le premier retire complètement une tâche d’arrière-plan de vos artistes grâce à un handler, et le second remplace un workflow lent et manuel par un seul clic avec un opérateur modal.

1. Auto-Export lors de la fin du rendu

Il existe de nombreux handlers utiles, notamment :

  • render_init — se déclenche lorsqu’un job de rendu démarre
  • render_pre — se déclenche avant que chaque frame ne soit rendue
  • render_post — se déclenche après que chaque frame a été rendue
  • load_pre / load_post — avant/après le chargement d’un fichier .blend
  • save_pre / save_post — avant/après l’enregistrement d’un fichier .blend

Ouvrez Blender et passez à l’espace de travail Scripting depuis la barre d’onglets en haut. Vous verrez la console Python à gauche et l’éditeur de texte à droite. Écrivez votre code dans l’éditeur de texte et lancez-le avec Alt+P.

Vous pouvez aussi utiliser une extension pour conserver le script de façon persistante.

Au lieu de construire un outil complet de pipeline de rendu, nous allons commencer par quelque chose de petit pour comprendre le modèle principal : un handler minimal qui se déclenche au moment où le rendu se termine et écrit un horodatage de confirmation dans un fichier. C’est un bon point de départ pour vérifier que votre handler fonctionne correctement avant de construire une logique de post-rendu plus complexe :

import bpy
from datetime import datetime

@bpy.app.handlers.persistent
def on_render_complete(scene, depsgraph):
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    open("test.txt", "w").write(f"Completed: {timestamp}\n")

bpy.app.handlers.render_complete.append(on_render_complete)

Le décorateur @bpy.app.handlers.persistent conserve le handler enregistré lors du chargement des fichiers, de sorte qu’il survit aux changements de scène pendant une session.

À la fin du rendu, datetime.now() capture l’heure de fin et la met en forme sous la forme d’une chaîne d’horodatage compacte. Cette chaîne est écrite directement dans un chemin codé en dur, en écrasant le fichier à chaque rendu.

Enfin, bpy.app.handlers.render_complete.append enregistre la fonction pour que Blender l’appelle automatiquement lorsqu’un rendu se termine.

Pour tester sans attendre un rendu complet, utilisez Render Single Frame, puis vérifiez que test.txt existe bien au chemin cible et qu’il contient l’horodatage attendu.

Ensuite, vous pouvez étendre le handler pour copier les fichiers de sortie, enregistrer des métadonnées de scène ou déclencher des workflows en aval.

Le modèle est toujours le même que dans l’exemple : définissez une fonction, éventuellement décorez-la avec @bpy.app.handlers.persistent, puis ajoutez-la à la liste pertinente.

2. Opérateurs modaux

app.handlers ne peut pas vous aider lorsque la tâche implique de répondre à ce que l’artiste fait activement dans la vue. Vous avez besoin d’un opérateur modal à la place.

Le cas d’usage ici est un cadrage caméra en un clic : un artiste clique sur un objet et la caméra active se repositionne et se reframe pour une composition standard du studio. Aucun réglage manuel de la caméra et aucune estimation de la longueur focale : pas d’incohérence entre les artistes.

Un opérateur modal est une classe avec deux méthodes clés :

  • invoke() démarre l’opérateur et l’enregistre auprès du gestionnaire de fenêtre.
  • modal() reçoit tous les événements qui surviennent après cela et décide quoi en faire. L’opérateur reste actif et continue à recevoir des événements jusqu’à ce qu’il renvoie FINISHED ou CANCELLED.
import bpy

class AutoFrameOperator(bpy.types.Operator):
    bl_idname = "studio.auto_frame"
    bl_label = "Auto Frame Selected"

    def invoke(self, context, event):
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def modal(self, context, event):
        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            target = context.active_object
            if target:
                self.frame_camera_to(context, target)
            return {'FINISHED'}

        if event.type in {'RIGHTMOUSE', 'ESC'}:
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def frame_camera_to(self, context, target):
        camera = context.scene.camera
        if not camera:
            return
        focal_length = 85
        camera.data.lens = focal_length
        
        print(f"Framed camera on: {target.name}")

def register():
    bpy.utils.register_class(AutoFrameOperator)

def unregister():
    bpy.utils.unregister_class(AutoFrameOperator)

Nous définissons un opérateur Blender appelé AutoFrameOperator, une action réutilisable que Blender expose sous l’ID studio.auto_frame. Une fois déclenché, invoke l’enregistre comme gestionnaire modal, ce qui signifie qu’il reste actif et écoute la saisie de l’utilisateur au lieu de s’exécuter immédiatement.

La méthode modal est la boucle d’événements qui s’exécute à chaque interaction. Un clic gauche récupère l’objet actuellement actif et le transmet à frame_camera_to, puis l’opération se termine. Un clic droit ou Échap annule proprement, et tout le reste maintient l’opérateur en attente.

La valeur de retour RUNNING_MODAL sert à garder l’opérateur vivant et à l’écoute. Tout événement qui ne correspond pas à une condition que vous gérez doit renvoyer RUNNING_MODAL pour que l’opérateur reste actif. Renvoyer PASS_THROUGH à la place indique à Blender de traiter l’événement normalement en plus de le transmettre à votre opérateur : c’est utile lorsque vous voulez que l’artiste puisse encore naviguer dans la vue pendant que l’opérateur tourne.

frame_camera_to contient la logique centrale. Elle récupère la caméra active de la scène et règle sa longueur focale sur 85 mm, bien que le calcul réel pour repositionner la caméra et cadrer correctement l’objet cible ne soit pas implémenté, car il sort du périmètre de cet article.

register et unregister sont des éléments boilerplate standard des extensions Blender qui rendent l’opérateur disponible lorsque le script se charge et le retirent proprement lorsqu’il se décharge.

Pour appeler l’opérateur après avoir installé le script comme extension, nous ouvrons le menu de recherche avec F3 et nous saisissons « Auto Frame Selected ». Pour lier cela à un raccourci, nous pouvons simplement ajouter l’extrait suivant à l’intérieur de la fonction register() :

wm = bpy.context.window_manager
kc = wm.keyconfigs.addon
if kc:
    km = kc.keymaps.new(name='3D View', space_type='VIEW_3D')
    kmi = km.keymap_items.new("studio.auto_frame", type='F', value='PRESS', ctrl=True)

Il est important d’espacer correctement vos raccourcis. Ctrl+F dans la vue 3D n’a pas de liaison par défaut dans Blender, mais vérifiez par rapport à la configuration existante de votre studio avant de déployer. Un conflit de raccourci qui écrase silencieusement une action par défaut de Blender est difficile à diagnostiquer et frustrera vos artistes.

Une règle supplémentaire à suivre : gardez la méthode modal() légère. Un calcul lourd à l’intérieur de modal() s’exécute à chaque événement, ce qui inclut chaque mouvement de souris. Si votre logique de cadrage est coûteuse, déportez-la vers une méthode séparée et ne l’appelez que lorsque l’événement pertinent se déclenche, comme montré plus haut avec frame_camera_to.

Conclusion

Vous avez maintenant deux exemples d’outils qui résolvent des problèmes réels du studio sans ajouter d’étapes au workflow de vos artistes.

Le handler de rendu peut supprimer entièrement un transfert manuel, source d’erreurs, de votre pipeline. Et l’opérateur modal offre aux artistes une manière cohérente, en un clic, de cadrer une caméra selon le standard de votre studio.

Les mêmes schémas s’étendent plus loin. Un handler load_post pourrait imposer des conventions de nommage au moment où un fichier s’ouvre. Un handler depsgraph_update_post pourrait signaler les objets qui ne respectent pas le budget de votre scène. Un handler de fin de rendu peut déclencher une requête HTTP vers un webhook et publier une notification Slack à votre canal de production quand une prise est terminée.

Le système d’événements est déjà là : il vous suffit de commencer à écouter !

📽️
Pour en savoir plus sur le processus d'animation, rejoignez notre communauté Discord ! Nous réunissons plus d'un millier d'experts qui partagent les meilleures pratiques et organisent occasionnellement des événements en personne. Nous serions ravis de vous accueillir ! 😊